@@ -188,6 +188,24 @@ struct ClaimableHTLC {
188
188
total_msat : u64 ,
189
189
}
190
190
191
+ /// An identifier used to uniquely identify an intercepted htlc to LDK.
192
+ /// (C-not exported) as we just use [u8; 32] directly
193
+ #[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
194
+ pub struct InterceptId ( pub [ u8 ; 32 ] ) ;
195
+
196
+ impl Writeable for InterceptId {
197
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
198
+ self . 0 . write ( w)
199
+ }
200
+ }
201
+
202
+ impl Readable for InterceptId {
203
+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
204
+ let buf: [ u8 ; 32 ] = Readable :: read ( r) ?;
205
+ Ok ( InterceptId ( buf) )
206
+ }
207
+ }
208
+
191
209
/// A payment identifier used to uniquely identify a payment to LDK.
192
210
/// (C-not exported) as we just use [u8; 32] directly
193
211
#[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -722,6 +740,10 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
722
740
/// Locked *after* channel_state.
723
741
pending_outbound_payments : Mutex < HashMap < PaymentId , PendingOutboundPayment > > ,
724
742
743
+ /// Storage for HTLCForwardInfo's that have been intercepted and bubbled up to the user.
744
+ /// We hold them here until the user tells us what we should to with them.
745
+ pending_intercepted_payments : Mutex < HashMap < InterceptId , HTLCForwardInfo > > ,
746
+
725
747
/// The set of outbound SCID aliases across all our channels, including unconfirmed channels
726
748
/// and some closed channels which reached a usable state prior to being closed. This is used
727
749
/// only to avoid duplicates, and is not persisted explicitly to disk, but rebuilt from the
@@ -1581,6 +1603,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1581
1603
outbound_scid_aliases : Mutex :: new ( HashSet :: new ( ) ) ,
1582
1604
pending_inbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1583
1605
pending_outbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1606
+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1584
1607
1585
1608
our_network_key : keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ,
1586
1609
our_network_pubkey : PublicKey :: from_secret_key ( & secp_ctx, & keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ) ,
@@ -3011,6 +3034,55 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3011
3034
Ok ( ( ) )
3012
3035
}
3013
3036
3037
+ pub fn fail_intercepted_payment ( & self , intercept_id : InterceptId ) {
3038
+ let pending_intercept = {
3039
+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3040
+ pending_intercepts. remove ( & intercept_id)
3041
+ } ;
3042
+
3043
+ if let Some ( _payment) = pending_intercept {
3044
+ // TODO: what's best way to fail this? in `process_pending_htlc_forwards` it uses that `fail_forward` macro
3045
+ // awkward way could be to just use the forward_intercepted_payment code and pick a random scid
3046
+ }
3047
+ }
3048
+
3049
+ pub fn forward_intercepted_payment ( & self , intercept_id : InterceptId , scid : u64 , amt_to_forward : u64 ) -> Result < ( ) , APIError > {
3050
+ let pending_intercept = {
3051
+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3052
+ pending_intercepts. remove ( & intercept_id)
3053
+ } ;
3054
+
3055
+ match pending_intercept {
3056
+ None => Err ( APIError :: APIMisuseError { err : "Payment with that InterceptId not found" . to_string ( ) } ) ,
3057
+ Some ( payment) => {
3058
+ match payment {
3059
+ HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info, prev_funding_outpoint } => {
3060
+
3061
+ let routing = match forward_info. routing {
3062
+ PendingHTLCRouting :: Forward { onion_packet, .. } => {
3063
+ PendingHTLCRouting :: Forward { onion_packet, short_channel_id : scid }
3064
+ } ,
3065
+ _ => forward_info. routing
3066
+ } ;
3067
+
3068
+ let pending_htlc_info = PendingHTLCInfo {
3069
+ amt_to_forward,
3070
+ routing,
3071
+ ..forward_info
3072
+ } ;
3073
+
3074
+ let mut per_source_pending_forward = vec ! [ ( prev_short_channel_id, prev_funding_outpoint, vec![ ( pending_htlc_info, prev_htlc_id) ] ) ] ;
3075
+
3076
+ self . forward_htlcs ( & mut per_source_pending_forward) ;
3077
+
3078
+ Ok ( ( ) )
3079
+ } ,
3080
+ _ => Err ( APIError :: APIMisuseError { err : "impossible" . to_string ( ) } )
3081
+ }
3082
+ }
3083
+ }
3084
+ }
3085
+
3014
3086
/// Processes HTLCs which are pending waiting on random forward delay.
3015
3087
///
3016
3088
/// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -3034,7 +3106,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3034
3106
for forward_info in pending_forwards. drain ( ..) {
3035
3107
match forward_info {
3036
3108
HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
3037
- routing, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
3109
+ ref routing, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
3038
3110
prev_funding_outpoint } => {
3039
3111
macro_rules! fail_forward {
3040
3112
( $msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr) => {
@@ -3081,6 +3153,24 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3081
3153
} ,
3082
3154
_ => panic ! ( ) ,
3083
3155
}
3156
+ } else if fake_scid:: is_valid_intercept ( & self . fake_scid_rand_bytes , short_chan_id) {
3157
+ let intercept_id = InterceptId ( Sha256 :: hash ( & incoming_shared_secret) . into_inner ( ) ) ;
3158
+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3159
+ match pending_intercepts. entry ( intercept_id) {
3160
+ hash_map:: Entry :: Vacant ( entry) => {
3161
+ entry. insert ( forward_info) ;
3162
+ new_events. push ( events:: Event :: PaymentIntercepted {
3163
+ short_channel_id : short_chan_id,
3164
+ payment_hash,
3165
+ inbound_amount_msats : 0 ,
3166
+ expected_outbound_amount_msats : amt_to_forward,
3167
+ intercept_id
3168
+ } ) ;
3169
+ } ,
3170
+ hash_map:: Entry :: Occupied ( _) => {
3171
+ fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
3172
+ }
3173
+ }
3084
3174
} else {
3085
3175
fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
3086
3176
}
@@ -5432,6 +5522,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
5432
5522
inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
5433
5523
}
5434
5524
5525
+ /// Gets a fake short channel id for use in receiving [intercepted payments]. These fake scids
5526
+ /// are used when constructing the route hints for payments intended to be intercepted.
5527
+ pub fn get_intercept_scid ( & self ) -> u64 {
5528
+ let mut channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
5529
+ let best_block = self . best_block . read ( ) . unwrap ( ) ;
5530
+ loop {
5531
+ let scid_candidate = fake_scid:: Namespace :: Intercept . get_fake_scid ( best_block. height ( ) , & self . genesis_hash , & self . fake_scid_rand_bytes , & self . keys_manager ) ;
5532
+ // Ensure the generated scid doesn't conflict with a real channel.
5533
+ match channel_state. short_to_id . entry ( scid_candidate) {
5534
+ hash_map:: Entry :: Occupied ( _) => continue ,
5535
+ hash_map:: Entry :: Vacant ( _) => return scid_candidate
5536
+ }
5537
+ }
5538
+ }
5539
+
5435
5540
/// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
5436
5541
/// are used when constructing the phantom invoice's route hints.
5437
5542
///
@@ -7140,6 +7245,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
7140
7245
inbound_payment_key : expanded_inbound_key,
7141
7246
pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
7142
7247
pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
7248
+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
7143
7249
7144
7250
outbound_scid_aliases : Mutex :: new ( outbound_scid_aliases) ,
7145
7251
fake_scid_rand_bytes : fake_scid_rand_bytes. unwrap ( ) ,
0 commit comments