Skip to content

Commit 90fd429

Browse files
author
Antoine Riard
committed
-f Dry-up aggregation from OnchainRequest to PackageTemplate
1 parent a01942b commit 90fd429

File tree

3 files changed

+37
-27
lines changed

3 files changed

+37
-27
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,8 +1582,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15821582
for (idx, outp) in tx.output.iter().enumerate() {
15831583
if outp.script_pubkey == revokeable_p2wsh {
15841584
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);
1585-
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);
1586-
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
1585+
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, true);
1586+
claimable_outpoints.push(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
15871587
}
15881588
}
15891589

@@ -1596,8 +1596,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15961596
return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
15971597
}
15981598
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);
1599-
let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable, htlc.cltv_expiry);
1600-
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
1599+
let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedOutput(revk_outp), PackageMalleability::Malleable, htlc.cltv_expiry, true);
1600+
claimable_outpoints.push(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: height, content: justice_package});
16011601
}
16021602
}
16031603
}
@@ -1745,8 +1745,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
17451745
let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
17461746
if preimage.is_some() || !htlc.offered {
17471747
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());
1748-
let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::CounterpartyHTLCOutput(counterparty_htlc_outp), PackageMalleability::Malleable, htlc.cltv_expiry);
1749-
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 });
1748+
let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::CounterpartyHTLCOutput(counterparty_htlc_outp), PackageMalleability::Malleable, htlc.cltv_expiry, if !htlc.offered { false } else { true });
1749+
claimable_outpoints.push(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: /*XXX(ariard) Option<height> */ 0, content: counterparty_package });
17501750
}
17511751
}
17521752
}
@@ -1778,8 +1778,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
17781778

17791779
log_trace!(logger, "Counterparty HTLC broadcast {}:{}", htlc_txid, 0);
17801780
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);
1781-
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);
1782-
let claimable_outpoints = vec!(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, height_original: height, content: justice_package });
1781+
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, true);
1782+
let claimable_outpoints = vec!(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: height, content: justice_package });
17831783
let outputs = vec![(0, tx.output[0].clone())];
17841784
(claimable_outpoints, Some((htlc_txid, outputs)))
17851785
}
@@ -1803,8 +1803,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18031803
continue;
18041804
}
18051805
} else { None }, htlc.amount_msat);
1806-
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), PackageMalleability::Untractable, height);
1807-
claim_requests.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, height_original: height, content: htlc_package });
1806+
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), PackageMalleability::Untractable, height, false);
1807+
claim_requests.push(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: height, content: htlc_package });
18081808
}
18091809
}
18101810

@@ -2077,8 +2077,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20772077
let should_broadcast = self.would_broadcast_at_height(height, &logger);
20782078
if should_broadcast {
20792079
let funding_outp = HolderFundingOutput::build(self.funding_redeemscript.clone());
2080-
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);
2081-
claimable_outpoints.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, height_original: height, content: commitment_package });
2080+
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, false);
2081+
claimable_outpoints.push(OnchainRequest { feerate_previous: 0, height_timer: None, height_original: height, content: commitment_package });
20822082
self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));
20832083
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
20842084
self.holder_tx_signed = true;
@@ -2891,8 +2891,8 @@ mod tests {
28912891
use chain::channelmonitor::ChannelMonitor;
28922892
use chain::transaction::OutPoint;
28932893
use ln::channelmanager::{BestBlock, PaymentPreimage, PaymentHash};
2894-
use ln::onchain_utils;
2895-
use ln::onchain_utils::InputDescriptors;
2894+
use chain::onchain_utils;
2895+
use chain::onchain_utils::InputDescriptors;
28962896
use ln::chan_utils;
28972897
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
28982898
use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};

lightning/src/chain/onchain_utils.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,13 @@ pub(crate) struct PackageTemplate {
482482
// Block height before which claiming is exclusive to one party,
483483
// after reaching it, claiming may be contentious.
484484
absolute_timelock: u32,
485+
// Timeout tx must have nLocktime set which means aggregating multiple
486+
// ones must take the higher nLocktime among them to satisfy all of them.
487+
// Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
488+
// of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
489+
// To simplify we mark them as non-aggregable.
490+
aggregation: bool,
491+
485492
}
486493

487494
impl PackageTemplate {
@@ -491,6 +498,9 @@ impl PackageTemplate {
491498
pub(crate) fn timelock(&self) -> u32 {
492499
self.absolute_timelock
493500
}
501+
pub(crate) fn aggregation(&self) -> bool {
502+
self.aggregation
503+
}
494504
pub(crate) fn outpoints(&self) -> Vec<&BitcoinOutPoint> {
495505
let mut outpoints = Vec::with_capacity(self.inputs.len());
496506
for (o, _) in self.inputs.iter() {
@@ -503,12 +513,14 @@ impl PackageTemplate {
503513
PackageMalleability::Malleable => {
504514
let mut split_package = None;
505515
let timelock = self.absolute_timelock;
516+
let aggregation = self.aggregation;
506517
self.inputs.retain(|outp| {
507518
if *split_outp == outp.0 {
508519
split_package = Some(PackageTemplate {
509520
inputs: vec![(outp.0, outp.1.clone())],
510521
malleability: PackageMalleability::Malleable,
511522
absolute_timelock: timelock,
523+
aggregation,
512524
});
513525
return false;
514526
}
@@ -530,6 +542,9 @@ impl PackageTemplate {
530542
if self.malleability == PackageMalleability::Untractable || merge_from.malleability == PackageMalleability::Untractable {
531543
panic!("Merging template on untractable packages");
532544
}
545+
if !self.aggregation || !merge_from.aggregation {
546+
panic!("Merging non aggregatable packages");
547+
}
533548
let lead_category;
534549
if let Some((_, lead_input)) = self.inputs.first() {
535550
lead_category = lead_input.category();
@@ -614,13 +629,14 @@ impl PackageTemplate {
614629
},
615630
}
616631
}
617-
pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, malleability: PackageMalleability, absolute_timelock: u32) -> Self {
632+
pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, malleability: PackageMalleability, absolute_timelock: u32, aggregation: bool) -> Self {
618633
let mut inputs = Vec::with_capacity(1);
619634
inputs.push((BitcoinOutPoint { txid, vout }, input_solving_data));
620635
PackageTemplate {
621636
inputs,
622637
malleability,
623-
absolute_timelock
638+
absolute_timelock,
639+
aggregation
624640
}
625641
}
626642
}
@@ -634,6 +650,7 @@ impl Writeable for PackageTemplate {
634650
}
635651
self.malleability.write(writer)?;
636652
self.absolute_timelock.write(writer)?;
653+
self.aggregation.write(writer)?;
637654
Ok(())
638655
}
639656
}
@@ -649,10 +666,12 @@ impl Readable for PackageTemplate {
649666
}
650667
let malleability = Readable::read(reader)?;
651668
let absolute_timelock = Readable::read(reader)?;
669+
let aggregation = Readable::read(reader)?;
652670
Ok(PackageTemplate {
653671
inputs,
654672
malleability,
655-
absolute_timelock
673+
absolute_timelock,
674+
aggregation
656675
})
657676
}
658677
}
@@ -676,12 +695,6 @@ impl Readable for PackageTemplate {
676695
/// Content embeds transactions elements to generate transaction. See PackageTemplate.
677696
#[derive(PartialEq, Clone)]
678697
pub struct OnchainRequest {
679-
// Timeout tx must have nLocktime set which means aggregating multiple
680-
// ones must take the higher nLocktime among them to satisfy all of them.
681-
// Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
682-
// of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
683-
// Do simplify we mark them as non-aggregable.
684-
pub(crate) aggregation: bool,
685698
// Based feerate of previous broadcast. If resources available (either
686699
// output value or utxo bumping).
687700
pub(crate) feerate_previous: u64,
@@ -703,7 +716,6 @@ impl OnchainRequest {
703716

704717
impl Writeable for OnchainRequest {
705718
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
706-
self.aggregation.write(writer)?;
707719
self.feerate_previous.write(writer)?;
708720
self.height_timer.write(writer)?;
709721
self.height_original.write(writer)?;
@@ -715,14 +727,12 @@ impl Writeable for OnchainRequest {
715727

716728
impl Readable for OnchainRequest {
717729
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
718-
let aggregation = Readable::read(reader)?;
719730
let feerate_previous = Readable::read(reader)?;
720731
let height_timer = Readable::read(reader)?;
721732
let height_original = Readable::read(reader)?;
722733
let content = Readable::read(reader)?;
723734

724735
Ok(OnchainRequest {
725-
aggregation,
726736
feerate_previous,
727737
height_timer,
728738
height_original,

lightning/src/chain/onchaintx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
390390
// Don't claim a outpoint twice that would be bad for privacy and may uselessly lock a CPFP input for a while
391391
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 {
392392
log_trace!(logger, "Test if outpoint can be aggregated with expiration {} against {}", req.content.timelock(), height + CLTV_SHARED_CLAIM_BUFFER);
393-
if req.content.timelock() <= height + CLTV_SHARED_CLAIM_BUFFER || !req.aggregation {
393+
if req.content.timelock() <= height + CLTV_SHARED_CLAIM_BUFFER || !req.content.aggregation() {
394394
// Don't aggregate if outpoint package timelock is soon or marked as non-aggregable
395395
preprocessed_requests.push(req);
396396
} else if aggregated_request.is_none() {

0 commit comments

Comments
 (0)