@@ -33,6 +33,7 @@ use util::ser::{Readable, ReadableArgs, Writer, Writeable, VecWriter};
33
33
use util:: byte_utils;
34
34
35
35
use prelude:: * ;
36
+ use alloc:: collections:: BTreeMap ;
36
37
use std:: collections:: HashMap ;
37
38
use core:: cmp;
38
39
use core:: ops:: Deref ;
@@ -165,9 +166,9 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
165
166
#[ cfg( not( test) ) ]
166
167
claimable_outpoints : HashMap < BitcoinOutPoint , ( Txid , u32 ) > ,
167
168
168
- onchain_events_awaiting_threshold_conf : Vec < OnchainEventEntry > ,
169
+ locktimed_packages : BTreeMap < u32 , Vec < PackageTemplate > > ,
169
170
170
- latest_height : u32 ,
171
+ onchain_events_awaiting_threshold_conf : Vec < OnchainEventEntry > ,
171
172
172
173
pub ( super ) secp_ctx : Secp256k1 < secp256k1:: All > ,
173
174
}
@@ -207,6 +208,15 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
207
208
claim_and_height. 1 . write ( writer) ?;
208
209
}
209
210
211
+ writer. write_all ( & byte_utils:: be64_to_array ( self . locktimed_packages . len ( ) as u64 ) ) ?;
212
+ for ( ref locktime, ref packages) in self . locktimed_packages . iter ( ) {
213
+ locktime. write ( writer) ?;
214
+ writer. write_all ( & byte_utils:: be64_to_array ( packages. len ( ) as u64 ) ) ?;
215
+ for ref package in packages. iter ( ) {
216
+ package. write ( writer) ?;
217
+ }
218
+ }
219
+
210
220
writer. write_all ( & byte_utils:: be64_to_array ( self . onchain_events_awaiting_threshold_conf . len ( ) as u64 ) ) ?;
211
221
for ref entry in self . onchain_events_awaiting_threshold_conf . iter ( ) {
212
222
entry. txid . write ( writer) ?;
@@ -222,7 +232,6 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
222
232
}
223
233
}
224
234
}
225
- self . latest_height . write ( writer) ?;
226
235
227
236
write_tlv_fields ! ( writer, { } , { } ) ;
228
237
Ok ( ( ) )
@@ -267,6 +276,19 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
267
276
let height = Readable :: read ( reader) ?;
268
277
claimable_outpoints. insert ( outpoint, ( ancestor_claim_txid, height) ) ;
269
278
}
279
+
280
+ let locktimed_packages_len: u64 = Readable :: read ( reader) ?;
281
+ let mut locktimed_packages = BTreeMap :: new ( ) ;
282
+ for _ in 0 ..locktimed_packages_len {
283
+ let locktime = Readable :: read ( reader) ?;
284
+ let packages_len: u64 = Readable :: read ( reader) ?;
285
+ let mut packages = Vec :: with_capacity ( cmp:: min ( packages_len as usize , MAX_ALLOC_SIZE / std:: mem:: size_of :: < PackageTemplate > ( ) ) ) ;
286
+ for _ in 0 ..packages_len {
287
+ packages. push ( Readable :: read ( reader) ?) ;
288
+ }
289
+ locktimed_packages. insert ( locktime, packages) ;
290
+ }
291
+
270
292
let waiting_threshold_conf_len: u64 = Readable :: read ( reader) ?;
271
293
let mut onchain_events_awaiting_threshold_conf = Vec :: with_capacity ( cmp:: min ( waiting_threshold_conf_len as usize , MAX_ALLOC_SIZE / 128 ) ) ;
272
294
for _ in 0 ..waiting_threshold_conf_len {
@@ -289,7 +311,6 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
289
311
} ;
290
312
onchain_events_awaiting_threshold_conf. push ( OnchainEventEntry { txid, height, event } ) ;
291
313
}
292
- let latest_height = Readable :: read ( reader) ?;
293
314
294
315
read_tlv_fields ! ( reader, { } , { } ) ;
295
316
@@ -305,9 +326,9 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
305
326
signer,
306
327
channel_transaction_parameters : channel_parameters,
307
328
claimable_outpoints,
329
+ locktimed_packages,
308
330
pending_claim_requests,
309
331
onchain_events_awaiting_threshold_conf,
310
- latest_height,
311
332
secp_ctx,
312
333
} )
313
334
}
@@ -325,8 +346,8 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
325
346
channel_transaction_parameters : channel_parameters,
326
347
pending_claim_requests : HashMap :: new ( ) ,
327
348
claimable_outpoints : HashMap :: new ( ) ,
349
+ locktimed_packages : BTreeMap :: new ( ) ,
328
350
onchain_events_awaiting_threshold_conf : Vec :: new ( ) ,
329
- latest_height : 0 ,
330
351
331
352
secp_ctx,
332
353
}
@@ -345,10 +366,9 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
345
366
// Compute new height timer to decide when we need to regenerate a new bumped version of the claim tx (if we
346
367
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
347
368
let new_timer = Some ( cached_request. get_height_timer ( height) ) ;
348
- let amt = cached_request. package_amount ( ) ;
349
369
if cached_request. is_malleable ( ) {
350
370
let predicted_weight = cached_request. package_weight ( & self . destination_script ) ;
351
- if let Some ( ( output_value, new_feerate) ) = cached_request. compute_package_output ( predicted_weight, amt , fee_estimator, logger) {
371
+ if let Some ( ( output_value, new_feerate) ) = cached_request. compute_package_output ( predicted_weight, fee_estimator, logger) {
352
372
assert ! ( new_feerate != 0 ) ;
353
373
354
374
let transaction = cached_request. finalize_package ( self , output_value, self . destination_script . clone ( ) , logger) . unwrap ( ) ;
@@ -360,8 +380,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
360
380
// Note: Currently, amounts of holder outputs spending witnesses aren't used
361
381
// as we can't malleate spending package to increase their feerate. This
362
382
// should change with the remaining anchor output patchset.
363
- debug_assert ! ( amt == 0 ) ;
364
- if let Some ( transaction) = cached_request. finalize_package ( self , amt, self . destination_script . clone ( ) , logger) {
383
+ if let Some ( transaction) = cached_request. finalize_package ( self , 0 , self . destination_script . clone ( ) , logger) {
365
384
return Some ( ( None , 0 , transaction) ) ;
366
385
}
367
386
}
@@ -372,15 +391,11 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
372
391
/// for this channel, provide new relevant on-chain transactions and/or new claim requests.
373
392
/// Formerly this was named `block_connected`, but it is now also used for claiming an HTLC output
374
393
/// if we receive a preimage after force-close.
375
- pub ( crate ) fn update_claims_view < B : Deref , F : Deref , L : Deref > ( & mut self , txn_matched : & [ & Transaction ] , requests : Vec < PackageTemplate > , latest_height : Option < u32 > , broadcaster : & B , fee_estimator : & F , logger : & L )
394
+ pub ( crate ) fn update_claims_view < B : Deref , F : Deref , L : Deref > ( & mut self , txn_matched : & [ & Transaction ] , requests : Vec < PackageTemplate > , height : u32 , broadcaster : & B , fee_estimator : & F , logger : & L )
376
395
where B :: Target : BroadcasterInterface ,
377
396
F :: Target : FeeEstimator ,
378
397
L :: Target : Logger ,
379
398
{
380
- let height = match latest_height {
381
- Some ( h) => h,
382
- None => self . latest_height ,
383
- } ;
384
399
log_trace ! ( logger, "Updating claims view at height {} with {} matched transactions and {} claim requests" , height, txn_matched. len( ) , requests. len( ) ) ;
385
400
let mut preprocessed_requests = Vec :: with_capacity ( requests. len ( ) ) ;
386
401
let mut aggregated_request = None ;
@@ -389,7 +404,26 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
389
404
// <= CLTV_SHARED_CLAIM_BUFFER) and they don't require an immediate nLockTime (aggregable).
390
405
for req in requests {
391
406
// Don't claim a outpoint twice that would be bad for privacy and may uselessly lock a CPFP input for a while
392
- if let Some ( _) = self . claimable_outpoints . get ( req. outpoints ( ) [ 0 ] ) { log_trace ! ( logger, "Bouncing off outpoint {}:{}, already registered its claiming request" , req. outpoints( ) [ 0 ] . txid, req. outpoints( ) [ 0 ] . vout) ; } else {
407
+ if let Some ( _) = self . claimable_outpoints . get ( req. outpoints ( ) [ 0 ] ) {
408
+ log_trace ! ( logger, "Ignoring second claim for outpoint {}:{}, already registered its claiming request" , req. outpoints( ) [ 0 ] . txid, req. outpoints( ) [ 0 ] . vout) ;
409
+ } else {
410
+ let timelocked_equivalent_package = self . locktimed_packages . iter ( ) . map ( |v| v. 1 . iter ( ) ) . flatten ( )
411
+ . find ( |locked_package| locked_package. outpoints ( ) == req. outpoints ( ) ) ;
412
+ if let Some ( package) = timelocked_equivalent_package {
413
+ log_trace ! ( logger, "Ignoring second claim for outpoint {}:{}, we already have one which we're waiting on a timelock at {} for." ,
414
+ req. outpoints( ) [ 0 ] . txid, req. outpoints( ) [ 0 ] . vout, package. package_timelock( ) ) ;
415
+ continue ;
416
+ }
417
+
418
+ if req. package_timelock ( ) > height + 1 {
419
+ log_debug ! ( logger, "Delaying claim of package until its timelock at {} (current height {}), the following outpoints are spent:" , req. package_timelock( ) , height) ;
420
+ for outpoint in req. outpoints ( ) {
421
+ log_debug ! ( logger, " Outpoint {}" , outpoint) ;
422
+ }
423
+ self . locktimed_packages . entry ( req. package_timelock ( ) ) . or_insert ( Vec :: new ( ) ) . push ( req) ;
424
+ continue ;
425
+ }
426
+
393
427
log_trace ! ( logger, "Test if outpoint can be aggregated with expiration {} against {}" , req. timelock( ) , height + CLTV_SHARED_CLAIM_BUFFER ) ;
394
428
if req. timelock ( ) <= height + CLTV_SHARED_CLAIM_BUFFER || !req. aggregable ( ) {
395
429
// Don't aggregate if outpoint package timelock is soon or marked as non-aggregable
@@ -405,6 +439,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
405
439
preprocessed_requests. push ( req) ;
406
440
}
407
441
442
+ // Claim everything up to and including height + 1
443
+ let remaining_locked_packages = self . locktimed_packages . split_off ( & ( height + 2 ) ) ;
444
+ for ( pop_height, mut entry) in self . locktimed_packages . iter_mut ( ) {
445
+ log_trace ! ( logger, "Restoring delayed claim of package(s) at their timelock at {}." , pop_height) ;
446
+ preprocessed_requests. append ( & mut entry) ;
447
+ }
448
+ self . locktimed_packages = remaining_locked_packages;
449
+
408
450
// Generate claim transactions and track them to bump if necessary at
409
451
// height timer expiration (i.e in how many blocks we're going to take action).
410
452
for mut req in preprocessed_requests {
0 commit comments