@@ -114,6 +114,7 @@ pub(super) struct PendingHTLCInfo {
114
114
payment_hash : PaymentHash ,
115
115
pub ( super ) amt_to_forward : u64 ,
116
116
pub ( super ) outgoing_cltv_value : u32 ,
117
+ pub ( super ) amt_incoming : Option < u64 >
117
118
}
118
119
119
120
#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
@@ -129,6 +130,13 @@ pub(super) enum PendingHTLCStatus {
129
130
Fail ( HTLCFailureMsg ) ,
130
131
}
131
132
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
+
132
140
pub ( super ) enum HTLCForwardInfo {
133
141
AddHTLC {
134
142
forward_info : PendingHTLCInfo ,
@@ -186,6 +194,24 @@ struct ClaimableHTLC {
186
194
total_msat : u64 ,
187
195
}
188
196
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
+
189
215
/// A payment identifier used to uniquely identify a payment to LDK.
190
216
/// (C-not exported) as we just use [u8; 32] directly
191
217
#[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -761,6 +787,9 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
761
787
pub ( super ) forward_htlcs : Mutex < HashMap < u64 , Vec < HTLCForwardInfo > > > ,
762
788
#[ cfg( not( test) ) ]
763
789
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 > > ,
764
793
765
794
/// The set of outbound SCID aliases across all our channels, including unconfirmed channels
766
795
/// 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
1634
1663
pending_outbound_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1635
1664
forward_htlcs : Mutex :: new ( HashMap :: new ( ) ) ,
1636
1665
id_to_peer : Mutex :: new ( HashMap :: new ( ) ) ,
1666
+ pending_intercepted_payments : Mutex :: new ( HashMap :: new ( ) ) ,
1637
1667
1638
1668
our_network_key : keys_manager. get_node_secret ( Recipient :: Node ) . unwrap ( ) ,
1639
1669
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
2163
2193
payment_hash,
2164
2194
incoming_shared_secret : shared_secret,
2165
2195
amt_to_forward : amt_msat,
2196
+ amt_incoming : Some ( amt_msat) ,
2166
2197
outgoing_cltv_value : hop_data. outgoing_cltv_value ,
2167
2198
} )
2168
2199
}
@@ -2260,6 +2291,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2260
2291
incoming_shared_secret : shared_secret,
2261
2292
amt_to_forward : next_hop_data. amt_to_forward ,
2262
2293
outgoing_cltv_value : next_hop_data. outgoing_cltv_value ,
2294
+ amt_incoming : Some ( msg. amount_msat )
2263
2295
} )
2264
2296
}
2265
2297
} ;
@@ -3030,6 +3062,66 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3030
3062
Ok ( ( ) )
3031
3063
}
3032
3064
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
+
3033
3125
/// Processes HTLCs which are pending waiting on random forward delay.
3034
3126
///
3035
3127
/// 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
3054
3146
None => {
3055
3147
for forward_info in pending_forwards. drain ( ..) {
3056
3148
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 } => {
3060
3150
macro_rules! failure_handler {
3061
3151
( $msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr, $next_hop_unknown: expr) => {
3062
3152
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
3065
3155
short_channel_id: prev_short_channel_id,
3066
3156
outpoint: prev_funding_outpoint,
3067
3157
htlc_id: prev_htlc_id,
3068
- incoming_packet_shared_secret: incoming_shared_secret,
3158
+ incoming_packet_shared_secret: forward_info . incoming_shared_secret,
3069
3159
phantom_shared_secret: $phantom_ss,
3070
3160
} ) ;
3071
3161
3072
3162
let reason = if $next_hop_unknown {
3073
3163
HTLCDestination :: UnknownNextHop { requested_forward_scid: short_chan_id }
3074
3164
} else {
3075
- HTLCDestination :: FailedPayment { payment_hash }
3165
+ HTLCDestination :: FailedPayment { payment_hash: forward_info . payment_hash }
3076
3166
} ;
3077
3167
3078
- failed_forwards. push( ( htlc_source, payment_hash,
3168
+ failed_forwards. push( ( htlc_source, forward_info . payment_hash,
3079
3169
HTLCFailReason :: Reason { failure_code: $err_code, data: $err_data } ,
3080
3170
reason
3081
3171
) ) ;
@@ -3096,11 +3186,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3096
3186
}
3097
3187
}
3098
3188
}
3099
- if let PendingHTLCRouting :: Forward { onion_packet, .. } = routing {
3189
+ if let PendingHTLCRouting :: Forward { ref onion_packet, .. } = forward_info . routing {
3100
3190
let phantom_secret_res = self . keys_manager . get_node_secret ( Recipient :: PhantomNode ) ;
3101
3191
if phantom_secret_res. is_ok ( ) && fake_scid:: is_valid_phantom ( & self . fake_scid_rand_bytes , short_chan_id) {
3102
3192
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 ) {
3104
3194
Ok ( res) => res,
3105
3195
Err ( onion_utils:: OnionDecodeErr :: Malformed { err_msg, err_code } ) => {
3106
3196
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
3116
3206
} ;
3117
3207
match next_hop {
3118
3208
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) ) {
3120
3210
Ok ( info) => phantom_receives. push ( ( prev_short_channel_id, prev_funding_outpoint, vec ! [ ( info, prev_htlc_id) ] ) ) ,
3121
3211
Err ( ReceiveError { err_code, err_data, msg } ) => failed_payment ! ( msg, err_code, err_data, Some ( phantom_shared_secret) )
3122
3212
}
3123
3213
} ,
3124
3214
_ => panic ! ( ) ,
3125
3215
}
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
+ }
3126
3240
} else {
3127
3241
fail_forward ! ( format!( "Unknown short channel id {} for forward HTLC" , short_chan_id) , 0x4000 | 10 , Vec :: new( ) , None ) ;
3128
3242
}
@@ -3149,8 +3263,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3149
3263
HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
3150
3264
routing : PendingHTLCRouting :: Forward {
3151
3265
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, .. } => {
3154
3268
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) ;
3155
3269
let htlc_source = HTLCSource :: PreviousHopData ( HTLCPreviousHopData {
3156
3270
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
3274
3388
match forward_info {
3275
3389
HTLCForwardInfo :: AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info : PendingHTLCInfo {
3276
3390
routing, incoming_shared_secret, payment_hash, amt_to_forward, .. } ,
3277
- prev_funding_outpoint } => {
3391
+ prev_funding_outpoint, .. } => {
3278
3392
let ( cltv_expiry, onion_payload, payment_data, phantom_shared_secret) = match routing {
3279
3393
PendingHTLCRouting :: Receive { payment_data, incoming_cltv_expiry, phantom_shared_secret } => {
3280
3394
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
5521
5635
inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
5522
5636
}
5523
5637
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
+
5524
5653
/// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
5525
5654
/// are used when constructing the phantom invoice's route hints.
5526
5655
///
@@ -6324,7 +6453,8 @@ impl_writeable_tlv_based!(PendingHTLCInfo, {
6324
6453
( 2 , incoming_shared_secret, required) ,
6325
6454
( 4 , payment_hash, required) ,
6326
6455
( 6 , amt_to_forward, required) ,
6327
- ( 8 , outgoing_cltv_value, required)
6456
+ ( 8 , outgoing_cltv_value, required) ,
6457
+ ( 9 , amt_incoming, option) ,
6328
6458
} ) ;
6329
6459
6330
6460
@@ -6567,6 +6697,13 @@ impl_writeable_tlv_based!(PendingInboundPayment, {
6567
6697
( 8 , min_value_msat, required) ,
6568
6698
} ) ;
6569
6699
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
+
6570
6707
impl_writeable_tlv_based_enum_upgradable ! ( PendingOutboundPayment ,
6571
6708
( 0 , Legacy ) => {
6572
6709
( 0 , session_privs, required) ,
@@ -6661,6 +6798,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6661
6798
6662
6799
let pending_inbound_payments = self . pending_inbound_payments . lock ( ) . unwrap ( ) ;
6663
6800
let pending_outbound_payments = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
6801
+ let pending_intercepted_payments = self . pending_intercepted_payments . lock ( ) . unwrap ( ) ;
6802
+
6664
6803
let events = self . pending_events . lock ( ) . unwrap ( ) ;
6665
6804
( events. len ( ) as u64 ) . write ( writer) ?;
6666
6805
for event in events. iter ( ) {
@@ -6732,6 +6871,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6732
6871
( 11 , self . probing_cookie_secret, required) ,
6733
6872
} ) ;
6734
6873
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
+
6735
6880
Ok ( ( ) )
6736
6881
}
6737
6882
}
@@ -7032,14 +7177,23 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
7032
7177
let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
7033
7178
let mut probing_cookie_secret: Option < [ u8 ; 32 ] > = None ;
7034
7179
let mut claimable_htlc_purposes = None ;
7035
- read_tlv_fields ! ( reader, {
7180
+ read_tlv_fields ! ( reader. by_ref ( ) , {
7036
7181
( 1 , pending_outbound_payments_no_retry, option) ,
7037
7182
( 3 , pending_outbound_payments, option) ,
7038
7183
( 5 , received_network_pubkey, option) ,
7039
7184
( 7 , fake_scid_rand_bytes, option) ,
7040
7185
( 9 , claimable_htlc_purposes, vec_type) ,
7041
7186
( 11 , probing_cookie_secret, option) ,
7042
7187
} ) ;
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
+
7043
7197
if fake_scid_rand_bytes. is_none ( ) {
7044
7198
fake_scid_rand_bytes = Some ( args. keys_manager . get_secure_random_bytes ( ) ) ;
7045
7199
}
@@ -7250,6 +7404,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
7250
7404
inbound_payment_key : expanded_inbound_key,
7251
7405
pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
7252
7406
pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
7407
+ pending_intercepted_payments : Mutex :: new ( pending_intercepted_payments) ,
7253
7408
7254
7409
forward_htlcs : Mutex :: new ( forward_htlcs) ,
7255
7410
outbound_scid_aliases : Mutex :: new ( outbound_scid_aliases) ,
0 commit comments