Skip to content

Commit 6b730e0

Browse files
committed
Use outpoint creation height when restoring locktimed packages
When we have an outpoint to claim which is lock-timed and the locktime is reached, we add it to `OnchainTxHandler::claimable_outpoints` to indicate the outpoint is now being claimed. However, `claimable_outpoints` is supposed to track when the outpoint first appeared on chain so that we can remove the claim if the outpoint is reorged out. Sadly, in the handling for lock-timed packages, we incorrectly stored the current height in `claimable_outpoints`, causing such claims to be removed in case of a reorg right after they were generated, even if the output we intend to claim isn't removed at all. Here we use the creation-height tracking added in the previous commit to actually address the issue, using the tracked height when adding a claim to `OnchainTxHandler::claimable_outpoints`. In cases where we have no information, we continue to use the current height, retaining the issue for locktimed packages on upgrades, but this simplifies cases where we actually don't have the information available anyway. Trivial conflicts resolved in: * lightning/src/chain/package.rs
1 parent 0a87307 commit 6b730e0

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

lightning/src/chain/onchaintx.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,10 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
865865
// Because fuzzing can cause hash collisions, we can end up with conflicting claim
866866
// ids here, so we only assert when not fuzzing.
867867
debug_assert!(cfg!(fuzzing) || self.pending_claim_requests.get(&claim_id).is_none());
868-
for k in req.outpoints() {
869-
log_info!(logger, "Registering claiming request for {}:{}", k.txid, k.vout);
870-
self.claimable_outpoints.insert(k.clone(), (claim_id, conf_height));
868+
for (k, outpoint_confirmation_height) in req.outpoints_and_creation_heights() {
869+
let creation_height = outpoint_confirmation_height.unwrap_or(conf_height);
870+
log_info!(logger, "Registering claiming request for {}:{}, which exists as of height {creation_height}", k.txid, k.vout);
871+
self.claimable_outpoints.insert(k.clone(), (claim_id, creation_height));
871872
}
872873
self.pending_claim_requests.insert(claim_id, req);
873874
}

lightning/src/chain/package.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,35 @@ impl PackageSolvingData {
603603
}
604604
}
605605

606+
fn input_confirmation_height(&self) -> Option<u32> {
607+
match self {
608+
PackageSolvingData::RevokedOutput(RevokedOutput {
609+
outpoint_confirmation_height,
610+
..
611+
})
612+
| PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput {
613+
outpoint_confirmation_height,
614+
..
615+
})
616+
| PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput {
617+
outpoint_confirmation_height,
618+
..
619+
})
620+
| PackageSolvingData::CounterpartyReceivedHTLCOutput(
621+
CounterpartyReceivedHTLCOutput { outpoint_confirmation_height, .. },
622+
)
623+
| PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput {
624+
outpoint_confirmation_height,
625+
..
626+
}) => *outpoint_confirmation_height,
627+
// We don't bother to track `HolderFundingOutput`'s creation height as its the funding
628+
// transaction itself and we build `HolderFundingOutput`s before we actually get the
629+
// commitment transaction confirmed.
630+
PackageSolvingData::HolderFundingOutput(_) => None,
631+
}
632+
}
633+
634+
#[rustfmt::skip]
606635
fn as_tx_input(&self, previous_output: BitcoinOutPoint) -> TxIn {
607636
let sequence = match self {
608637
PackageSolvingData::RevokedOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME,
@@ -905,6 +934,12 @@ impl PackageTemplate {
905934
pub(crate) fn outpoints(&self) -> Vec<&BitcoinOutPoint> {
906935
self.inputs.iter().map(|(o, _)| o).collect()
907936
}
937+
pub(crate) fn outpoints_and_creation_heights(
938+
&self,
939+
) -> impl Iterator<Item = (&BitcoinOutPoint, Option<u32>)> {
940+
self.inputs.iter().map(|(o, p)| (o, p.input_confirmation_height()))
941+
}
942+
908943
pub(crate) fn inputs(&self) -> impl ExactSizeIterator<Item = &PackageSolvingData> {
909944
self.inputs.iter().map(|(_, i)| i)
910945
}

0 commit comments

Comments
 (0)