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