Skip to content

Commit dffb6c9

Browse files
committed
Split finalize_claim_tx from generate_claim_tx and try to reorder finalization
1 parent 0d3e990 commit dffb6c9

File tree

1 file changed

+72
-53
lines changed

1 file changed

+72
-53
lines changed

lightning/src/chain/onchaintx.rs

+72-53
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,11 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
377377
/// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
378378
/// Panics if there are signing errors, because signing operations in reaction to on-chain events
379379
/// are not expected to fail, and if they do, we may lose funds.
380-
fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &F, logger: &L) -> Result<Option<(Option<u32>, u64, Transaction)>, SignError>
380+
fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &F, logger: &L) -> Option<(Option<u32>, u64, u64)>
381381
where F::Target: FeeEstimator,
382382
L::Target: Logger,
383383
{
384-
if cached_request.outpoints().len() == 0 { return Ok(None) } // But don't prune pending claiming request yet, we may have to resurrect HTLCs
384+
if cached_request.outpoints().len() == 0 { return None } // But don't prune pending claiming request yet, we may have to resurrect HTLCs
385385

386386
// Compute new height timer to decide when we need to regenerate a new bumped version of the claim tx (if we
387387
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
@@ -391,21 +391,32 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
391391
if let Some((output_value, new_feerate)) =
392392
cached_request.compute_package_output(predicted_weight, self.destination_script.dust_value().as_sat(), fee_estimator, logger) {
393393
assert!(new_feerate != 0);
394-
395-
let transaction = cached_request.finalize_package(self, output_value, self.destination_script.clone(), logger)?.unwrap();
396394
log_trace!(logger, "...with timer {} and feerate {}", new_timer.unwrap(), new_feerate);
397-
assert!(predicted_weight >= transaction.weight());
398-
return Ok(Some((new_timer, new_feerate, transaction)))
395+
return Some((new_timer, new_feerate, output_value))
399396
}
400397
} else {
401398
// Note: Currently, amounts of holder outputs spending witnesses aren't used
402399
// as we can't malleate spending package to increase their feerate. This
403400
// should change with the remaining anchor output patchset.
404-
if let Some(transaction) = cached_request.finalize_package(self, 0, self.destination_script.clone(), logger)? {
405-
return Ok(Some((None, 0, transaction)));
406-
}
401+
return Some((None, 0, 0));
407402
}
408-
Ok(None)
403+
None
404+
}
405+
406+
fn finalize_claim_tx<L: Deref>(&mut self, output_value: u64, cached_request: &PackageTemplate, logger: &L) -> Result<Option<Transaction>, SignError>
407+
where L::Target: Logger,
408+
{
409+
let transaction = cached_request.finalize_package(self, output_value, self.destination_script.clone(), logger)
410+
.map_err(|e| {
411+
log_warn!(logger, "Unable to sign claims because signer was not available, will retry");
412+
e
413+
})?;
414+
if cached_request.is_malleable() {
415+
let predicted_weight = cached_request.package_weight(&self.destination_script, self.channel_transaction_parameters.opt_anchors.is_some());
416+
// If the request is malleable, a transaction must have been finalized, so the unwrap is safe
417+
assert!(predicted_weight >= transaction.as_ref().unwrap().weight());
418+
}
419+
Ok(transaction)
409420
}
410421

411422
/// Upon channelmonitor.block_connected(..) or upon provision of a preimage on the forward link
@@ -471,27 +482,15 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
471482
}
472483
self.locktimed_packages = remaining_locked_packages;
473484

485+
let mut claims = Vec::new();
486+
474487
// Generate claim transactions and track them to bump if necessary at
475488
// height timer expiration (i.e in how many blocks we're going to take action).
476489
for mut req in preprocessed_requests {
477-
match self.generate_claim_tx(cur_height, &req, &*fee_estimator, &*logger) {
478-
Ok(Some((new_timer, new_feerate, tx))) => {
479-
req.set_timer(new_timer);
480-
req.set_feerate(new_feerate);
481-
let txid = tx.txid();
482-
for k in req.outpoints() {
483-
log_info!(logger, "Registering claiming request for {}:{}", k.txid, k.vout);
484-
self.claimable_outpoints.insert(k.clone(), (txid, conf_height));
485-
}
486-
self.pending_claim_requests.insert(txid, req);
487-
log_info!(logger, "Broadcasting onchain {}", log_tx!(tx));
488-
broadcaster.broadcast_transaction(&tx);
489-
}
490-
Ok(None) => {}
491-
Err(_) => {
492-
log_warn!(logger, "Unable to broadcast claims because signer was not available, will retry");
493-
req.set_timer(Some(cur_height + 1));
494-
}
490+
if let Some((new_timer, new_feerate, output_value)) = self.generate_claim_tx(cur_height, &req, &*fee_estimator, &*logger) {
491+
req.set_timer(new_timer);
492+
req.set_feerate(new_feerate);
493+
claims.push((output_value, req));
495494
}
496495
}
497496

@@ -570,6 +569,26 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
570569
}
571570
}
572571

572+
for (output_value, mut req) in claims {
573+
match self.finalize_claim_tx(output_value, &req, &*logger) {
574+
Ok(Some(tx)) => {
575+
let txid = tx.txid();
576+
for k in req.outpoints() {
577+
log_info!(logger, "Registering claiming request for {}:{}", k.txid, k.vout);
578+
// XXX this cannot be reordered to later than previous block because of data dependency - tests are failing
579+
self.claimable_outpoints.insert(k.clone(), (txid, conf_height));
580+
}
581+
self.pending_claim_requests.insert(txid, req);
582+
log_info!(logger, "Broadcasting onchain {}", log_tx!(tx));
583+
broadcaster.broadcast_transaction(&tx);
584+
}
585+
Ok(None) => {}
586+
Err(_) => {
587+
req.set_timer(Some(cur_height + 1));
588+
}
589+
}
590+
}
591+
573592
// After security delay, either our claim tx got enough confs or outpoint is definetely out of reach
574593
let onchain_events_awaiting_threshold_conf =
575594
self.onchain_events_awaiting_threshold_conf.drain(..).collect::<Vec<_>>();
@@ -608,21 +627,25 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
608627

609628
// Build, bump and rebroadcast tx accordingly
610629
log_trace!(logger, "Bumping {} candidates", bump_candidates.len());
611-
for (first_claim_txid, req) in bump_candidates.iter_mut() {
612-
match self.generate_claim_tx(cur_height, req, &*fee_estimator, &*logger) {
613-
Ok(Some((new_timer, new_feerate, bump_tx))) => {
614-
log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx));
615-
broadcaster.broadcast_transaction(&bump_tx);
616-
if let Some(request) = self.pending_claim_requests.get_mut(first_claim_txid) {
617-
request.set_timer(new_timer);
618-
request.set_feerate(new_feerate);
630+
for (first_claim_txid, req) in bump_candidates.drain() {
631+
if let Some((new_timer, new_feerate, output_value)) = self.generate_claim_tx(cur_height, &req, &*fee_estimator, &*logger) {
632+
match self.finalize_claim_tx(output_value, &req, &*logger) {
633+
Ok(Some(bump_tx)) => {
634+
log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx));
635+
broadcaster.broadcast_transaction(&bump_tx);
636+
if let Some(request) = self.pending_claim_requests.get_mut(&first_claim_txid) {
637+
request.set_timer(new_timer);
638+
request.set_feerate(new_feerate);
639+
}
640+
}
641+
Ok(None) => {}
642+
Err(_) => {
643+
if let Some(request) = self.pending_claim_requests.get_mut(&first_claim_txid) {
644+
request.set_timer(Some(cur_height + 1));
645+
}
619646
}
620647
}
621-
Ok(None) => {}
622-
Err(_) => {
623-
log_warn!(logger, "Unable to broadcast claims because signer was not available, will retry");
624-
req.set_timer(Some(cur_height + 1));
625-
}
648+
626649
}
627650
}
628651

@@ -683,18 +706,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
683706
}
684707
}
685708
for (_, request) in bump_candidates.iter_mut() {
686-
match self.generate_claim_tx(height, &request, &&*fee_estimator, &&*logger) {
687-
Ok(Some((new_timer, new_feerate, bump_tx))) => {
688-
request.set_timer(new_timer);
689-
request.set_feerate(new_feerate);
690-
log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx));
691-
broadcaster.broadcast_transaction(&bump_tx);
692-
}
693-
Ok(None) => {}
694-
Err(_) => {
695-
log_warn!(logger, "Unable to generate claim tx because signer is unavailable, will retry next block");
696-
request.set_timer(Some(height + 1));
697-
}
709+
if let Some((new_timer, new_feerate, output_value)) = self.generate_claim_tx(height, request, &&*fee_estimator, &&*logger) {
710+
let bump_tx = self.finalize_claim_tx(output_value, request, &&*logger).unwrap().unwrap();
711+
request.set_timer(new_timer);
712+
request.set_feerate(new_feerate);
713+
log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx));
714+
broadcaster.broadcast_transaction(&bump_tx);
715+
// log_warn!(logger, "Unable to generate claim tx because signer is unavailable, will retry next block");
716+
// request.set_timer(Some(height + 1));
698717
}
699718
}
700719
for (ancestor_claim_txid, request) in bump_candidates.drain() {

0 commit comments

Comments
 (0)