Skip to content

Commit 8b27973

Browse files
author
Antoine Riard
committed
-f Move timelock from OnchainRequest to PackageTemplate
1 parent 461fef6 commit 8b27973

File tree

3 files changed

+37
-38
lines changed

3 files changed

+37
-38
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,8 +1462,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
14621462
for (idx, outp) in tx.output.iter().enumerate() {
14631463
if outp.script_pubkey == revokeable_p2wsh {
14641464
let revk_outp = RevokedOutput::build(per_commitment_point, per_commitment_key, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, InputDescriptors::RevokedOutput, outp.value, None, self.counterparty_tx_cache.on_counterparty_tx_csv);
1465-
let justice_package = PackageTemplate::build_package(commitment_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable);
1466-
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, absolute_timelock: height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, height_original: height, content: justice_package});
1465+
let justice_package = PackageTemplate::build_package(commitment_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable, height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32);
1466+
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
14671467
}
14681468
}
14691469

@@ -1476,8 +1476,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
14761476
return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
14771477
}
14781478
let revk_outp = RevokedOutput::build(per_commitment_point, per_commitment_key, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }, htlc.amount_msat / 1000, Some(htlc.clone()), self.counterparty_tx_cache.on_counterparty_tx_csv);
1479-
let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable);
1480-
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, absolute_timelock: htlc.cltv_expiry, height_original: height, content: justice_package});
1479+
let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable, htlc.cltv_expiry);
1480+
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
14811481
}
14821482
}
14831483
}
@@ -1626,8 +1626,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
16261626
let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
16271627
if preimage.is_some() || !htlc.offered {
16281628
let counterparty_htlc_outp = CounterpartyHTLCOutput::build(*revocation_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, preimage, htlc.clone());
1629-
let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::CounterpartyHTLCOutput(counterparty_htlc_outp), PackageMalleability::Malleable);
1630-
claimable_outpoints.push(OnchainRequest { aggregation: if !htlc.offered { false } else { true }, feerate_previous: 0, height_timer: None, absolute_timelock: htlc.cltv_expiry, height_original: /*XXX(ariard) Option<height> */ 0, content: counterparty_package });
1629+
let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::CounterpartyHTLCOutput(counterparty_htlc_outp), PackageMalleability::Malleable, htlc.cltv_expiry);
1630+
claimable_outpoints.push(OnchainRequest { aggregation: if !htlc.offered { false } else { true }, feerate_previous: 0, height_timer: None, height_original: /*XXX(ariard) Option<height> */ 0, content: counterparty_package });
16311631
}
16321632
}
16331633
}
@@ -1659,8 +1659,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
16591659

16601660
log_trace!(logger, "Counterparty HTLC broadcast {}:{}", htlc_txid, 0);
16611661
let revk_outp = RevokedOutput::build(per_commitment_point, per_commitment_key, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, InputDescriptors::RevokedOutput, tx.output[0].value, None, self.counterparty_tx_cache.on_counterparty_tx_csv);
1662-
let justice_package = PackageTemplate::build_package(htlc_txid, 0, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable);
1663-
let claimable_outpoints = vec!(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, absolute_timelock: height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, height_original: height, content: justice_package });
1662+
let justice_package = PackageTemplate::build_package(htlc_txid, 0, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable, height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32);
1663+
let claimable_outpoints = vec!(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package });
16641664
let outputs = vec![(0, tx.output[0].clone())];
16651665
(claimable_outpoints, Some((htlc_txid, outputs)))
16661666
}
@@ -1684,8 +1684,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
16841684
continue;
16851685
}
16861686
} else { None }, htlc.amount_msat);
1687-
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), PackageMalleability::Untractable);
1688-
claim_requests.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, absolute_timelock: height, height_original: height, content: htlc_package });
1687+
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), PackageMalleability::Untractable, height);
1688+
claim_requests.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, height_original: height, content: htlc_package });
16891689
}
16901690
}
16911691

@@ -1893,8 +1893,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18931893
let should_broadcast = self.would_broadcast_at_height(height, &logger);
18941894
if should_broadcast {
18951895
let funding_outp = HolderFundingOutput::build(self.funding_redeemscript.clone());
1896-
let commitment_package = PackageTemplate::build_package(self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), PackageMalleability::Untractable);
1897-
claimable_outpoints.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, absolute_timelock: height, height_original: height, content: commitment_package });
1896+
let commitment_package = PackageTemplate::build_package(self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), PackageMalleability::Untractable, height);
1897+
claimable_outpoints.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, height_original: height, content: commitment_package });
18981898
}
18991899
if should_broadcast {
19001900
self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));

lightning/src/chain/onchain_utils.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,18 @@ impl Readable for PackageMalleability {
479479
pub(crate) struct PackageTemplate {
480480
inputs: Vec<(BitcoinOutPoint, PackageSolvingData)>,
481481
malleability: PackageMalleability,
482+
// Block height before which claiming is exclusive to one party,
483+
// after reaching it, claiming may be contentious.
484+
absolute_timelock: u32,
482485
}
483486

484487
impl PackageTemplate {
485488
pub(crate) fn is_malleable(&self) -> bool {
486489
self.malleability == PackageMalleability::Malleable
487490
}
491+
pub(crate) fn timelock(&self) -> u32 {
492+
self.absolute_timelock
493+
}
488494
pub(crate) fn outpoints(&self) -> Vec<&BitcoinOutPoint> {
489495
let mut outpoints = Vec::with_capacity(self.inputs.len());
490496
for (o, _) in self.inputs.iter() {
@@ -496,11 +502,13 @@ impl PackageTemplate {
496502
match self.malleability {
497503
PackageMalleability::Malleable => {
498504
let mut split_package = None;
505+
let timelock = self.absolute_timelock;
499506
self.inputs.retain(|outp| {
500507
if *split_outp == outp.0 {
501508
split_package = Some(PackageTemplate {
502509
inputs: vec![(outp.0, outp.1.clone())],
503-
malleability: PackageMalleability::Malleable
510+
malleability: PackageMalleability::Malleable,
511+
absolute_timelock: timelock,
504512
});
505513
return false;
506514
}
@@ -530,6 +538,10 @@ impl PackageTemplate {
530538
if lead_category != v.category() { panic!("Merging outputs from differing categories !"); }
531539
self.inputs.push((k, v));
532540
}
541+
//TODO: verify coverage and sanity?
542+
if self.absolute_timelock > merge_from.absolute_timelock {
543+
self.absolute_timelock = merge_from.absolute_timelock;
544+
}
533545
}
534546
pub(crate) fn package_amount(&self) -> u64 {
535547
let mut amounts = 0;
@@ -602,12 +614,13 @@ impl PackageTemplate {
602614
},
603615
}
604616
}
605-
pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, malleability: PackageMalleability) -> Self {
617+
pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, malleability: PackageMalleability, absolute_timelock: u32) -> Self {
606618
let mut inputs = Vec::with_capacity(1);
607619
inputs.push((BitcoinOutPoint { txid, vout }, input_solving_data));
608620
PackageTemplate {
609621
inputs,
610-
malleability
622+
malleability,
623+
absolute_timelock
611624
}
612625
}
613626
}
@@ -620,6 +633,7 @@ impl Writeable for PackageTemplate {
620633
rev_outp.write(writer)?;
621634
}
622635
self.malleability.write(writer)?;
636+
self.absolute_timelock.write(writer)?;
623637
Ok(())
624638
}
625639
}
@@ -634,9 +648,11 @@ impl Readable for PackageTemplate {
634648
inputs.push((outpoint, rev_outp));
635649
}
636650
let malleability = Readable::read(reader)?;
651+
let absolute_timelock = Readable::read(reader)?;
637652
Ok(PackageTemplate {
638653
inputs,
639-
malleability
654+
malleability,
655+
absolute_timelock
640656
})
641657
}
642658
}
@@ -672,9 +688,6 @@ pub struct OnchainRequest {
672688
// At every block tick, used to check if pending claiming tx is taking too
673689
// much time for confirmation and we need to bump it.
674690
pub(crate) height_timer: Option<u32>,
675-
// Block height before which claiming is exclusive to one party,
676-
// after reaching it, claiming may be contentious.
677-
pub(crate) absolute_timelock: u32,
678691
// Tracked in case of reorg to wipe out now-superflous request.
679692
pub(crate) height_original: u32,
680693
// Content of request.
@@ -683,18 +696,7 @@ pub struct OnchainRequest {
683696

684697
impl OnchainRequest {
685698
pub(crate) fn request_merge(&mut self, req: OnchainRequest) {
686-
// We init default onchain request with first merge content
687-
if self.absolute_timelock == ::std::u32::MAX {
688-
println!("Init merging {}", req.height_original);
689-
self.height_original = req.height_original;
690-
self.content = req.content;
691-
self.absolute_timelock = req.absolute_timelock;
692-
return;
693-
}
694699
assert_eq!(self.height_original, req.height_original);
695-
if self.absolute_timelock > req.absolute_timelock {
696-
self.absolute_timelock = req.absolute_timelock;
697-
}
698700
self.content.merge_package(req.content);
699701
}
700702
}
@@ -704,7 +706,6 @@ impl Writeable for OnchainRequest {
704706
self.aggregation.write(writer)?;
705707
self.feerate_previous.write(writer)?;
706708
self.height_timer.write(writer)?;
707-
self.absolute_timelock.write(writer)?;
708709
self.height_original.write(writer)?;
709710
self.content.write(writer)?;
710711

@@ -717,15 +718,13 @@ impl Readable for OnchainRequest {
717718
let aggregation = Readable::read(reader)?;
718719
let feerate_previous = Readable::read(reader)?;
719720
let height_timer = Readable::read(reader)?;
720-
let absolute_timelock = Readable::read(reader)?;
721721
let height_original = Readable::read(reader)?;
722722
let content = Readable::read(reader)?;
723723

724724
Ok(OnchainRequest {
725725
aggregation,
726726
feerate_previous,
727727
height_timer,
728-
absolute_timelock,
729728
height_original,
730729
content
731730
})

lightning/src/chain/onchaintx.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
332332

333333
// Compute new height timer to decide when we need to regenerate a new bumped version of the claim tx (if we
334334
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
335-
let new_timer = Some(Self::get_height_timer(height, cached_request.absolute_timelock));
335+
let new_timer = Some(Self::get_height_timer(height, cached_request.content.timelock()));
336336
let amt = cached_request.content.package_amount();
337337
if cached_request.content.is_malleable() {
338338
let predicted_weight = cached_request.content.package_weight(&self.destination_script);
@@ -369,14 +369,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
369369
let mut preprocessed_requests = Vec::with_capacity(requests.len());
370370
let mut aggregated_request = None;
371371

372-
// Try to aggregate outputs if their timelock expiration isn't imminent (absolute_timelock
372+
// Try to aggregate outputs if their timelock expiration isn't imminent (package timelock
373373
// <= CLTV_SHARED_CLAIM_BUFFER) and they don't require an immediate nLockTime (aggregable).
374374
for req in requests {
375375
// Don't claim a outpoint twice that would be bad for privacy and may uselessly lock a CPFP input for a while
376376
if let Some(_) = self.claimable_outpoints.get(req.content.outpoints()[0]) { log_trace!(logger, "Bouncing off outpoint {}:{}, already registered its claiming request", req.content.outpoints()[0].txid, req.content.outpoints()[0].vout); } else {
377-
log_trace!(logger, "Test if outpoint can be aggregated with expiration {} against {}", req.absolute_timelock, height + CLTV_SHARED_CLAIM_BUFFER);
378-
if req.absolute_timelock <= height + CLTV_SHARED_CLAIM_BUFFER || !req.aggregation {
379-
// Don't aggregate if outpoint absolute timelock is soon or marked as non-aggregable
377+
log_trace!(logger, "Test if outpoint can be aggregated with expiration {} against {}", req.content.timelock(), height + CLTV_SHARED_CLAIM_BUFFER);
378+
if req.content.timelock() <= height + CLTV_SHARED_CLAIM_BUFFER || !req.aggregation {
379+
// Don't aggregate if outpoint package timelock is soon or marked as non-aggregable
380380
preprocessed_requests.push(req);
381381
} else if aggregated_request.is_none() {
382382
aggregated_request = Some(req);

0 commit comments

Comments
 (0)