Skip to content

Commit d8021c7

Browse files
committed
Introduce OutputSpender trait and implement for (Phantom)KeysManager
.. we move `spend_spendable_outputs` to a new trait which we can easily reuse in `OutputSweeper` later.
1 parent ac9a2c8 commit d8021c7

File tree

4 files changed

+84
-64
lines changed

4 files changed

+84
-64
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1717
use crate::chain::channelmonitor;
1818
use crate::chain::channelmonitor::{CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
1919
use crate::chain::transaction::OutPoint;
20-
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, SignerProvider};
20+
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
2121
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
2222
use crate::ln::{ChannelId, PaymentPreimage, PaymentSecret, PaymentHash};
2323
use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY, ChannelPhase};
@@ -9951,9 +9951,9 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
99519951
let dust_outbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat;
99529952

99539953
// Substract 3 sats for multiplier and 2 sats for fixed limit to make sure we are 50% below the dust limit.
9954-
// This is to make sure we fully use the dust limit. If we don't, we could end up with `dust_ibd_htlc_on_holder_tx` being 1
9954+
// This is to make sure we fully use the dust limit. If we don't, we could end up with `dust_ibd_htlc_on_holder_tx` being 1
99559955
// while `max_dust_htlc_exposure_msat` is not equal to `dust_outbound_htlc_on_holder_tx_msat`.
9956-
let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - if multiplier_dust_limit { 3 } else { 2 }) * 1000;
9956+
let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - if multiplier_dust_limit { 3 } else { 2 }) * 1000;
99579957
let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat;
99589958

99599959
let dust_htlc_on_counterparty_tx: u64 = 4;

lightning/src/ln/monitor_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
//! Further functional tests which test blockchain reorganizations.
1111
12-
use crate::sign::{ecdsa::EcdsaChannelSigner, SpendableOutputDescriptor};
12+
use crate::sign::{ecdsa::EcdsaChannelSigner, OutputSpender, SpendableOutputDescriptor};
1313
use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS, Balance};
1414
use crate::chain::transaction::OutPoint;
1515
use crate::chain::chaininterface::{LowerBoundedFeeEstimator, compute_feerate_sat_per_1000_weight};

lightning/src/ln/reorg_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::chain::transaction::OutPoint;
1515
use crate::chain::Confirm;
1616
use crate::events::{Event, MessageSendEventsProvider, ClosureReason, HTLCDestination, MessageSendEvent};
1717
use crate::ln::msgs::{ChannelMessageHandler, Init};
18+
use crate::sign::OutputSpender;
1819
use crate::util::test_utils;
1920
use crate::util::ser::Writeable;
2021
use crate::util::string::UntrustedString;

lightning/src/sign/mod.rs

Lines changed: 79 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,28 @@ pub trait NodeSigner {
805805
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()>;
806806
}
807807

808+
/// A trait that describes a wallet capable of creating a spending [`Transaction`] from a set of
809+
/// [`SpendableOutputDescriptor`]s.
810+
pub trait OutputSpender {
811+
/// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
812+
/// output to the given change destination (if sufficient change value remains). The
813+
/// transaction will have a feerate, at least, of the given value.
814+
///
815+
/// The `locktime` argument is used to set the transaction's locktime. If `None`, the
816+
/// transaction will have a locktime of 0. It it recommended to set this to the current block
817+
/// height to avoid fee sniping, unless you have some specific reason to use a different
818+
/// locktime.
819+
///
820+
/// Returns `Err(())` if the output value is greater than the input value minus required fee,
821+
/// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
822+
/// does not match the one we can spend.
823+
fn spend_spendable_outputs<C: Signing>(
824+
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
825+
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
826+
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
827+
) -> Result<Transaction, ()>;
828+
}
829+
808830
// Primarily needed in doctests because of https://github.com/rust-lang/rust/issues/67295
809831
/// A dynamic [`SignerProvider`] temporarily needed for doc tests.
810832
#[cfg(taproot)]
@@ -1991,50 +2013,6 @@ impl KeysManager {
19912013

19922014
Ok(psbt)
19932015
}
1994-
1995-
/// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
1996-
/// output to the given change destination (if sufficient change value remains). The
1997-
/// transaction will have a feerate, at least, of the given value.
1998-
///
1999-
/// The `locktime` argument is used to set the transaction's locktime. If `None`, the
2000-
/// transaction will have a locktime of 0. It it recommended to set this to the current block
2001-
/// height to avoid fee sniping, unless you have some specific reason to use a different
2002-
/// locktime.
2003-
///
2004-
/// Returns `Err(())` if the output value is greater than the input value minus required fee,
2005-
/// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
2006-
/// does not match the one we can spend.
2007-
///
2008-
/// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
2009-
///
2010-
/// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
2011-
/// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
2012-
pub fn spend_spendable_outputs<C: Signing>(
2013-
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
2014-
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
2015-
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
2016-
) -> Result<Transaction, ()> {
2017-
let (mut psbt, expected_max_weight) =
2018-
SpendableOutputDescriptor::create_spendable_outputs_psbt(
2019-
descriptors,
2020-
outputs,
2021-
change_destination_script,
2022-
feerate_sat_per_1000_weight,
2023-
locktime,
2024-
)?;
2025-
psbt = self.sign_spendable_outputs_psbt(descriptors, psbt, secp_ctx)?;
2026-
2027-
let spend_tx = psbt.extract_tx();
2028-
2029-
debug_assert!(expected_max_weight >= spend_tx.weight().to_wu());
2030-
// Note that witnesses with a signature vary somewhat in size, so allow
2031-
// `expected_max_weight` to overshoot by up to 3 bytes per input.
2032-
debug_assert!(
2033-
expected_max_weight <= spend_tx.weight().to_wu() + descriptors.len() as u64 * 3
2034-
);
2035-
2036-
Ok(spend_tx)
2037-
}
20382016
}
20392017

20402018
impl EntropySource for KeysManager {
@@ -2106,6 +2084,44 @@ impl NodeSigner for KeysManager {
21062084
}
21072085
}
21082086

2087+
impl OutputSpender for KeysManager {
2088+
/// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
2089+
/// output to the given change destination (if sufficient change value remains).
2090+
///
2091+
/// See [`OutputSpender::spend_spendable_outputs`] documentation for more information.
2092+
///
2093+
/// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
2094+
///
2095+
/// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
2096+
/// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
2097+
fn spend_spendable_outputs<C: Signing>(
2098+
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
2099+
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
2100+
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
2101+
) -> Result<Transaction, ()> {
2102+
let (mut psbt, expected_max_weight) =
2103+
SpendableOutputDescriptor::create_spendable_outputs_psbt(
2104+
descriptors,
2105+
outputs,
2106+
change_destination_script,
2107+
feerate_sat_per_1000_weight,
2108+
locktime,
2109+
)?;
2110+
psbt = self.sign_spendable_outputs_psbt(descriptors, psbt, secp_ctx)?;
2111+
2112+
let spend_tx = psbt.extract_tx();
2113+
2114+
debug_assert!(expected_max_weight >= spend_tx.weight().to_wu());
2115+
// Note that witnesses with a signature vary somewhat in size, so allow
2116+
// `expected_max_weight` to overshoot by up to 3 bytes per input.
2117+
debug_assert!(
2118+
expected_max_weight <= spend_tx.weight().to_wu() + descriptors.len() as u64 * 3
2119+
);
2120+
2121+
Ok(spend_tx)
2122+
}
2123+
}
2124+
21092125
impl SignerProvider for KeysManager {
21102126
type EcdsaSigner = InMemorySigner;
21112127
#[cfg(taproot)]
@@ -2238,6 +2254,25 @@ impl NodeSigner for PhantomKeysManager {
22382254
}
22392255
}
22402256

2257+
impl OutputSpender for PhantomKeysManager {
2258+
/// See [`OutputSpender::spend_spendable_outputs`] and [`KeysManager::spend_spendable_outputs`]
2259+
/// for documentation on this method.
2260+
fn spend_spendable_outputs<C: Signing>(
2261+
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
2262+
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
2263+
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
2264+
) -> Result<Transaction, ()> {
2265+
self.inner.spend_spendable_outputs(
2266+
descriptors,
2267+
outputs,
2268+
change_destination_script,
2269+
feerate_sat_per_1000_weight,
2270+
locktime,
2271+
secp_ctx,
2272+
)
2273+
}
2274+
}
2275+
22412276
impl SignerProvider for PhantomKeysManager {
22422277
type EcdsaSigner = InMemorySigner;
22432278
#[cfg(taproot)]
@@ -2299,22 +2334,6 @@ impl PhantomKeysManager {
22992334
}
23002335
}
23012336

2302-
/// See [`KeysManager::spend_spendable_outputs`] for documentation on this method.
2303-
pub fn spend_spendable_outputs<C: Signing>(
2304-
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
2305-
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
2306-
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
2307-
) -> Result<Transaction, ()> {
2308-
self.inner.spend_spendable_outputs(
2309-
descriptors,
2310-
outputs,
2311-
change_destination_script,
2312-
feerate_sat_per_1000_weight,
2313-
locktime,
2314-
secp_ctx,
2315-
)
2316-
}
2317-
23182337
/// See [`KeysManager::derive_channel_keys`] for documentation on this method.
23192338
pub fn derive_channel_keys(
23202339
&self, channel_value_satoshis: u64, params: &[u8; 32],

0 commit comments

Comments
 (0)