Skip to content

Commit 0808478

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.
1 parent 57fa2a2 commit 0808478

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

lightning/src/chain/onchaintx.rs

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

lightning/src/chain/package.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,28 @@ impl PackageSolvingData {
808808
}
809809
}
810810

811+
fn input_confirmation_height(&self) -> Option<u32> {
812+
match self {
813+
PackageSolvingData::RevokedOutput(RevokedOutput { outpoint_confirmation_height, ..})
814+
| PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput {
815+
outpoint_confirmation_height, ..
816+
})
817+
| PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput {
818+
outpoint_confirmation_height, ..
819+
})
820+
| PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput {
821+
outpoint_confirmation_height, ..
822+
})
823+
|PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput {
824+
outpoint_confirmation_height, ..
825+
}) => *outpoint_confirmation_height,
826+
// We don't bother to track `HolderFundingOutput`'s creation height as its the funding
827+
// transaction itself and we build `HolderFundingOutput`s before we actually get the
828+
// commitment transaction confirmed.
829+
PackageSolvingData::HolderFundingOutput(_) => None,
830+
}
831+
}
832+
811833
#[rustfmt::skip]
812834
fn as_tx_input(&self, previous_output: BitcoinOutPoint) -> TxIn {
813835
let sequence = match self {
@@ -1175,6 +1197,12 @@ impl PackageTemplate {
11751197
pub(crate) fn outpoints(&self) -> Vec<&BitcoinOutPoint> {
11761198
self.inputs.iter().map(|(o, _)| o).collect()
11771199
}
1200+
pub(crate) fn outpoints_and_creation_heights(
1201+
&self,
1202+
) -> impl Iterator<Item = (&BitcoinOutPoint, Option<u32>)> {
1203+
self.inputs.iter().map(|(o, p)| (o, p.input_confirmation_height()))
1204+
}
1205+
11781206
pub(crate) fn inputs(&self) -> impl ExactSizeIterator<Item = &PackageSolvingData> {
11791207
self.inputs.iter().map(|(_, i)| i)
11801208
}

0 commit comments

Comments
 (0)