@@ -319,33 +319,30 @@ fn write_legacy_holder_commitment_data<W: Writer>(
319
319
let delayed_payment_key = & tx_keys. broadcaster_delayed_payment_key ;
320
320
let per_commitment_point = & tx_keys. per_commitment_point ;
321
321
322
- let mut nondust_htlcs = commitment_tx. nondust_htlcs ( ) . iter ( )
323
- . zip ( commitment_tx. counterparty_htlc_sigs . iter ( ) ) ;
324
- let mut sources = htlc_data. nondust_htlc_sources . iter ( ) ;
325
-
326
- // Use an iterator to write `htlc_outputs` to avoid allocations.
327
- let nondust_htlcs = core:: iter:: from_fn ( move || {
328
- let ( htlc, counterparty_htlc_sig) = if let Some ( nondust_htlc) = nondust_htlcs. next ( ) {
329
- nondust_htlc
330
- } else {
331
- debug_assert ! ( sources. next( ) . is_none( ) ) ;
332
- return None ;
333
- } ;
334
-
335
- let mut source = None ;
336
- if htlc. offered {
337
- source = sources. next ( ) ;
338
- if source. is_none ( ) {
339
- panic ! ( "Every offered non-dust HTLC should have a corresponding source" ) ;
340
- }
322
+ let mut table: Vec < ( HTLCOutputInCommitment , Option < & HTLCSource > ) > = htlc_data. htlcs_and_sources . iter ( ) . map ( |( htlc, source) | ( htlc. clone ( ) , source. as_ref ( ) ) ) . collect ( ) ;
323
+ let mut htlc_sig_sources = Vec :: new ( ) ;
324
+ for ( nondust_htlc, sig) in commitment_tx. nondust_htlcs ( ) . iter ( ) . zip ( commitment_tx. counterparty_htlc_sigs . iter ( ) ) {
325
+ let ( htlc, source) = table
326
+ . iter_mut ( )
327
+ . filter ( |( htlc, _source) | htlc. transaction_output_index . is_none ( ) )
328
+ . find_map ( |( htlc, source) | {
329
+ if htlc. is_data_equal ( nondust_htlc) {
330
+ Some ( ( htlc, source) )
331
+ } else {
332
+ None
333
+ }
334
+ } )
335
+ . unwrap ( ) ;
336
+ htlc. transaction_output_index = Some ( nondust_htlc. transaction_output_index . unwrap ( ) ) ;
337
+ htlc_sig_sources. push ( ( htlc. clone ( ) , Some ( sig) , source. clone ( ) ) ) ;
338
+ }
339
+ for ( htlc, source) in table {
340
+ if htlc. transaction_output_index . is_none ( ) {
341
+ htlc_sig_sources. push ( ( htlc, None , source) ) ;
341
342
}
342
- Some ( ( htlc, Some ( counterparty_htlc_sig) , source) )
343
- } ) ;
343
+ }
344
344
345
- // Dust HTLCs go last.
346
- let dust_htlcs = htlc_data. dust_htlcs . iter ( )
347
- . map ( |( htlc, source) | ( htlc, None :: < & Signature > , source. as_ref ( ) ) ) ;
348
- let htlc_outputs = crate :: util:: ser:: IterableOwned ( nondust_htlcs. chain ( dust_htlcs) ) ;
345
+ let htlc_outputs = crate :: util:: ser:: IterableOwned ( htlc_sig_sources. into_iter ( ) ) ;
349
346
350
347
write_tlv_fields ! ( writer, {
351
348
( 0 , txid, required) ,
@@ -924,44 +921,21 @@ impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer:
924
921
struct HolderCommitmentHTLCData {
925
922
// These must be sorted in increasing output index order to match the expected order of the
926
923
// HTLCs in the `CommitmentTransaction`.
927
- nondust_htlc_sources : Vec < HTLCSource > ,
928
- dust_htlcs : Vec < ( HTLCOutputInCommitment , Option < HTLCSource > ) > ,
924
+ htlcs_and_sources : Vec < ( HTLCOutputInCommitment , Option < HTLCSource > ) > ,
929
925
}
930
926
931
927
impl TryFrom < ( & HolderCommitmentTransaction , & HolderSignedTx ) > for HolderCommitmentHTLCData {
932
928
type Error = ( ) ;
933
929
fn try_from ( value : ( & HolderCommitmentTransaction , & HolderSignedTx ) ) -> Result < Self , Self :: Error > {
934
- let holder_commitment_tx = value. 0 ;
935
930
let holder_signed_tx = value. 1 ;
936
931
937
- // HolderSignedTx tracks all HTLCs included in the commitment (dust included). For
938
- // `HolderCommitment`, we'll need to extract the dust HTLCs and their sources, and non-dust
939
- // HTLC sources, separately. All offered, non-dust HTLCs must have a source available.
940
-
941
- let mut missing_nondust_source = false ;
942
- let mut nondust_htlc_sources = Vec :: with_capacity ( holder_commitment_tx. nondust_htlcs ( ) . len ( ) ) ;
943
- let dust_htlcs = holder_signed_tx. htlc_outputs . iter ( ) . filter_map ( |( htlc, _, source) | {
944
- // Filter our non-dust HTLCs, while at the same time pushing their sources into
945
- // `nondust_htlc_sources`.
946
- if htlc. transaction_output_index . is_none ( ) {
947
- return Some ( ( htlc. clone ( ) , source. clone ( ) ) )
948
- }
949
- if htlc. offered {
950
- if let Some ( source) = source {
951
- nondust_htlc_sources. push ( source. clone ( ) ) ;
952
- } else {
953
- missing_nondust_source = true ;
954
- }
955
- }
956
- None
957
- } ) . collect ( ) ;
958
- if missing_nondust_source {
959
- return Err ( ( ) ) ;
960
- }
961
-
962
932
Ok ( Self {
963
- nondust_htlc_sources,
964
- dust_htlcs,
933
+ htlcs_and_sources : holder_signed_tx. htlc_outputs . iter ( )
934
+ . map ( |( htlc, _, source) | {
935
+ let mut htlc = htlc. clone ( ) ;
936
+ htlc. transaction_output_index = None ;
937
+ ( htlc, source. clone ( ) )
938
+ } ) . collect ( ) ,
965
939
} )
966
940
}
967
941
}
@@ -1171,20 +1145,28 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
1171
1145
// we'd be unable to mutate `self` while holding an immutable iterator (specifically, returned from
1172
1146
// a function) over `self`.
1173
1147
macro_rules! holder_commitment_htlcs {
1174
- ( $self: expr, CURRENT ) => {
1148
+ ( $self: expr, CURRENT ) => { {
1149
+ let nondust_htlc_count = $self. funding. current_holder_commitment_tx. nondust_htlcs( ) . len( ) ;
1150
+ let mut dust_iter = $self. current_holder_htlc_data. htlcs_and_sources. iter( ) . map( |( htlc, _) | htlc) ;
1151
+ if nondust_htlc_count > 0 {
1152
+ dust_iter. nth( nondust_htlc_count - 1 ) ;
1153
+ }
1175
1154
$self. funding. current_holder_commitment_tx. nondust_htlcs( ) . iter( )
1176
- . chain( $self . current_holder_htlc_data . dust_htlcs . iter ( ) . map ( | ( htlc , _ ) | htlc ) )
1177
- } ;
1155
+ . chain( dust_iter )
1156
+ } } ;
1178
1157
( $self: expr, CURRENT_WITH_SOURCES ) => { {
1179
1158
holder_commitment_htlcs!(
1180
1159
& $self. funding. current_holder_commitment_tx, & $self. current_holder_htlc_data
1181
1160
)
1182
1161
} } ;
1183
1162
( $self: expr, PREV ) => { {
1184
1163
if let Some ( tx) = & $self. funding. prev_holder_commitment_tx {
1185
- let dust_htlcs = $self. prev_holder_htlc_data. as_ref( ) . unwrap( ) . dust_htlcs. iter( )
1186
- . map( |( htlc, _) | htlc) ;
1187
- Some ( tx. nondust_htlcs( ) . iter( ) . chain( dust_htlcs) )
1164
+ let nondust_htlc_count = tx. nondust_htlcs( ) . len( ) ;
1165
+ let mut dust_iter = $self. prev_holder_htlc_data. as_ref( ) . unwrap( ) . htlcs_and_sources. iter( ) . map( |( htlc, _) | htlc) ;
1166
+ if nondust_htlc_count > 0 {
1167
+ dust_iter. nth( nondust_htlc_count - 1 ) ;
1168
+ }
1169
+ Some ( tx. nondust_htlcs( ) . iter( ) . chain( dust_iter) )
1188
1170
} else {
1189
1171
None
1190
1172
}
@@ -1197,19 +1179,22 @@ macro_rules! holder_commitment_htlcs {
1197
1179
}
1198
1180
} } ;
1199
1181
( $commitment_tx: expr, $htlc_data: expr) => { {
1200
- let mut sources = $htlc_data. nondust_htlc_sources. iter( ) ;
1201
- let nondust_htlcs = $commitment_tx. nondust_htlcs( ) . iter( ) . map( move |htlc| {
1202
- let mut source = None ;
1203
- if htlc. offered && htlc. transaction_output_index. is_some( ) {
1204
- source = sources. next( ) ;
1205
- if source. is_none( ) {
1206
- panic!( "Every offered non-dust HTLC should have a corresponding source" ) ;
1207
- }
1208
- }
1209
- ( htlc, source)
1210
- } ) ;
1211
- let dust_htlcs = $htlc_data. dust_htlcs. iter( ) . map( |( htlc, source) | ( htlc, source. as_ref( ) ) ) ;
1212
- nondust_htlcs. chain( dust_htlcs)
1182
+ let mut table: Vec <( HTLCOutputInCommitment , Option <& HTLCSource >) > = $htlc_data. htlcs_and_sources. iter( ) . map( |( htlc, source) | ( htlc. clone( ) , source. as_ref( ) ) ) . collect( ) ;
1183
+ for nondust_htlc in $commitment_tx. nondust_htlcs( ) {
1184
+ let htlc = table
1185
+ . iter_mut( )
1186
+ . filter( |( htlc, _source) | htlc. transaction_output_index. is_none( ) )
1187
+ . find_map( |( htlc, _source) | {
1188
+ if htlc. is_data_equal( nondust_htlc) {
1189
+ Some ( htlc)
1190
+ } else {
1191
+ None
1192
+ }
1193
+ } )
1194
+ . unwrap( ) ;
1195
+ htlc. transaction_output_index = Some ( nondust_htlc. transaction_output_index. unwrap( ) ) ;
1196
+ }
1197
+ table. into_iter( ) . map( |( htlc, source) | ( htlc, source) )
1213
1198
} } ;
1214
1199
}
1215
1200
@@ -2546,7 +2531,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2546
2531
if htlc. transaction_output_index. is_some( ) {
2547
2532
2548
2533
if let Some ( bal) = us. get_htlc_balance(
2549
- htlc, source, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid
2534
+ & htlc, source, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid
2550
2535
) {
2551
2536
res. push( bal) ;
2552
2537
}
@@ -2885,7 +2870,7 @@ macro_rules! fail_unbroadcast_htlcs {
2885
2870
// broadcastable commitment transaction has the HTLC in it, but it
2886
2871
// cannot currently change after channel initialization, so we don't
2887
2872
// need to here.
2888
- let confirmed_htlcs_iter: & mut dyn Iterator <Item = ( & HTLCOutputInCommitment , Option <& HTLCSource >) > = & mut $confirmed_htlcs_list;
2873
+ let confirmed_htlcs_iter: & mut dyn Iterator <Item = ( HTLCOutputInCommitment , Option <& HTLCSource >) > = & mut $confirmed_htlcs_list;
2889
2874
2890
2875
let mut matched_htlc = false ;
2891
2876
for ( ref broadcast_htlc, ref broadcast_source) in confirmed_htlcs_iter {
@@ -3135,7 +3120,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3135
3120
// Backfill the non-dust HTLC sources.
3136
3121
debug_assert ! ( nondust_htlc_sources. is_empty( ) ) ;
3137
3122
nondust_htlc_sources. reserve_exact ( holder_commitment_tx. nondust_htlcs ( ) . len ( ) ) ;
3138
- let dust_htlcs = htlc_outputs. into_iter ( ) . filter_map ( |( htlc, _, source) | {
3123
+ let _dust_htlcs : Vec < _ > = htlc_outputs. into_iter ( ) . filter_map ( |( htlc, _, source) | {
3139
3124
// Filter our non-dust HTLCs, while at the same time pushing their sources into
3140
3125
// `nondust_htlc_sources`.
3141
3126
if htlc. transaction_output_index . is_none ( ) {
@@ -3146,8 +3131,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3146
3131
}
3147
3132
None
3148
3133
} ) . collect ( ) ;
3149
-
3150
- dust_htlcs
3134
+ panic ! ( "This path should not be exercised" ) ;
3151
3135
} else {
3152
3136
// If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via
3153
3137
// `nondust_htlc_sources`, building up the final htlc_outputs by combining
@@ -3160,6 +3144,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3160
3144
}
3161
3145
}
3162
3146
3147
+ /*
3163
3148
debug_assert!(htlc_outputs.iter().all(|(htlc, _, _)| htlc.transaction_output_index.is_none()));
3164
3149
debug_assert!(htlc_outputs.iter().all(|(_, sig_opt, _)| sig_opt.is_none()));
3165
3150
debug_assert_eq!(holder_commitment_tx.trust().nondust_htlcs().len(), holder_commitment_tx.counterparty_htlc_sigs.len());
@@ -3172,17 +3157,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3172
3157
}
3173
3158
}
3174
3159
assert!(sources.next().is_none(), "All HTLC sources should have been exhausted");
3160
+ */
3175
3161
3176
3162
// This only includes dust HTLCs as checked above.
3177
- htlc_outputs. into_iter ( ) . map ( |( htlc, _, source) | ( htlc, source) ) . collect ( )
3163
+ htlc_outputs. into_iter ( ) . map ( |( mut htlc, _, source) | {
3164
+ htlc. transaction_output_index = None ;
3165
+ ( htlc, source)
3166
+ } ) . collect ( )
3178
3167
} ;
3179
3168
3180
3169
self . current_holder_commitment_number = holder_commitment_tx. trust ( ) . commitment_number ( ) ;
3181
3170
self . onchain_tx_handler . provide_latest_holder_tx ( holder_commitment_tx. clone ( ) ) ;
3182
3171
3183
3172
mem:: swap ( & mut holder_commitment_tx, & mut self . funding . current_holder_commitment_tx ) ;
3184
3173
self . funding . prev_holder_commitment_tx = Some ( holder_commitment_tx) ;
3185
- let mut holder_htlc_data = HolderCommitmentHTLCData { nondust_htlc_sources , dust_htlcs } ;
3174
+ let mut holder_htlc_data = HolderCommitmentHTLCData { htlcs_and_sources : dust_htlcs } ;
3186
3175
mem:: swap ( & mut holder_htlc_data, & mut self . current_holder_htlc_data ) ;
3187
3176
self . prev_holder_htlc_data = Some ( holder_htlc_data) ;
3188
3177
@@ -3812,7 +3801,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3812
3801
if let Some ( per_commitment_claimable_data) = per_commitment_option {
3813
3802
fail_unbroadcast_htlcs ! ( self , "revoked_counterparty" , commitment_txid, tx, height,
3814
3803
block_hash, per_commitment_claimable_data. iter( ) . map( |( htlc, htlc_source) |
3815
- ( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
3804
+ ( htlc. clone ( ) , htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
3816
3805
) , logger) ;
3817
3806
} else {
3818
3807
// Our fuzzers aren't constrained by pesky things like valid signatures, so can
@@ -3821,7 +3810,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3821
3810
// fuzzing.
3822
3811
debug_assert ! ( cfg!( fuzzing) , "We should have per-commitment option for any recognized old commitment txn" ) ;
3823
3812
fail_unbroadcast_htlcs ! ( self , "revoked counterparty" , commitment_txid, tx, height,
3824
- block_hash, [ ] . iter( ) . map ( |reference| * reference ) , logger) ;
3813
+ block_hash, core :: iter:: empty ( ) , logger) ;
3825
3814
}
3826
3815
}
3827
3816
} else if let Some ( per_commitment_claimable_data) = per_commitment_option {
@@ -3837,7 +3826,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3837
3826
log_info ! ( logger, "Got broadcast of non-revoked counterparty commitment transaction {}" , commitment_txid) ;
3838
3827
fail_unbroadcast_htlcs ! ( self , "counterparty" , commitment_txid, tx, height, block_hash,
3839
3828
per_commitment_claimable_data. iter( ) . map( |( htlc, htlc_source) |
3840
- ( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
3829
+ ( htlc. clone ( ) , htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
3841
3830
) , logger) ;
3842
3831
let ( htlc_claim_reqs, counterparty_output_info) =
3843
3832
self . get_counterparty_output_claim_info ( commitment_number, commitment_txid, Some ( tx) , per_commitment_option) ;
@@ -4532,8 +4521,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4532
4521
} else { None } . into_iter ( ) . flatten ( ) ;
4533
4522
4534
4523
let htlcs = holder_commitment_htlcs ! ( self , CURRENT_WITH_SOURCES )
4535
- . chain ( current_counterparty_htlcs)
4536
- . chain ( prev_counterparty_htlcs) ;
4524
+ . chain ( current_counterparty_htlcs. map ( | ( htlc , source ) | ( htlc . clone ( ) , source ) ) )
4525
+ . chain ( prev_counterparty_htlcs. map ( | ( htlc , source ) | ( htlc . clone ( ) , source ) ) ) ;
4537
4526
4538
4527
let height = self . best_block . height ;
4539
4528
for ( htlc, source_opt) in htlcs {
@@ -5728,7 +5717,7 @@ mod tests {
5728
5717
let nondust_htlcs = dummy_commitment_tx. nondust_htlcs ( ) ;
5729
5718
5730
5719
monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx. clone ( ) ,
5731
- nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , Some ( dummy_sig ) , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5720
+ nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , None , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5732
5721
monitor. provide_latest_counterparty_commitment_tx ( Txid :: from_byte_array ( Sha256 :: hash ( b"1" ) . to_byte_array ( ) ) ,
5733
5722
preimages_slice_to_htlc_outputs ! ( preimages[ 5 ..15 ] ) , 281474976710655 , dummy_key, & logger) ;
5734
5723
monitor. provide_latest_counterparty_commitment_tx ( Txid :: from_byte_array ( Sha256 :: hash ( b"2" ) . to_byte_array ( ) ) ,
@@ -5768,7 +5757,7 @@ mod tests {
5768
5757
// These HTLCs now have their output indices assigned
5769
5758
let nondust_htlcs = dummy_commitment_tx. nondust_htlcs ( ) ;
5770
5759
monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx. clone ( ) ,
5771
- nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , Some ( dummy_sig ) , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5760
+ nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , None , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5772
5761
secret[ 0 ..32 ] . clone_from_slice ( & <Vec < u8 > >:: from_hex ( "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8" ) . unwrap ( ) ) ;
5773
5762
monitor. provide_secret ( 281474976710653 , secret. clone ( ) ) . unwrap ( ) ;
5774
5763
assert_eq ! ( monitor. inner. lock( ) . unwrap( ) . payment_preimages. len( ) , 12 ) ;
@@ -5781,7 +5770,7 @@ mod tests {
5781
5770
// These HTLCs now have their output indices assigned
5782
5771
let nondust_htlcs = dummy_commitment_tx. nondust_htlcs ( ) ;
5783
5772
monitor. provide_latest_holder_commitment_tx ( dummy_commitment_tx. clone ( ) ,
5784
- nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , Some ( dummy_sig ) , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5773
+ nondust_htlcs. into_iter ( ) . map ( |htlc| ( htlc. clone ( ) , None , Some ( dummy_source. clone ( ) ) ) ) . collect ( ) ) ;
5785
5774
secret[ 0 ..32 ] . clone_from_slice ( & <Vec < u8 > >:: from_hex ( "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116" ) . unwrap ( ) ) ;
5786
5775
monitor. provide_secret ( 281474976710652 , secret. clone ( ) ) . unwrap ( ) ;
5787
5776
assert_eq ! ( monitor. inner. lock( ) . unwrap( ) . payment_preimages. len( ) , 5 ) ;
0 commit comments