@@ -493,8 +493,12 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
493
493
pub ( crate ) enum ChannelMonitorUpdateStep {
494
494
LatestHolderCommitmentTXInfo {
495
495
commitment_tx : HolderCommitmentTransaction ,
496
+ /// Note that LDK after 0.0.115 supports this only containing dust HTLCs (implying the
497
+ /// `Signature` field is never filled in). At that point, non-dust HTLCs are implied by the
498
+ /// HTLC fields in `commitment_tx` and the sources passed via `nondust_htlc_sources`.
496
499
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > ,
497
500
claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
501
+ nondust_htlc_sources : Vec < HTLCSource > ,
498
502
} ,
499
503
LatestCounterpartyCommitmentTXInfo {
500
504
commitment_txid : Txid ,
@@ -539,6 +543,7 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
539
543
( 0 , commitment_tx, required) ,
540
544
( 1 , claimed_htlcs, vec_type) ,
541
545
( 2 , htlc_outputs, vec_type) ,
546
+ ( 3 , nondust_htlc_sources, vec_type) ,
542
547
} ,
543
548
( 1 , LatestCounterpartyCommitmentTXInfo ) => {
544
549
( 0 , commitment_txid, required) ,
@@ -1180,7 +1185,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1180
1185
& self , holder_commitment_tx : HolderCommitmentTransaction ,
1181
1186
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > ,
1182
1187
) -> Result < ( ) , ( ) > {
1183
- self . inner . lock ( ) . unwrap ( ) . provide_latest_holder_commitment_tx ( holder_commitment_tx, htlc_outputs, & Vec :: new ( ) ) . map_err ( |_| ( ) )
1188
+ self . inner . lock ( ) . unwrap ( ) . provide_latest_holder_commitment_tx ( holder_commitment_tx, htlc_outputs, & Vec :: new ( ) , Vec :: new ( ) ) . map_err ( |_| ( ) )
1184
1189
}
1185
1190
1186
1191
/// This is used to provide payment preimage(s) out-of-band during startup without updating the
@@ -2160,7 +2165,51 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2160
2165
/// is important that any clones of this channel monitor (including remote clones) by kept
2161
2166
/// up-to-date as our holder commitment transaction is updated.
2162
2167
/// Panics if set_on_holder_tx_csv has never been called.
2163
- fn provide_latest_holder_commitment_tx ( & mut self , holder_commitment_tx : HolderCommitmentTransaction , htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > , claimed_htlcs : & [ ( SentHTLCId , PaymentPreimage ) ] ) -> Result < ( ) , & ' static str > {
2168
+ fn provide_latest_holder_commitment_tx ( & mut self , holder_commitment_tx : HolderCommitmentTransaction , mut htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > , claimed_htlcs : & [ ( SentHTLCId , PaymentPreimage ) ] , nondust_htlc_sources : Vec < HTLCSource > ) -> Result < ( ) , & ' static str > {
2169
+ if htlc_outputs. iter ( ) . any ( |( _, s, _) | s. is_some ( ) ) {
2170
+ // If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the
2171
+ // `holder_commitment_tx`. In the future, we'll no longer provide the redundant data
2172
+ // and just pass in source data via `nondust_htlc_sources`.
2173
+ debug_assert_eq ! ( htlc_outputs. iter( ) . filter( |( _, s, _) | s. is_some( ) ) . count( ) , holder_commitment_tx. trust( ) . htlcs( ) . len( ) ) ;
2174
+ for ( a, b) in htlc_outputs. iter ( ) . filter ( |( _, s, _) | s. is_some ( ) ) . map ( |( h, _, _) | h) . zip ( holder_commitment_tx. trust ( ) . htlcs ( ) . iter ( ) ) {
2175
+ debug_assert_eq ! ( a, b) ;
2176
+ }
2177
+ debug_assert_eq ! ( htlc_outputs. iter( ) . filter( |( _, s, _) | s. is_some( ) ) . count( ) , holder_commitment_tx. counterparty_htlc_sigs. len( ) ) ;
2178
+ for ( a, b) in htlc_outputs. iter ( ) . filter_map ( |( _, s, _) | s. as_ref ( ) ) . zip ( holder_commitment_tx. counterparty_htlc_sigs . iter ( ) ) {
2179
+ debug_assert_eq ! ( a, b) ;
2180
+ }
2181
+ debug_assert ! ( nondust_htlc_sources. is_empty( ) ) ;
2182
+ } else {
2183
+ // If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via
2184
+ // `nondust_htlc_sources`, building up the final htlc_outputs by combining
2185
+ // `nondust_htlc_sources` and the `holder_commitment_tx`
2186
+ #[ cfg( debug_assertions) ] {
2187
+ let mut prev = -1 ;
2188
+ for htlc in holder_commitment_tx. trust ( ) . htlcs ( ) . iter ( ) {
2189
+ assert ! ( htlc. transaction_output_index. unwrap( ) as i32 > prev) ;
2190
+ prev = htlc. transaction_output_index . unwrap ( ) as i32 ;
2191
+ }
2192
+ }
2193
+ debug_assert ! ( htlc_outputs. iter( ) . all( |( htlc, _, _) | htlc. transaction_output_index. is_none( ) ) ) ;
2194
+ debug_assert ! ( htlc_outputs. iter( ) . all( |( _, sig_opt, _) | sig_opt. is_none( ) ) ) ;
2195
+ debug_assert_eq ! ( holder_commitment_tx. trust( ) . htlcs( ) . len( ) , holder_commitment_tx. counterparty_htlc_sigs. len( ) ) ;
2196
+
2197
+ let mut sources_iter = nondust_htlc_sources. into_iter ( ) ;
2198
+
2199
+ for ( htlc, counterparty_sig) in holder_commitment_tx. trust ( ) . htlcs ( ) . iter ( )
2200
+ . zip ( holder_commitment_tx. counterparty_htlc_sigs . iter ( ) )
2201
+ {
2202
+ if htlc. offered {
2203
+ let source = sources_iter. next ( ) . expect ( "Non-dust HTLC sources didn't match commitment tx" ) ;
2204
+ debug_assert ! ( source. possibly_matches_output( htlc) ) ;
2205
+ htlc_outputs. push ( ( htlc. clone ( ) , Some ( counterparty_sig. clone ( ) ) , Some ( source) ) ) ;
2206
+ } else {
2207
+ htlc_outputs. push ( ( htlc. clone ( ) , Some ( counterparty_sig. clone ( ) ) , None ) ) ;
2208
+ }
2209
+ }
2210
+ debug_assert ! ( sources_iter. next( ) . is_none( ) ) ;
2211
+ }
2212
+
2164
2213
let trusted_tx = holder_commitment_tx. trust ( ) ;
2165
2214
let txid = trusted_tx. txid ( ) ;
2166
2215
let tx_keys = trusted_tx. keys ( ) ;
@@ -2285,10 +2334,10 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2285
2334
let bounded_fee_estimator = LowerBoundedFeeEstimator :: new ( & * fee_estimator) ;
2286
2335
for update in updates. updates . iter ( ) {
2287
2336
match update {
2288
- ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs } => {
2337
+ ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => {
2289
2338
log_trace ! ( logger, "Updating ChannelMonitor with latest holder commitment transaction info" ) ;
2290
2339
if self . lockdown_from_offchain { panic ! ( ) ; }
2291
- if let Err ( e) = self . provide_latest_holder_commitment_tx ( commitment_tx. clone ( ) , htlc_outputs. clone ( ) , & claimed_htlcs) {
2340
+ if let Err ( e) = self . provide_latest_holder_commitment_tx ( commitment_tx. clone ( ) , htlc_outputs. clone ( ) , & claimed_htlcs, nondust_htlc_sources . clone ( ) ) {
2292
2341
log_error ! ( logger, "Providing latest holder commitment transaction failed/was refused:" ) ;
2293
2342
log_error ! ( logger, " {}" , e) ;
2294
2343
ret = Err ( ( ) ) ;
@@ -4132,7 +4181,7 @@ mod tests {
4132
4181
}
4133
4182
}
4134
4183
4135
- macro_rules! preimages_slice_to_htlc_outputs {
4184
+ macro_rules! preimages_slice_to_htlcs {
4136
4185
( $preimages_slice: expr) => {
4137
4186
{
4138
4187
let mut res = Vec :: new( ) ;
@@ -4143,21 +4192,20 @@ mod tests {
4143
4192
cltv_expiry: 0 ,
4144
4193
payment_hash: preimage. 1 . clone( ) ,
4145
4194
transaction_output_index: Some ( idx as u32 ) ,
4146
- } , None ) ) ;
4195
+ } , ( ) ) ) ;
4147
4196
}
4148
4197
res
4149
4198
}
4150
4199
}
4151
4200
}
4152
- macro_rules! preimages_to_holder_htlcs {
4201
+ macro_rules! preimages_slice_to_htlc_outputs {
4153
4202
( $preimages_slice: expr) => {
4154
- {
4155
- let mut inp = preimages_slice_to_htlc_outputs!( $preimages_slice) ;
4156
- let res: Vec <_> = inp. drain( ..) . map( |e| { ( e. 0 , None , e. 1 ) } ) . collect( ) ;
4157
- res
4158
- }
4203
+ preimages_slice_to_htlcs!( $preimages_slice) . into_iter( ) . map( |( htlc, _) | ( htlc, None ) ) . collect( )
4159
4204
}
4160
4205
}
4206
+ let dummy_sig = crate :: util:: crypto:: sign ( & secp_ctx,
4207
+ & bitcoin:: secp256k1:: Message :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
4208
+ & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4161
4209
4162
4210
macro_rules! test_preimages_exist {
4163
4211
( $preimages_slice: expr, $monitor: expr) => {
@@ -4204,13 +4252,15 @@ mod tests {
4204
4252
let shutdown_pubkey = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4205
4253
let best_block = BestBlock :: from_network ( Network :: Testnet ) ;
4206
4254
let monitor = ChannelMonitor :: new ( Secp256k1 :: new ( ) , keys,
4207
- Some ( ShutdownScript :: new_p2wpkh_from_pubkey ( shutdown_pubkey) . into_inner ( ) ) , 0 , & Script :: new ( ) ,
4208
- ( OutPoint { txid : Txid :: from_slice ( & [ 43 ; 32 ] ) . unwrap ( ) , index : 0 } , Script :: new ( ) ) ,
4209
- & channel_parameters,
4210
- Script :: new ( ) , 46 , 0 ,
4211
- HolderCommitmentTransaction :: dummy ( ) , best_block, dummy_key) ;
4212
-
4213
- monitor. provide_latest_holder_commitment_tx ( HolderCommitmentTransaction :: dummy ( ) , preimages_to_holder_htlcs ! ( preimages[ 0 ..10 ] ) ) . unwrap ( ) ;
4255
+ Some ( ShutdownScript :: new_p2wpkh_from_pubkey ( shutdown_pubkey) . into_inner ( ) ) , 0 , & Script :: new ( ) ,
4256
+ ( OutPoint { txid : Txid :: from_slice ( & [ 43 ; 32 ] ) . unwrap ( ) , index : 0 } , Script :: new ( ) ) ,
4257
+ & channel_parameters, Script :: new ( ) , 46 , 0 , HolderCommitmentTransaction :: dummy ( & mut Vec :: new ( ) ) ,
4258
+ best_block, dummy_key) ;
4259
+
4260
+ let mut htlcs = preimages_slice_to_htlcs ! ( preimages[ 0 ..10 ] ) ;
4261
+ let dummy_commitment_tx = HolderCommitmentTransaction :: dummy ( & mut htlcs) ;
4262
+ monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx. clone ( ) ,
4263
+ htlcs. into_iter ( ) . map ( |( htlc, _) | ( htlc, Some ( dummy_sig) , None ) ) . collect ( ) ) . unwrap ( ) ;
4214
4264
monitor. provide_latest_counterparty_commitment_tx ( Txid :: from_inner ( Sha256 :: hash ( b"1" ) . into_inner ( ) ) ,
4215
4265
preimages_slice_to_htlc_outputs ! ( preimages[ 5 ..15 ] ) , 281474976710655 , dummy_key, & logger) ;
4216
4266
monitor. provide_latest_counterparty_commitment_tx ( Txid :: from_inner ( Sha256 :: hash ( b"2" ) . into_inner ( ) ) ,
@@ -4243,15 +4293,21 @@ mod tests {
4243
4293
4244
4294
// Now update holder commitment tx info, pruning only element 18 as we still care about the
4245
4295
// previous commitment tx's preimages too
4246
- monitor. provide_latest_holder_commitment_tx ( HolderCommitmentTransaction :: dummy ( ) , preimages_to_holder_htlcs ! ( preimages[ 0 ..5 ] ) ) . unwrap ( ) ;
4296
+ let mut htlcs = preimages_slice_to_htlcs ! ( preimages[ 0 ..5 ] ) ;
4297
+ let dummy_commitment_tx = HolderCommitmentTransaction :: dummy ( & mut htlcs) ;
4298
+ monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx. clone ( ) ,
4299
+ htlcs. into_iter ( ) . map ( |( htlc, _) | ( htlc, Some ( dummy_sig) , None ) ) . collect ( ) ) . unwrap ( ) ;
4247
4300
secret[ 0 ..32 ] . clone_from_slice ( & hex:: decode ( "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8" ) . unwrap ( ) ) ;
4248
4301
monitor. provide_secret ( 281474976710653 , secret. clone ( ) ) . unwrap ( ) ;
4249
4302
assert_eq ! ( monitor. inner. lock( ) . unwrap( ) . payment_preimages. len( ) , 12 ) ;
4250
4303
test_preimages_exist ! ( & preimages[ 0 ..10 ] , monitor) ;
4251
4304
test_preimages_exist ! ( & preimages[ 18 ..20 ] , monitor) ;
4252
4305
4253
4306
// But if we do it again, we'll prune 5-10
4254
- monitor. provide_latest_holder_commitment_tx ( HolderCommitmentTransaction :: dummy ( ) , preimages_to_holder_htlcs ! ( preimages[ 0 ..3 ] ) ) . unwrap ( ) ;
4307
+ let mut htlcs = preimages_slice_to_htlcs ! ( preimages[ 0 ..3 ] ) ;
4308
+ let dummy_commitment_tx = HolderCommitmentTransaction :: dummy ( & mut htlcs) ;
4309
+ monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx,
4310
+ htlcs. into_iter ( ) . map ( |( htlc, _) | ( htlc, Some ( dummy_sig) , None ) ) . collect ( ) ) . unwrap ( ) ;
4255
4311
secret[ 0 ..32 ] . clone_from_slice ( & hex:: decode ( "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116" ) . unwrap ( ) ) ;
4256
4312
monitor. provide_secret ( 281474976710652 , secret. clone ( ) ) . unwrap ( ) ;
4257
4313
assert_eq ! ( monitor. inner. lock( ) . unwrap( ) . payment_preimages. len( ) , 5 ) ;
0 commit comments