Skip to content

Commit 8d50c91

Browse files
authored
Merge pull request #2203 from wpaulino/retry-untractable-packages
Retry untractable packages
2 parents 2e15df7 + a3b416a commit 8d50c91

File tree

8 files changed

+248
-129
lines changed

8 files changed

+248
-129
lines changed

lightning/src/chain/onchaintx.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
489489
///
490490
/// Panics if there are signing errors, because signing operations in reaction to on-chain
491491
/// events are not expected to fail, and if they do, we may lose funds.
492-
fn generate_claim<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(Option<u32>, u64, OnchainClaim)>
492+
fn generate_claim<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u32, u64, OnchainClaim)>
493493
where F::Target: FeeEstimator,
494494
L::Target: Logger,
495495
{
@@ -533,7 +533,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
533533

534534
// Compute new height timer to decide when we need to regenerate a new bumped version of the claim tx (if we
535535
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
536-
let new_timer = Some(cached_request.get_height_timer(cur_height));
536+
let new_timer = cached_request.get_height_timer(cur_height);
537537
if cached_request.is_malleable() {
538538
#[cfg(anchors)]
539539
{ // Attributes are not allowed on if expressions on our current MSRV of 1.41.
@@ -565,7 +565,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
565565
let transaction = cached_request.finalize_malleable_package(
566566
cur_height, self, output_value, self.destination_script.clone(), logger
567567
).unwrap();
568-
log_trace!(logger, "...with timer {} and feerate {}", new_timer.unwrap(), new_feerate);
568+
log_trace!(logger, "...with timer {} and feerate {}", new_timer, new_feerate);
569569
assert!(predicted_weight >= transaction.weight());
570570
return Some((new_timer, new_feerate, OnchainClaim::Tx(transaction)));
571571
}
@@ -583,7 +583,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
583583
None => return None,
584584
};
585585
if !cached_request.requires_external_funding() {
586-
return Some((None, 0, OnchainClaim::Tx(tx)));
586+
return Some((new_timer, 0, OnchainClaim::Tx(tx)));
587587
}
588588
#[cfg(anchors)]
589589
return inputs.find_map(|input| match input {
@@ -616,7 +616,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
616616
// attempt to broadcast the transaction with its current fee rate and hope
617617
// it confirms. This is essentially the same behavior as a commitment
618618
// transaction without anchor outputs.
619-
None => Some((None, 0, OnchainClaim::Tx(tx.clone()))),
619+
None => Some((new_timer, 0, OnchainClaim::Tx(tx.clone()))),
620620
}
621621
},
622622
_ => {
@@ -885,10 +885,8 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
885885

886886
// Check if any pending claim request must be rescheduled
887887
for (package_id, request) in self.pending_claim_requests.iter() {
888-
if let Some(h) = request.timer() {
889-
if cur_height >= h {
890-
bump_candidates.insert(*package_id, request.clone());
891-
}
888+
if cur_height >= request.timer() {
889+
bump_candidates.insert(*package_id, request.clone());
892890
}
893891
}
894892

lightning/src/chain/package.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ pub struct PackageTemplate {
538538
feerate_previous: u64,
539539
// Cache of next height at which fee-bumping and rebroadcast will be attempted. In
540540
// the future, we might abstract it to an observed mempool fluctuation.
541-
height_timer: Option<u32>,
541+
height_timer: u32,
542542
// Confirmation height of the claimed outputs set transaction. In case of reorg reaching
543543
// it, we wipe out and forget the package.
544544
height_original: u32,
@@ -557,13 +557,10 @@ impl PackageTemplate {
557557
pub(crate) fn set_feerate(&mut self, new_feerate: u64) {
558558
self.feerate_previous = new_feerate;
559559
}
560-
pub(crate) fn timer(&self) -> Option<u32> {
561-
if let Some(ref timer) = self.height_timer {
562-
return Some(*timer);
563-
}
564-
None
560+
pub(crate) fn timer(&self) -> u32 {
561+
self.height_timer
565562
}
566-
pub(crate) fn set_timer(&mut self, new_timer: Option<u32>) {
563+
pub(crate) fn set_timer(&mut self, new_timer: u32) {
567564
self.height_timer = new_timer;
568565
}
569566
pub(crate) fn outpoints(&self) -> Vec<&BitcoinOutPoint> {
@@ -837,7 +834,7 @@ impl PackageTemplate {
837834
soonest_conf_deadline,
838835
aggregable,
839836
feerate_previous: 0,
840-
height_timer: None,
837+
height_timer: height_original,
841838
height_original,
842839
}
843840
}
@@ -854,7 +851,7 @@ impl Writeable for PackageTemplate {
854851
(0, self.soonest_conf_deadline, required),
855852
(2, self.feerate_previous, required),
856853
(4, self.height_original, required),
857-
(6, self.height_timer, option)
854+
(6, self.height_timer, required)
858855
});
859856
Ok(())
860857
}
@@ -893,13 +890,16 @@ impl Readable for PackageTemplate {
893890
(4, height_original, required),
894891
(6, height_timer, option),
895892
});
893+
if height_timer.is_none() {
894+
height_timer = Some(height_original);
895+
}
896896
Ok(PackageTemplate {
897897
inputs,
898898
malleability,
899899
soonest_conf_deadline,
900900
aggregable,
901901
feerate_previous,
902-
height_timer,
902+
height_timer: height_timer.unwrap(),
903903
height_original,
904904
})
905905
}
@@ -1177,12 +1177,9 @@ mod tests {
11771177
let revk_outp = dumb_revk_output!(secp_ctx);
11781178

11791179
let mut package = PackageTemplate::build_package(txid, 0, revk_outp, 1000, true, 100);
1180-
let timer_none = package.timer();
1181-
assert!(timer_none.is_none());
1182-
package.set_timer(Some(100));
1183-
if let Some(timer_some) = package.timer() {
1184-
assert_eq!(timer_some, 100);
1185-
} else { panic!() }
1180+
assert_eq!(package.timer(), 100);
1181+
package.set_timer(101);
1182+
assert_eq!(package.timer(), 101);
11861183
}
11871184

11881185
#[test]

lightning/src/ln/functional_test_utils.rs

+32-20
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,20 @@ pub enum ConnectStyle {
137137
}
138138

139139
impl ConnectStyle {
140+
pub fn skips_blocks(&self) -> bool {
141+
match self {
142+
ConnectStyle::BestBlockFirst => false,
143+
ConnectStyle::BestBlockFirstSkippingBlocks => true,
144+
ConnectStyle::BestBlockFirstReorgsOnlyTip => true,
145+
ConnectStyle::TransactionsFirst => false,
146+
ConnectStyle::TransactionsFirstSkippingBlocks => true,
147+
ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks => true,
148+
ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks => true,
149+
ConnectStyle::TransactionsFirstReorgsOnlyTip => true,
150+
ConnectStyle::FullBlockViaListen => false,
151+
}
152+
}
153+
140154
fn random_style() -> ConnectStyle {
141155
#[cfg(feature = "std")] {
142156
use core::hash::{BuildHasher, Hasher};
@@ -164,12 +178,7 @@ impl ConnectStyle {
164178
}
165179

166180
pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> BlockHash {
167-
let skip_intermediaries = match *node.connect_style.borrow() {
168-
ConnectStyle::BestBlockFirstSkippingBlocks|ConnectStyle::TransactionsFirstSkippingBlocks|
169-
ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks|ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks|
170-
ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::TransactionsFirstReorgsOnlyTip => true,
171-
_ => false,
172-
};
181+
let skip_intermediaries = node.connect_style.borrow().skips_blocks();
173182

174183
let height = node.best_block_info().1 + 1;
175184
let mut block = Block {
@@ -2535,6 +2544,8 @@ pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
25352544
/// also fail.
25362545
pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction), commitment_tx: Option<Transaction>, has_htlc_tx: HTLCType) -> Vec<Transaction> {
25372546
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
2547+
let mut txn_seen = HashSet::new();
2548+
node_txn.retain(|tx| txn_seen.insert(tx.txid()));
25382549
assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 });
25392550

25402551
let mut res = Vec::with_capacity(2);
@@ -2598,22 +2609,23 @@ pub fn test_revoked_htlc_claim_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>
25982609

25992610
pub fn check_preimage_claim<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, prev_txn: &Vec<Transaction>) -> Vec<Transaction> {
26002611
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
2612+
let mut txn_seen = HashSet::new();
2613+
node_txn.retain(|tx| txn_seen.insert(tx.txid()));
26012614

2602-
assert!(node_txn.len() >= 1);
2603-
assert_eq!(node_txn[0].input.len(), 1);
26042615
let mut found_prev = false;
2605-
2606-
for tx in prev_txn {
2607-
if node_txn[0].input[0].previous_output.txid == tx.txid() {
2608-
check_spends!(node_txn[0], tx);
2609-
let mut iter = node_txn[0].input[0].witness.iter();
2610-
iter.next().expect("expected 3 witness items");
2611-
iter.next().expect("expected 3 witness items");
2612-
assert!(iter.next().expect("expected 3 witness items").len() > 106); // must spend an htlc output
2613-
assert_eq!(tx.input.len(), 1); // must spend a commitment tx
2614-
2615-
found_prev = true;
2616-
break;
2616+
for prev_tx in prev_txn {
2617+
for tx in &*node_txn {
2618+
if tx.input[0].previous_output.txid == prev_tx.txid() {
2619+
check_spends!(tx, prev_tx);
2620+
let mut iter = tx.input[0].witness.iter();
2621+
iter.next().expect("expected 3 witness items");
2622+
iter.next().expect("expected 3 witness items");
2623+
assert!(iter.next().expect("expected 3 witness items").len() > 106); // must spend an htlc output
2624+
assert_eq!(tx.input.len(), 1); // must spend a commitment tx
2625+
2626+
found_prev = true;
2627+
break;
2628+
}
26172629
}
26182630
}
26192631
assert!(found_prev);

0 commit comments

Comments
 (0)