@@ -123,8 +123,12 @@ pub trait ManyChannelMonitor: Send + Sync {
123
123
fn add_update_monitor ( & self , funding_txo : OutPoint , monitor : ChannelMonitor ) -> Result < ( ) , ChannelMonitorUpdateErr > ;
124
124
125
125
/// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
126
- /// with success or failure backward
127
- fn fetch_pending_htlc_updated ( & self ) -> Vec < HTLCUpdate > ;
126
+ /// with success or failure.
127
+ ///
128
+ /// You should probably just call through to
129
+ /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return
130
+ /// the full list.
131
+ fn get_and_clear_pending_htlcs_updated ( & self ) -> Vec < HTLCUpdate > ;
128
132
}
129
133
130
134
/// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
@@ -146,7 +150,6 @@ pub struct SimpleManyChannelMonitor<Key> {
146
150
chain_monitor : Arc < ChainWatchInterface > ,
147
151
broadcaster : Arc < BroadcasterInterface > ,
148
152
pending_events : Mutex < Vec < events:: Event > > ,
149
- pending_htlc_updated : Mutex < HashMap < PaymentHash , Vec < ( HTLCSource , Option < PaymentPreimage > ) > > > ,
150
153
logger : Arc < Logger > ,
151
154
fee_estimator : Arc < FeeEstimator >
152
155
}
@@ -155,11 +158,10 @@ impl<'a, Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelM
155
158
fn block_connected ( & self , header : & BlockHeader , height : u32 , txn_matched : & [ & Transaction ] , _indexes_of_txn_matched : & [ u32 ] ) {
156
159
let block_hash = header. bitcoin_hash ( ) ;
157
160
let mut new_events: Vec < events:: Event > = Vec :: with_capacity ( 0 ) ;
158
- let mut htlc_updated_infos = Vec :: new ( ) ;
159
161
{
160
162
let mut monitors = self . monitors . lock ( ) . unwrap ( ) ;
161
163
for monitor in monitors. values_mut ( ) {
162
- let ( txn_outputs, spendable_outputs, mut htlc_updated ) = monitor. block_connected ( txn_matched, height, & block_hash, & * self . broadcaster , & * self . fee_estimator ) ;
164
+ let ( txn_outputs, spendable_outputs) = monitor. block_connected ( txn_matched, height, & block_hash, & * self . broadcaster , & * self . fee_estimator ) ;
163
165
if spendable_outputs. len ( ) > 0 {
164
166
new_events. push ( events:: Event :: SpendableOutputs {
165
167
outputs : spendable_outputs,
@@ -171,35 +173,6 @@ impl<'a, Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelM
171
173
self . chain_monitor . install_watch_outpoint ( ( txid. clone ( ) , idx as u32 ) , & output. script_pubkey ) ;
172
174
}
173
175
}
174
- htlc_updated_infos. append ( & mut htlc_updated) ;
175
- }
176
- }
177
- {
178
- // ChannelManager will just need to fetch pending_htlc_updated and pass state backward
179
- let mut pending_htlc_updated = self . pending_htlc_updated . lock ( ) . unwrap ( ) ;
180
- for htlc in htlc_updated_infos. drain ( ..) {
181
- match pending_htlc_updated. entry ( htlc. 2 ) {
182
- hash_map:: Entry :: Occupied ( mut e) => {
183
- // In case of reorg we may have htlc outputs solved in a different way so
184
- // we prefer to keep claims but don't store duplicate updates for a given
185
- // (payment_hash, HTLCSource) pair.
186
- let mut existing_claim = false ;
187
- e. get_mut ( ) . retain ( |htlc_data| {
188
- if htlc. 0 == htlc_data. 0 {
189
- if htlc_data. 1 . is_some ( ) {
190
- existing_claim = true ;
191
- true
192
- } else { false }
193
- } else { true }
194
- } ) ;
195
- if !existing_claim {
196
- e. get_mut ( ) . push ( ( htlc. 0 , htlc. 1 ) ) ;
197
- }
198
- }
199
- hash_map:: Entry :: Vacant ( e) => {
200
- e. insert ( vec ! [ ( htlc. 0 , htlc. 1 ) ] ) ;
201
- }
202
- }
203
176
}
204
177
}
205
178
let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
@@ -224,7 +197,6 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key>
224
197
chain_monitor,
225
198
broadcaster,
226
199
pending_events : Mutex :: new ( Vec :: new ( ) ) ,
227
- pending_htlc_updated : Mutex :: new ( HashMap :: new ( ) ) ,
228
200
logger,
229
201
fee_estimator : feeest,
230
202
} ;
@@ -272,17 +244,10 @@ impl ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint> {
272
244
}
273
245
}
274
246
275
- fn fetch_pending_htlc_updated ( & self ) -> Vec < HTLCUpdate > {
276
- let mut updated = self . pending_htlc_updated . lock ( ) . unwrap ( ) ;
277
- let mut pending_htlcs_updated = Vec :: with_capacity ( updated. len ( ) ) ;
278
- for ( k, v) in updated. drain ( ) {
279
- for htlc_data in v {
280
- pending_htlcs_updated. push ( HTLCUpdate {
281
- payment_hash : k,
282
- payment_preimage : htlc_data. 1 ,
283
- source : htlc_data. 0 ,
284
- } ) ;
285
- }
247
+ fn get_and_clear_pending_htlcs_updated ( & self ) -> Vec < HTLCUpdate > {
248
+ let mut pending_htlcs_updated = Vec :: new ( ) ;
249
+ for chan in self . monitors . lock ( ) . unwrap ( ) . values_mut ( ) {
250
+ pending_htlcs_updated. append ( & mut chan. get_and_clear_pending_htlcs_updated ( ) ) ;
286
251
}
287
252
pending_htlcs_updated
288
253
}
@@ -604,6 +569,8 @@ pub struct ChannelMonitor {
604
569
605
570
payment_preimages : HashMap < PaymentHash , PaymentPreimage > ,
606
571
572
+ pending_htlcs_updated : HashMap < PaymentHash , Vec < ( HTLCSource , Option < PaymentPreimage > ) > > ,
573
+
607
574
destination_script : Script ,
608
575
// Thanks to data loss protection, we may be able to claim our non-htlc funds
609
576
// back, this is the script we have to spend from but we need to
@@ -708,6 +675,7 @@ impl PartialEq for ChannelMonitor {
708
675
self . current_remote_commitment_number != other. current_remote_commitment_number ||
709
676
self . current_local_signed_commitment_tx != other. current_local_signed_commitment_tx ||
710
677
self . payment_preimages != other. payment_preimages ||
678
+ self . pending_htlcs_updated != other. pending_htlcs_updated ||
711
679
self . destination_script != other. destination_script ||
712
680
self . to_remote_rescue != other. to_remote_rescue ||
713
681
self . pending_claim_requests != other. pending_claim_requests ||
@@ -761,6 +729,8 @@ impl ChannelMonitor {
761
729
current_remote_commitment_number : 1 << 48 ,
762
730
763
731
payment_preimages : HashMap :: new ( ) ,
732
+ pending_htlcs_updated : HashMap :: new ( ) ,
733
+
764
734
destination_script : destination_script,
765
735
to_remote_rescue : None ,
766
736
@@ -1117,6 +1087,22 @@ impl ChannelMonitor {
1117
1087
res
1118
1088
}
1119
1089
1090
+ /// Get the list of HTLCs who's status has been updated on chain. This should be called by
1091
+ /// ChannelManager via ManyChannelMonitor::fetch_pending_htlcs_updated().
1092
+ pub fn get_and_clear_pending_htlcs_updated ( & mut self ) -> Vec < HTLCUpdate > {
1093
+ let mut pending_htlcs_updated = Vec :: with_capacity ( self . pending_htlcs_updated . len ( ) ) ;
1094
+ for ( k, v) in self . pending_htlcs_updated . drain ( ) {
1095
+ for htlc_data in v {
1096
+ pending_htlcs_updated. push ( HTLCUpdate {
1097
+ payment_hash : k,
1098
+ payment_preimage : htlc_data. 1 ,
1099
+ source : htlc_data. 0 ,
1100
+ } ) ;
1101
+ }
1102
+ }
1103
+ pending_htlcs_updated
1104
+ }
1105
+
1120
1106
/// Serializes into a vec, with various modes for the exposed pub fns
1121
1107
fn write < W : Writer > ( & self , writer : & mut W , for_local_storage : bool ) -> Result < ( ) , :: std:: io:: Error > {
1122
1108
//TODO: We still write out all the serialization here manually instead of using the fancy
@@ -1284,6 +1270,16 @@ impl ChannelMonitor {
1284
1270
writer. write_all ( & payment_preimage. 0 [ ..] ) ?;
1285
1271
}
1286
1272
1273
+ writer. write_all ( & byte_utils:: be64_to_array ( self . pending_htlcs_updated . len ( ) as u64 ) ) ?;
1274
+ for ( payment_hash, data) in self . pending_htlcs_updated . iter ( ) {
1275
+ writer. write_all ( & payment_hash. 0 [ ..] ) ?;
1276
+ writer. write_all ( & byte_utils:: be64_to_array ( data. len ( ) as u64 ) ) ?;
1277
+ for ( source, payment_preimage) in data. iter ( ) {
1278
+ source. write ( writer) ?;
1279
+ write_option ! ( payment_preimage) ;
1280
+ }
1281
+ }
1282
+
1287
1283
self . last_block_hash . write ( writer) ?;
1288
1284
self . destination_script . write ( writer) ?;
1289
1285
if let Some ( ( ref to_remote_script, ref local_key) ) = self . to_remote_rescue {
@@ -2334,11 +2330,38 @@ impl ChannelMonitor {
2334
2330
}
2335
2331
}
2336
2332
2337
- fn block_connected ( & mut self , txn_matched : & [ & Transaction ] , height : u32 , block_hash : & Sha256dHash , broadcaster : & BroadcasterInterface , fee_estimator : & FeeEstimator ) -> ( Vec < ( Sha256dHash , Vec < TxOut > ) > , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
2333
+ fn append_htlc_updated ( & mut self , mut htlc_updated_infos : Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
2334
+ // ChannelManager will just need to fetch pending_htlcs_updated and pass state backward
2335
+ for htlc in htlc_updated_infos. drain ( ..) {
2336
+ match self . pending_htlcs_updated . entry ( htlc. 2 ) {
2337
+ hash_map:: Entry :: Occupied ( mut e) => {
2338
+ // In case of reorg we may have htlc outputs solved in a different way so
2339
+ // we prefer to keep claims but don't store duplicate updates for a given
2340
+ // (payment_hash, HTLCSource) pair.
2341
+ let mut existing_claim = false ;
2342
+ e. get_mut ( ) . retain ( |htlc_data| {
2343
+ if htlc. 0 == htlc_data. 0 {
2344
+ if htlc_data. 1 . is_some ( ) {
2345
+ existing_claim = true ;
2346
+ true
2347
+ } else { false }
2348
+ } else { true }
2349
+ } ) ;
2350
+ if !existing_claim {
2351
+ e. get_mut ( ) . push ( ( htlc. 0 , htlc. 1 ) ) ;
2352
+ }
2353
+ }
2354
+ hash_map:: Entry :: Vacant ( e) => {
2355
+ e. insert ( vec ! [ ( htlc. 0 , htlc. 1 ) ] ) ;
2356
+ }
2357
+ }
2358
+ }
2359
+ }
2360
+
2361
+ fn block_connected ( & mut self , txn_matched : & [ & Transaction ] , height : u32 , block_hash : & Sha256dHash , broadcaster : & BroadcasterInterface , fee_estimator : & FeeEstimator ) -> ( Vec < ( Sha256dHash , Vec < TxOut > ) > , Vec < SpendableOutputDescriptor > ) {
2338
2362
log_trace ! ( self , "Block {} at height {} connected with {} txn matched" , block_hash, height, txn_matched. len( ) ) ;
2339
2363
let mut watch_outputs = Vec :: new ( ) ;
2340
2364
let mut spendable_outputs = Vec :: new ( ) ;
2341
- let mut htlc_updated = Vec :: new ( ) ;
2342
2365
let mut bump_candidates = HashSet :: new ( ) ;
2343
2366
for tx in txn_matched {
2344
2367
if tx. input . len ( ) == 1 {
@@ -2397,10 +2420,8 @@ impl ChannelMonitor {
2397
2420
// While all commitment/HTLC-Success/HTLC-Timeout transactions have one input, HTLCs
2398
2421
// can also be resolved in a few other ways which can have more than one output. Thus,
2399
2422
// we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check.
2400
- let mut updated = self . is_resolving_htlc_output ( & tx, height) ;
2401
- if updated. len ( ) > 0 {
2402
- htlc_updated. append ( & mut updated) ;
2403
- }
2423
+ let htlcs_updated = self . is_resolving_htlc_output ( & tx, height) ;
2424
+ self . append_htlc_updated ( htlcs_updated) ;
2404
2425
2405
2426
// Scan all input to verify is one of the outpoint spent is of interest for us
2406
2427
let mut claimed_outputs_material = Vec :: new ( ) ;
@@ -2523,7 +2544,7 @@ impl ChannelMonitor {
2523
2544
} ,
2524
2545
OnchainEvent :: HTLCUpdate { htlc_update } => {
2525
2546
log_trace ! ( self , "HTLC {} failure update has got enough confirmations to be passed upstream" , log_bytes!( ( htlc_update. 1 ) . 0 ) ) ;
2526
- htlc_updated . push ( ( htlc_update. 0 , None , htlc_update. 1 ) ) ;
2547
+ self . append_htlc_updated ( vec ! [ ( htlc_update. 0 , None , htlc_update. 1 ) ] ) ;
2527
2548
} ,
2528
2549
OnchainEvent :: ContentiousOutpoint { outpoint, .. } => {
2529
2550
self . claimable_outpoints . remove ( & outpoint) ;
@@ -2552,7 +2573,7 @@ impl ChannelMonitor {
2552
2573
}
2553
2574
}
2554
2575
self . last_block_hash = block_hash. clone ( ) ;
2555
- ( watch_outputs, spendable_outputs, htlc_updated )
2576
+ ( watch_outputs, spendable_outputs)
2556
2577
}
2557
2578
2558
2579
fn block_disconnected ( & mut self , height : u32 , block_hash : & Sha256dHash , broadcaster : & BroadcasterInterface , fee_estimator : & FeeEstimator ) {
@@ -3140,6 +3161,20 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
3140
3161
}
3141
3162
}
3142
3163
3164
+ let pending_htlcs_updated_len: u64 = Readable :: read ( reader) ?;
3165
+ let mut pending_htlcs_updated = HashMap :: with_capacity ( cmp:: min ( pending_htlcs_updated_len as usize , MAX_ALLOC_SIZE / ( 32 + 8 * 3 ) ) ) ;
3166
+ for _ in 0 ..pending_htlcs_updated_len {
3167
+ let payment_hash: PaymentHash = Readable :: read ( reader) ?;
3168
+ let htlcs_len: u64 = Readable :: read ( reader) ?;
3169
+ let mut htlcs = Vec :: with_capacity ( cmp:: min ( htlcs_len as usize , MAX_ALLOC_SIZE / 64 ) ) ;
3170
+ for _ in 0 ..htlcs_len {
3171
+ htlcs. push ( ( Readable :: read ( reader) ?, Readable :: read ( reader) ?) ) ;
3172
+ }
3173
+ if let Some ( _) = pending_htlcs_updated. insert ( payment_hash, htlcs) {
3174
+ return Err ( DecodeError :: InvalidValue ) ;
3175
+ }
3176
+ }
3177
+
3143
3178
let last_block_hash: Sha256dHash = Readable :: read ( reader) ?;
3144
3179
let destination_script = Readable :: read ( reader) ?;
3145
3180
let to_remote_rescue = match <u8 as Readable < R > >:: read ( reader) ? {
@@ -3226,6 +3261,7 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
3226
3261
current_remote_commitment_number,
3227
3262
3228
3263
payment_preimages,
3264
+ pending_htlcs_updated,
3229
3265
3230
3266
destination_script,
3231
3267
to_remote_rescue,
0 commit comments