@@ -188,6 +188,24 @@ struct ClaimableHTLC {
188188 total_msat : u64 ,
189189}
190190
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+
191209/// A payment identifier used to uniquely identify a payment to LDK.
192210/// (C-not exported) as we just use [u8; 32] directly
193211#[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -722,6 +740,10 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
722740 /// Locked *after* channel_state.
723741 pending_outbound_payments : Mutex < HashMap < PaymentId , PendingOutboundPayment > > ,
724742
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+
725747 /// The set of outbound SCID aliases across all our channels, including unconfirmed channels
726748 /// and some closed channels which reached a usable state prior to being closed. This is used
727749 /// only to avoid duplicates, and is not persisted explicitly to disk, but rebuilt from the
@@ -1586,6 +1608,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15861608 outbound_scid_aliases : Mutex :: new ( HashSet :: new ( ) ) ,
15871609 pending_inbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
15881610 pending_outbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1611+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
15891612
15901613 our_network_key : keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ,
15911614 our_network_pubkey : PublicKey :: from_secret_key ( & secp_ctx, & keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ) ,
@@ -3055,6 +3078,63 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30553078 Ok ( ( ) )
30563079 }
30573080
3081+ /// Fails the intercepted payment indicated by intercept_id. This should really only be called in response
3082+ /// to a PaymentIntercepted event
3083+ pub fn fail_intercepted_payment ( & self , intercept_id : InterceptId ) {
3084+ let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3085+
3086+ let pending_intercept = {
3087+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3088+ pending_intercepts. remove ( & intercept_id)
3089+ } ;
3090+
3091+ if let Some ( _payment) = pending_intercept {
3092+ // TODO: what's best way to fail this? in `process_pending_htlc_forwards` it uses that `fail_forward` macro
3093+ // awkward way could be to just use the forward_intercepted_payment code and pick a random scid
3094+ }
3095+ }
3096+
3097+ /// Attempts to forward an intercepted payment over the provided scid and with the provided amt_to_forward.
3098+ /// Should only really be called in response to a PaymentIntercepted event
3099+ pub fn forward_intercepted_payment ( & self , intercept_id : InterceptId , scid : u64 , amt_to_forward : u64 ) -> Result < ( ) , APIError > {
3100+ let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3101+
3102+ let pending_intercept = {
3103+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3104+ pending_intercepts. remove ( & intercept_id)
3105+ } ;
3106+
3107+ match pending_intercept {
3108+ None => Err ( APIError :: APIMisuseError { err : "Payment with that InterceptId not found" . to_string ( ) } ) ,
3109+ Some ( payment) => {
3110+ match payment {
3111+ HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info, prev_funding_outpoint } => {
3112+
3113+ let routing = match forward_info. routing {
3114+ PendingHTLCRouting :: Forward { onion_packet, .. } => {
3115+ PendingHTLCRouting :: Forward { onion_packet, short_channel_id : scid }
3116+ } ,
3117+ _ => forward_info. routing
3118+ } ;
3119+
3120+ let pending_htlc_info = PendingHTLCInfo {
3121+ amt_to_forward,
3122+ routing,
3123+ ..forward_info
3124+ } ;
3125+
3126+ let mut per_source_pending_forward = vec ! [ ( prev_short_channel_id, prev_funding_outpoint, vec![ ( pending_htlc_info, prev_htlc_id) ] ) ] ;
3127+
3128+ self . forward_htlcs ( & mut per_source_pending_forward) ;
3129+
3130+ Ok ( ( ) )
3131+ } ,
3132+ _ => Err ( APIError :: APIMisuseError { err : "impossible" . to_string ( ) } )
3133+ }
3134+ }
3135+ }
3136+ }
3137+
30583138 /// Processes HTLCs which are pending waiting on random forward delay.
30593139 ///
30603140 /// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -3078,7 +3158,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30783158 for forward_info in pending_forwards. drain ( ..) {
30793159 match forward_info {
30803160 HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
3081- routing, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
3161+ ref routing, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
30823162 prev_funding_outpoint } => {
30833163 macro_rules! fail_forward {
30843164 ( $msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr) => {
@@ -3125,6 +3205,24 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31253205 } ,
31263206 _ => panic ! ( ) ,
31273207 }
3208+ } else if fake_scid:: is_valid_intercept ( & self . fake_scid_rand_bytes , short_chan_id) {
3209+ let intercept_id = InterceptId ( Sha256 :: hash ( & incoming_shared_secret) . into_inner ( ) ) ;
3210+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3211+ match pending_intercepts. entry ( intercept_id) {
3212+ hash_map:: Entry :: Vacant ( entry) => {
3213+ entry. insert ( forward_info) ;
3214+ new_events. push ( events:: Event :: PaymentIntercepted {
3215+ short_channel_id : short_chan_id,
3216+ payment_hash,
3217+ inbound_amount_msats : 0 ,
3218+ expected_outbound_amount_msats : amt_to_forward,
3219+ intercept_id
3220+ } ) ;
3221+ } ,
3222+ hash_map:: Entry :: Occupied ( _) => {
3223+ fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
3224+ }
3225+ }
31283226 } else {
31293227 fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
31303228 }
@@ -5494,6 +5592,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
54945592 inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
54955593 }
54965594
5595+ /// Gets a fake short channel id for use in receiving [intercepted payments]. These fake scids
5596+ /// are used when constructing the route hints for payments intended to be intercepted.
5597+ pub fn get_intercept_scid ( & self ) -> u64 {
5598+ let mut channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
5599+ let best_block = self . best_block . read ( ) . unwrap ( ) ;
5600+ loop {
5601+ let scid_candidate = fake_scid:: Namespace :: Intercept . get_fake_scid ( best_block. height ( ) , & self . genesis_hash , & self . fake_scid_rand_bytes , & self . keys_manager ) ;
5602+ // Ensure the generated scid doesn't conflict with a real channel.
5603+ match channel_state. short_to_id . entry ( scid_candidate) {
5604+ hash_map:: Entry :: Occupied ( _) => continue ,
5605+ hash_map:: Entry :: Vacant ( _) => return scid_candidate
5606+ }
5607+ }
5608+ }
5609+
54975610 /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
54985611 /// are used when constructing the phantom invoice's route hints.
54995612 ///
@@ -7209,6 +7322,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
72097322 inbound_payment_key : expanded_inbound_key,
72107323 pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
72117324 pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
7325+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
72127326
72137327 outbound_scid_aliases : Mutex :: new ( outbound_scid_aliases) ,
72147328 fake_scid_rand_bytes : fake_scid_rand_bytes. unwrap ( ) ,
0 commit comments