Skip to content

Commit a0840cb

Browse files
author
Antoine Riard
committed
-f Dry-up aggregation from OnchainRequest to PackageTemplate
1 parent 8b27973 commit a0840cb

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
@@ -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, 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});
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, true);
1466+
claimable_outpoints.push(OnchainRequest { 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, htlc.cltv_expiry);
1480-
claimable_outpoints.push(OnchainRequest { aggregation: true, feerate_previous: 0, height_timer: None, 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, true);
1480+
claimable_outpoints.push(OnchainRequest { 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, 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 });
1629+
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 });
1630+
claimable_outpoints.push(OnchainRequest { 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, 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 });
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, true);
1663+
let claimable_outpoints = vec!(OnchainRequest { 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, height);
1688-
claim_requests.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, 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, false);
1688+
claim_requests.push(OnchainRequest { 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, height);
1897-
claimable_outpoints.push(OnchainRequest { aggregation: false, feerate_previous: 0, height_timer: None, 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, false);
1897+
claimable_outpoints.push(OnchainRequest { 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));
@@ -2664,9 +2664,9 @@ mod tests {
26642664
use hex;
26652665
use chain::channelmonitor::ChannelMonitor;
26662666
use chain::transaction::OutPoint;
2667+
use chain::onchain_utils;
2668+
use chain::onchain_utils::InputDescriptors;
26672669
use ln::channelmanager::{PaymentPreimage, PaymentHash};
2668-
use ln::onchain_utils;
2669-
use ln::onchain_utils::InputDescriptors;
26702670
use ln::chan_utils;
26712671
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
26722672
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
@@ -375,7 +375,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
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 {
377377
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 {
378+
if req.content.timelock() <= height + CLTV_SHARED_CLAIM_BUFFER || !req.content.aggregation() {
379379
// 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() {

0 commit comments

Comments
 (0)