@@ -114,6 +114,7 @@ pub(super) struct PendingHTLCInfo {
114114 payment_hash : PaymentHash ,
115115 pub ( super ) amt_to_forward : u64 ,
116116 pub ( super ) outgoing_cltv_value : u32 ,
117+ pub ( super ) amt_incoming : Option < u64 >
117118}
118119
119120#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
@@ -129,6 +130,13 @@ pub(super) enum PendingHTLCStatus {
129130 Fail ( HTLCFailureMsg ) ,
130131}
131132
133+ pub ( super ) struct PendingInterceptedHTLC {
134+ forward_info : PendingHTLCInfo ,
135+ prev_short_channel_id : u64 ,
136+ prev_htlc_id : u64 ,
137+ prev_funding_outpoint : OutPoint ,
138+ }
139+
132140pub ( super ) enum HTLCForwardInfo {
133141 AddHTLC {
134142 forward_info : PendingHTLCInfo ,
@@ -186,6 +194,24 @@ struct ClaimableHTLC {
186194 total_msat : u64 ,
187195}
188196
197+ /// An identifier used to uniquely identify an intercepted htlc to LDK.
198+ /// (C-not exported) as we just use [u8; 32] directly
199+ #[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
200+ pub struct InterceptId ( pub [ u8 ; 32 ] ) ;
201+
202+ impl Writeable for InterceptId {
203+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
204+ self . 0 . write ( w)
205+ }
206+ }
207+
208+ impl Readable for InterceptId {
209+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
210+ let buf: [ u8 ; 32 ] = Readable :: read ( r) ?;
211+ Ok ( InterceptId ( buf) )
212+ }
213+ }
214+
189215/// A payment identifier used to uniquely identify a payment to LDK.
190216/// (C-not exported) as we just use [u8; 32] directly
191217#[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -761,6 +787,9 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
761787 pub ( super ) forward_htlcs : Mutex < HashMap < u64 , Vec < HTLCForwardInfo > > > ,
762788 #[ cfg( not( test) ) ]
763789 forward_htlcs : Mutex < HashMap < u64 , Vec < HTLCForwardInfo > > > ,
790+ /// Storage for PendingInterceptedHTLC's that have been intercepted and bubbled up to the user.
791+ /// We hold them here until the user tells us what we should to with them.
792+ pending_intercepted_payments : Mutex < HashMap < InterceptId , PendingInterceptedHTLC > > ,
764793
765794 /// The set of outbound SCID aliases across all our channels, including unconfirmed channels
766795 /// and some closed channels which reached a usable state prior to being closed. This is used
@@ -1634,6 +1663,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16341663 pending_outbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
16351664 forward_htlcs : Mutex :: new ( HashMap :: new ( ) ) ,
16361665 id_to_peer : Mutex :: new ( HashMap :: new ( ) ) ,
1666+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
16371667
16381668 our_network_key : keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ,
16391669 our_network_pubkey : PublicKey :: from_secret_key ( & secp_ctx, & keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ) ,
@@ -2163,6 +2193,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21632193 payment_hash,
21642194 incoming_shared_secret : shared_secret,
21652195 amt_to_forward : amt_msat,
2196+ amt_incoming : Some ( amt_msat) ,
21662197 outgoing_cltv_value : hop_data. outgoing_cltv_value ,
21672198 } )
21682199 }
@@ -2260,6 +2291,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
22602291 incoming_shared_secret : shared_secret,
22612292 amt_to_forward : next_hop_data. amt_to_forward ,
22622293 outgoing_cltv_value : next_hop_data. outgoing_cltv_value ,
2294+ amt_incoming : Some ( msg. amount_msat )
22632295 } )
22642296 }
22652297 } ;
@@ -3030,6 +3062,66 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30303062 Ok ( ( ) )
30313063 }
30323064
3065+ /// Fails the intercepted payment indicated by intercept_id. This should really only be called in response
3066+ /// to a PaymentIntercepted event
3067+ pub fn fail_intercepted_payment ( & self , intercept_id : InterceptId ) {
3068+ let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3069+
3070+ let pending_intercept = {
3071+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3072+ pending_intercepts. remove ( & intercept_id)
3073+ } ;
3074+
3075+ if let Some ( payment) = pending_intercept {
3076+ if let PendingHTLCRouting :: Forward { short_channel_id, .. } = payment. forward_info . routing {
3077+ let htlc_source = HTLCSource :: PreviousHopData ( HTLCPreviousHopData {
3078+ short_channel_id : payment. prev_short_channel_id ,
3079+ outpoint : payment. prev_funding_outpoint ,
3080+ htlc_id : payment. prev_htlc_id ,
3081+ incoming_packet_shared_secret : payment. forward_info . incoming_shared_secret ,
3082+ phantom_shared_secret : None ,
3083+ } ) ;
3084+
3085+ let failure_reason = HTLCFailReason :: Reason { failure_code : 0x4000 | 10 , data : Vec :: new ( ) } ;
3086+ let destination = HTLCDestination :: UnknownNextHop { requested_forward_scid : short_channel_id } ;
3087+ self . fail_htlc_backwards_internal ( htlc_source, & payment. forward_info . payment_hash , failure_reason, destination) ;
3088+ }
3089+ }
3090+ }
3091+
3092+ /// Attempts to forward an intercepted payment over the provided scid and with the provided amt_to_forward.
3093+ /// Should only really be called in response to a PaymentIntercepted event
3094+ pub fn forward_intercepted_payment ( & self , intercept_id : InterceptId , scid : u64 , amt_to_forward : u64 ) -> Result < ( ) , APIError > {
3095+ let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3096+
3097+ let pending_intercept = {
3098+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3099+ pending_intercepts. remove ( & intercept_id)
3100+ } ;
3101+
3102+ match pending_intercept {
3103+ None => Err ( APIError :: APIMisuseError { err : "Payment with that InterceptId not found" . to_string ( ) } ) ,
3104+ Some ( payment) => {
3105+ let routing = match payment. forward_info . routing {
3106+ PendingHTLCRouting :: Forward { onion_packet, .. } => {
3107+ PendingHTLCRouting :: Forward { onion_packet, short_channel_id : scid }
3108+ } ,
3109+ _ => payment. forward_info . routing
3110+ } ;
3111+
3112+ let pending_htlc_info = PendingHTLCInfo {
3113+ amt_to_forward,
3114+ routing,
3115+ ..payment. forward_info
3116+ } ;
3117+
3118+ let mut per_source_pending_forward = vec ! [ ( payment. prev_short_channel_id, payment. prev_funding_outpoint, vec![ ( pending_htlc_info, payment. prev_htlc_id) ] ) ] ;
3119+ self . forward_htlcs ( & mut per_source_pending_forward) ;
3120+ Ok ( ( ) )
3121+ }
3122+ }
3123+ }
3124+
30333125 /// Processes HTLCs which are pending waiting on random forward delay.
30343126 ///
30353127 /// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -3054,9 +3146,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30543146 None => {
30553147 for forward_info in pending_forwards. drain ( ..) {
30563148 match forward_info {
3057- HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
3058- routing, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
3059- prev_funding_outpoint } => {
3149+ HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info, prev_funding_outpoint } => {
30603150 macro_rules! failure_handler {
30613151 ( $msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr, $next_hop_unknown: expr) => {
30623152 log_info!( self . logger, "Failed to accept/forward incoming HTLC: {}" , $msg) ;
@@ -3065,17 +3155,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30653155 short_channel_id: prev_short_channel_id,
30663156 outpoint: prev_funding_outpoint,
30673157 htlc_id: prev_htlc_id,
3068- incoming_packet_shared_secret: incoming_shared_secret,
3158+ incoming_packet_shared_secret: forward_info . incoming_shared_secret,
30693159 phantom_shared_secret: $phantom_ss,
30703160 } ) ;
30713161
30723162 let reason = if $next_hop_unknown {
30733163 HTLCDestination :: UnknownNextHop { requested_forward_scid: short_chan_id }
30743164 } else {
3075- HTLCDestination :: FailedPayment { payment_hash }
3165+ HTLCDestination :: FailedPayment { payment_hash: forward_info . payment_hash }
30763166 } ;
30773167
3078- failed_forwards. push( ( htlc_source, payment_hash,
3168+ failed_forwards. push( ( htlc_source, forward_info . payment_hash,
30793169 HTLCFailReason :: Reason { failure_code: $err_code, data: $err_data } ,
30803170 reason
30813171 ) ) ;
@@ -3096,11 +3186,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30963186 }
30973187 }
30983188 }
3099- if let PendingHTLCRouting :: Forward { onion_packet, .. } = routing {
3189+ if let PendingHTLCRouting :: Forward { ref onion_packet, .. } = forward_info . routing {
31003190 let phantom_secret_res = self . keys_manager . get_node_secret ( Recipient :: PhantomNode ) ;
31013191 if phantom_secret_res. is_ok ( ) && fake_scid:: is_valid_phantom ( & self . fake_scid_rand_bytes , short_chan_id) {
31023192 let phantom_shared_secret = SharedSecret :: new ( & onion_packet. public_key . unwrap ( ) , & phantom_secret_res. unwrap ( ) ) . secret_bytes ( ) ;
3103- let next_hop = match onion_utils:: decode_next_payment_hop ( phantom_shared_secret, & onion_packet. hop_data , onion_packet. hmac , payment_hash) {
3193+ let next_hop = match onion_utils:: decode_next_payment_hop ( phantom_shared_secret, & onion_packet. hop_data , onion_packet. hmac , forward_info . payment_hash ) {
31043194 Ok ( res) => res,
31053195 Err ( onion_utils:: OnionDecodeErr :: Malformed { err_msg, err_code } ) => {
31063196 let sha256_of_onion = Sha256 :: hash ( & onion_packet. hop_data ) . into_inner ( ) ;
@@ -3116,13 +3206,37 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31163206 } ;
31173207 match next_hop {
31183208 onion_utils:: Hop :: Receive ( hop_data) => {
3119- match self . construct_recv_pending_htlc_info ( hop_data, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value, Some ( phantom_shared_secret) ) {
3209+ match self . construct_recv_pending_htlc_info ( hop_data, forward_info . incoming_shared_secret , forward_info . payment_hash , forward_info . amt_to_forward , forward_info . outgoing_cltv_value , Some ( phantom_shared_secret) ) {
31203210 Ok ( info) => phantom_receives. push ( ( prev_short_channel_id, prev_funding_outpoint, vec ! [ ( info, prev_htlc_id) ] ) ) ,
31213211 Err ( ReceiveError { err_code, err_data, msg } ) => failed_payment ! ( msg, err_code, err_data, Some ( phantom_shared_secret) )
31223212 }
31233213 } ,
31243214 _ => panic ! ( ) ,
31253215 }
3216+ } else if forward_info. amt_incoming . is_some ( ) && fake_scid:: is_valid_intercept ( & self . fake_scid_rand_bytes , short_chan_id) {
3217+ let intercept_id = InterceptId ( Sha256 :: hash ( & forward_info. incoming_shared_secret ) . into_inner ( ) ) ;
3218+ let mut pending_intercepts = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
3219+ match pending_intercepts. entry ( intercept_id) {
3220+ hash_map:: Entry :: Vacant ( entry) => {
3221+ let pending_intercepted_payment = PendingInterceptedHTLC {
3222+ forward_info : forward_info. clone ( ) ,
3223+ prev_short_channel_id,
3224+ prev_htlc_id,
3225+ prev_funding_outpoint,
3226+ } ;
3227+ entry. insert ( pending_intercepted_payment) ;
3228+ new_events. push ( events:: Event :: PaymentIntercepted {
3229+ short_channel_id : short_chan_id,
3230+ payment_hash : forward_info. payment_hash ,
3231+ inbound_amount_msats : forward_info. amt_incoming . unwrap ( ) ,
3232+ expected_outbound_amount_msats : forward_info. amt_to_forward ,
3233+ intercept_id
3234+ } ) ;
3235+ } ,
3236+ hash_map:: Entry :: Occupied ( _) => {
3237+ fail_forward ! ( format!( "Detected duplicate intercepted payment over short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
3238+ }
3239+ }
31263240 } else {
31273241 fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
31283242 }
@@ -3149,8 +3263,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31493263 HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
31503264 routing : PendingHTLCRouting :: Forward {
31513265 onion_packet, ..
3152- } , incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value } ,
3153- prev_funding_outpoint } => {
3266+ } , incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value, .. } ,
3267+ prev_funding_outpoint, .. } => {
31543268 log_trace ! ( self . logger, "Adding HTLC from short id {} with payment_hash {} to channel with short id {} after delay" , prev_short_channel_id, log_bytes!( payment_hash. 0 ) , short_chan_id) ;
31553269 let htlc_source = HTLCSource :: PreviousHopData ( HTLCPreviousHopData {
31563270 short_channel_id : prev_short_channel_id,
@@ -3274,7 +3388,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32743388 match forward_info {
32753389 HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
32763390 routing, incoming_shared_secret, payment_hash, amt_to_forward, .. } ,
3277- prev_funding_outpoint } => {
3391+ prev_funding_outpoint, .. } => {
32783392 let ( cltv_expiry, onion_payload, payment_data, phantom_shared_secret) = match routing {
32793393 PendingHTLCRouting :: Receive { payment_data, incoming_cltv_expiry, phantom_shared_secret } => {
32803394 let _legacy_hop_data = Some ( payment_data. clone ( ) ) ;
@@ -5521,6 +5635,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
55215635 inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
55225636 }
55235637
5638+ /// Gets a fake short channel id for use in receiving [intercepted payments]. These fake scids
5639+ /// are used when constructing the route hints for payments intended to be intercepted.
5640+ pub fn get_intercept_scid ( & self ) -> u64 {
5641+ let mut channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
5642+ let best_block = self . best_block . read ( ) . unwrap ( ) ;
5643+ loop {
5644+ let scid_candidate = fake_scid:: Namespace :: Intercept . get_fake_scid ( best_block. height ( ) , & self . genesis_hash , & self . fake_scid_rand_bytes , & self . keys_manager ) ;
5645+ // Ensure the generated scid doesn't conflict with a real channel.
5646+ match channel_state. short_to_chan_info . entry ( scid_candidate) {
5647+ hash_map:: Entry :: Occupied ( _) => continue ,
5648+ hash_map:: Entry :: Vacant ( _) => return scid_candidate
5649+ }
5650+ }
5651+ }
5652+
55245653 /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
55255654 /// are used when constructing the phantom invoice's route hints.
55265655 ///
@@ -6324,7 +6453,8 @@ impl_writeable_tlv_based!(PendingHTLCInfo, {
63246453 ( 2 , incoming_shared_secret, required) ,
63256454 ( 4 , payment_hash, required) ,
63266455 ( 6 , amt_to_forward, required) ,
6327- ( 8 , outgoing_cltv_value, required)
6456+ ( 8 , outgoing_cltv_value, required) ,
6457+ ( 9 , amt_incoming, option) ,
63286458} ) ;
63296459
63306460
@@ -6567,6 +6697,13 @@ impl_writeable_tlv_based!(PendingInboundPayment, {
65676697 ( 8 , min_value_msat, required) ,
65686698} ) ;
65696699
6700+ impl_writeable_tlv_based ! ( PendingInterceptedHTLC , {
6701+ ( 0 , forward_info, required) ,
6702+ ( 2 , prev_short_channel_id, required) ,
6703+ ( 4 , prev_htlc_id, required) ,
6704+ ( 6 , prev_funding_outpoint, required)
6705+ } ) ;
6706+
65706707impl_writeable_tlv_based_enum_upgradable ! ( PendingOutboundPayment ,
65716708 ( 0 , Legacy ) => {
65726709 ( 0 , session_privs, required) ,
@@ -6661,6 +6798,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
66616798
66626799 let pending_inbound_payments = self . pending_inbound_payments . lock ( ) . unwrap ( ) ;
66636800 let pending_outbound_payments = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
6801+ let pending_intercepted_payments = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
6802+
66646803 let events = self . pending_events . lock ( ) . unwrap ( ) ;
66656804 ( events. len ( ) as u64 ) . write ( writer) ?;
66666805 for event in events. iter ( ) {
@@ -6732,6 +6871,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
67326871 ( 11 , self . probing_cookie_secret, required) ,
67336872 } ) ;
67346873
6874+ ( pending_intercepted_payments. len ( ) as u64 ) . write ( writer) ?;
6875+ for ( intercept_id, pending_intercepted_payment) in pending_intercepted_payments. iter ( ) {
6876+ intercept_id. write ( writer) ?;
6877+ pending_intercepted_payment. write ( writer) ?;
6878+ }
6879+
67356880 Ok ( ( ) )
67366881 }
67376882}
@@ -7032,14 +7177,23 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
70327177 let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
70337178 let mut probing_cookie_secret: Option < [ u8 ; 32 ] > = None ;
70347179 let mut claimable_htlc_purposes = None ;
7035- read_tlv_fields ! ( reader, {
7180+ read_tlv_fields ! ( reader. by_ref ( ) , {
70367181 ( 1 , pending_outbound_payments_no_retry, option) ,
70377182 ( 3 , pending_outbound_payments, option) ,
70387183 ( 5 , received_network_pubkey, option) ,
70397184 ( 7 , fake_scid_rand_bytes, option) ,
70407185 ( 9 , claimable_htlc_purposes, vec_type) ,
70417186 ( 11 , probing_cookie_secret, option) ,
70427187 } ) ;
7188+
7189+ let pending_intercepted_payment_count: u64 = Readable :: read ( reader) ?;
7190+ let mut pending_intercepted_payments: HashMap < InterceptId , PendingInterceptedHTLC > = HashMap :: with_capacity ( cmp:: min ( pending_intercepted_payment_count as usize , MAX_ALLOC_SIZE /( 3 * 32 ) ) ) ;
7191+ for _ in 0 ..pending_intercepted_payment_count {
7192+ if pending_intercepted_payments. insert ( Readable :: read ( reader) ?, Readable :: read ( reader) ?) . is_some ( ) {
7193+ return Err ( DecodeError :: InvalidValue ) ;
7194+ }
7195+ }
7196+
70437197 if fake_scid_rand_bytes. is_none ( ) {
70447198 fake_scid_rand_bytes = Some ( args. keys_manager . get_secure_random_bytes ( ) ) ;
70457199 }
@@ -7250,6 +7404,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
72507404 inbound_payment_key : expanded_inbound_key,
72517405 pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
72527406 pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
7407+ pending_intercepted_payments : Mutex :: new ( pending_intercepted_payments) ,
72537408
72547409 forward_htlcs : Mutex :: new ( forward_htlcs) ,
72557410 outbound_scid_aliases : Mutex :: new ( outbound_scid_aliases) ,
0 commit comments