Skip to content

Commit cf66eb8

Browse files
committed
Move ECDSA-specific signers into ecdsa.rs
To separate out the logic in the `sign` module, which will start to be convoluted with multiple signer types, we're splitting out each signer type into its own submodule, following the taproot.rs example from a previous commit.
1 parent 9d425b0 commit cf66eb8

15 files changed

+199
-177
lines changed

lightning/src/chain/chainmonitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::chain::{ChannelMonitorUpdateStatus, Filter, WatchedOutput};
3131
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
3232
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs, LATENCY_GRACE_PERIOD_BLOCKS};
3333
use crate::chain::transaction::{OutPoint, TransactionData};
34-
use crate::sign::WriteableEcdsaChannelSigner;
34+
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
3535
use crate::events;
3636
use crate::events::{Event, EventHandler};
3737
use crate::util::atomic_counter::AtomicCounter;

lightning/src/chain/channelmonitor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use crate::chain;
4242
use crate::chain::{BestBlock, WatchedOutput};
4343
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
4444
use crate::chain::transaction::{OutPoint, TransactionData};
45-
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, WriteableEcdsaChannelSigner, SignerProvider, EntropySource};
45+
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, ecdsa::WriteableEcdsaChannelSigner, SignerProvider, EntropySource};
4646
use crate::chain::onchaintx::{ClaimEvent, OnchainTxHandler};
4747
use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
4848
use crate::chain::Filter;
@@ -1458,7 +1458,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
14581458
/// to the commitment transaction being revoked, this will return a signed transaction, but
14591459
/// the signature will not be valid.
14601460
///
1461-
/// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::EcdsaChannelSigner::sign_justice_revoked_output
1461+
/// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::ecdsa::EcdsaChannelSigner::sign_justice_revoked_output
14621462
/// [`Persist`]: crate::chain::chainmonitor::Persist
14631463
pub fn sign_to_local_justice_tx(&self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
14641464
self.inner.lock().unwrap().sign_to_local_justice_tx(justice_tx, input_idx, value, commitment_number)

lightning/src/chain/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use bitcoin::network::constants::Network;
1717
use bitcoin::secp256k1::PublicKey;
1818

1919
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, MonitorEvent};
20-
use crate::sign::WriteableEcdsaChannelSigner;
20+
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
2121
use crate::chain::transaction::{OutPoint, TransactionData};
2222

2323
use crate::prelude::*;

lightning/src/chain/onchaintx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
2323
use bitcoin::secp256k1;
2424

2525
use crate::chain::chaininterface::compute_feerate_sat_per_1000_weight;
26-
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ChannelSigner, EntropySource, SignerProvider, WriteableEcdsaChannelSigner};
26+
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ChannelSigner, EntropySource, SignerProvider, ecdsa::WriteableEcdsaChannelSigner};
2727
use crate::ln::msgs::DecodeError;
2828
use crate::ln::PaymentPreimage;
2929
use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction};

lightning/src/chain/package.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment};
2525
use crate::ln::chan_utils;
2626
use crate::ln::msgs::DecodeError;
2727
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT, compute_feerate_sat_per_1000_weight, FEERATE_FLOOR_SATS_PER_KW};
28-
use crate::sign::WriteableEcdsaChannelSigner;
28+
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
2929
use crate::chain::onchaintx::{ExternalHTLCClaim, OnchainTxHandler};
3030
use crate::util::logger::Logger;
3131
use crate::util::ser::{Readable, Writer, Writeable, RequiredWrapper};

lightning/src/events/bump_transaction.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use crate::ln::chan_utils::{
2525
};
2626
use crate::prelude::*;
2727
use crate::sign::{
28-
ChannelDerivationParameters, HTLCDescriptor, EcdsaChannelSigner, SignerProvider,
29-
WriteableEcdsaChannelSigner, P2WPKH_WITNESS_WEIGHT
28+
ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT
3029
};
30+
use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
3131
use crate::sync::Mutex;
3232
use crate::util::logger::Logger;
3333

@@ -141,8 +141,8 @@ pub enum BumpTransactionEvent {
141141
/// an empty `pending_htlcs`), confirmation of the commitment transaction can be considered to
142142
/// be not urgent.
143143
///
144-
/// [`EcdsaChannelSigner`]: crate::sign::EcdsaChannelSigner
145-
/// [`EcdsaChannelSigner::sign_holder_anchor_input`]: crate::sign::EcdsaChannelSigner::sign_holder_anchor_input
144+
/// [`EcdsaChannelSigner`]: crate::sign::ecdsa::EcdsaChannelSigner
145+
/// [`EcdsaChannelSigner::sign_holder_anchor_input`]: crate::sign::ecdsa::EcdsaChannelSigner::sign_holder_anchor_input
146146
/// [`build_anchor_input_witness`]: crate::ln::chan_utils::build_anchor_input_witness
147147
ChannelClose {
148148
/// The unique identifier for the claim of the anchor output in the commitment transaction.
@@ -195,8 +195,8 @@ pub enum BumpTransactionEvent {
195195
/// longer able to commit external confirmed funds to the HTLC transaction or the fee committed
196196
/// to the HTLC transaction is greater in value than the HTLCs being claimed.
197197
///
198-
/// [`EcdsaChannelSigner`]: crate::sign::EcdsaChannelSigner
199-
/// [`EcdsaChannelSigner::sign_holder_htlc_transaction`]: crate::sign::EcdsaChannelSigner::sign_holder_htlc_transaction
198+
/// [`EcdsaChannelSigner`]: crate::sign::ecdsa::EcdsaChannelSigner
199+
/// [`EcdsaChannelSigner::sign_holder_htlc_transaction`]: crate::sign::ecdsa::EcdsaChannelSigner::sign_holder_htlc_transaction
200200
HTLCResolution {
201201
/// The unique identifier for the claim of the HTLCs in the confirmed commitment
202202
/// transaction.

lightning/src/ln/channel.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ use crate::chain::BestBlock;
3636
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
3737
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID};
3838
use crate::chain::transaction::{OutPoint, TransactionData};
39-
use crate::sign::{EcdsaChannelSigner, WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
39+
use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
40+
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
4041
use crate::events::ClosureReason;
4142
use crate::routing::gossip::NodeId;
4243
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
@@ -8352,7 +8353,7 @@ mod tests {
83528353
use bitcoin::hashes::hex::FromHex;
83538354
use bitcoin::hash_types::Txid;
83548355
use bitcoin::secp256k1::Message;
8355-
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, EcdsaChannelSigner};
8356+
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ecdsa::EcdsaChannelSigner};
83568357
use crate::ln::PaymentPreimage;
83578358
use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys};
83588359
use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};

lightning/src/ln/channelmanager.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
6464
use crate::offers::parse::Bolt12SemanticError;
6565
use crate::offers::refund::{Refund, RefundBuilder};
6666
use crate::onion_message::{Destination, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
67-
use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, WriteableEcdsaChannelSigner};
67+
use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider};
68+
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
6869
use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
6970
use crate::util::wakers::{Future, Notifier};
7071
use crate::util::scid_utils::fake_scid;

lightning/src/ln/functional_tests.rs

+1-1
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::{EcdsaChannelSigner, EntropySource, SignerProvider};
20+
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, 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};

lightning/src/ln/monitor_tests.rs

+1-1
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::{EcdsaChannelSigner, SpendableOutputDescriptor};
12+
use crate::sign::{ecdsa::EcdsaChannelSigner, 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/sign/ecdsa.rs

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//! Defines ECDSA-specific signer types.
2+
3+
use bitcoin::blockdata::transaction::Transaction;
4+
5+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
6+
use bitcoin::secp256k1::ecdsa::Signature;
7+
use bitcoin::secp256k1;
8+
9+
use crate::util::ser::Writeable;
10+
use crate::ln::PaymentPreimage;
11+
use crate::ln::chan_utils::{HTLCOutputInCommitment, HolderCommitmentTransaction, CommitmentTransaction, ClosingTransaction};
12+
use crate::ln::msgs::UnsignedChannelAnnouncement;
13+
14+
use crate::prelude::*;
15+
use crate::sign::{ChannelSigner, HTLCDescriptor};
16+
17+
/// A trait to sign Lightning channel transactions as described in
18+
/// [BOLT 3](https://github.com/lightning/bolts/blob/master/03-transactions.md).
19+
///
20+
/// Signing services could be implemented on a hardware wallet and should implement signing
21+
/// policies in order to be secure. Please refer to the [VLS Policy
22+
/// Controls](https://gitlab.com/lightning-signer/validating-lightning-signer/-/blob/main/docs/policy-controls.md)
23+
/// for an example of such policies.
24+
pub trait EcdsaChannelSigner: ChannelSigner {
25+
/// Create a signature for a counterparty's commitment transaction and associated HTLC transactions.
26+
///
27+
/// Note that if signing fails or is rejected, the channel will be force-closed.
28+
///
29+
/// Policy checks should be implemented in this function, including checking the amount
30+
/// sent to us and checking the HTLCs.
31+
///
32+
/// The preimages of outgoing HTLCs that were fulfilled since the last commitment are provided.
33+
/// A validating signer should ensure that an HTLC output is removed only when the matching
34+
/// preimage is provided, or when the value to holder is restored.
35+
///
36+
/// Note that all the relevant preimages will be provided, but there may also be additional
37+
/// irrelevant or duplicate preimages.
38+
//
39+
// TODO: Document the things someone using this interface should enforce before signing.
40+
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction,
41+
preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>
42+
) -> Result<(Signature, Vec<Signature>), ()>;
43+
/// Validate the counterparty's revocation.
44+
///
45+
/// This is required in order for the signer to make sure that the state has moved
46+
/// forward and it is safe to sign the next counterparty commitment.
47+
fn validate_counterparty_revocation(&self, idx: u64, secret: &SecretKey) -> Result<(), ()>;
48+
/// Creates a signature for a holder's commitment transaction.
49+
///
50+
/// This will be called
51+
/// - with a non-revoked `commitment_tx`.
52+
/// - with the latest `commitment_tx` when we initiate a force-close.
53+
///
54+
/// This may be called multiple times for the same transaction.
55+
///
56+
/// An external signer implementation should check that the commitment has not been revoked.
57+
//
58+
// TODO: Document the things someone using this interface should enforce before signing.
59+
fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction,
60+
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
61+
/// Same as [`sign_holder_commitment`], but exists only for tests to get access to holder
62+
/// commitment transactions which will be broadcasted later, after the channel has moved on to a
63+
/// newer state. Thus, needs its own method as [`sign_holder_commitment`] may enforce that we
64+
/// only ever get called once.
65+
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
66+
fn unsafe_sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction,
67+
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
68+
/// Create a signature for the given input in a transaction spending an HTLC transaction output
69+
/// or a commitment transaction `to_local` output when our counterparty broadcasts an old state.
70+
///
71+
/// A justice transaction may claim multiple outputs at the same time if timelocks are
72+
/// similar, but only a signature for the input at index `input` should be signed for here.
73+
/// It may be called multiple times for same output(s) if a fee-bump is needed with regards
74+
/// to an upcoming timelock expiration.
75+
///
76+
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
77+
///
78+
/// `per_commitment_key` is revocation secret which was provided by our counterparty when they
79+
/// revoked the state which they eventually broadcast. It's not a _holder_ secret key and does
80+
/// not allow the spending of any funds by itself (you need our holder `revocation_secret` to do
81+
/// so).
82+
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64,
83+
per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>
84+
) -> Result<Signature, ()>;
85+
/// Create a signature for the given input in a transaction spending a commitment transaction
86+
/// HTLC output when our counterparty broadcasts an old state.
87+
///
88+
/// A justice transaction may claim multiple outputs at the same time if timelocks are
89+
/// similar, but only a signature for the input at index `input` should be signed for here.
90+
/// It may be called multiple times for same output(s) if a fee-bump is needed with regards
91+
/// to an upcoming timelock expiration.
92+
///
93+
/// `amount` is the value of the output spent by this input, committed to in the BIP 143
94+
/// signature.
95+
///
96+
/// `per_commitment_key` is revocation secret which was provided by our counterparty when they
97+
/// revoked the state which they eventually broadcast. It's not a _holder_ secret key and does
98+
/// not allow the spending of any funds by itself (you need our holder revocation_secret to do
99+
/// so).
100+
///
101+
/// `htlc` holds HTLC elements (hash, timelock), thus changing the format of the witness script
102+
/// (which is committed to in the BIP 143 signatures).
103+
fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64,
104+
per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment,
105+
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
106+
/// Computes the signature for a commitment transaction's HTLC output used as an input within
107+
/// `htlc_tx`, which spends the commitment transaction at index `input`. The signature returned
108+
/// must be be computed using [`EcdsaSighashType::All`].
109+
///
110+
/// Note that this may be called for HTLCs in the penultimate commitment transaction if a
111+
/// [`ChannelMonitor`] [replica](https://github.com/lightningdevkit/rust-lightning/blob/main/GLOSSARY.md#monitor-replicas)
112+
/// broadcasts it before receiving the update for the latest commitment transaction.
113+
///
114+
/// [`EcdsaSighashType::All`]: bitcoin::blockdata::transaction::EcdsaSighashType::All
115+
/// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
116+
fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize,
117+
htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1<secp256k1::All>
118+
) -> Result<Signature, ()>;
119+
/// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment
120+
/// transaction, either offered or received.
121+
///
122+
/// Such a transaction may claim multiples offered outputs at same time if we know the
123+
/// preimage for each when we create it, but only the input at index `input` should be
124+
/// signed for here. It may be called multiple times for same output(s) if a fee-bump is
125+
/// needed with regards to an upcoming timelock expiration.
126+
///
127+
/// `witness_script` is either an offered or received script as defined in BOLT3 for HTLC
128+
/// outputs.
129+
///
130+
/// `amount` is value of the output spent by this input, committed to in the BIP 143 signature.
131+
///
132+
/// `per_commitment_point` is the dynamic point corresponding to the channel state
133+
/// detected onchain. It has been generated by our counterparty and is used to derive
134+
/// channel state keys, which are then included in the witness script and committed to in the
135+
/// BIP 143 signature.
136+
fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64,
137+
per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment,
138+
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
139+
/// Create a signature for a (proposed) closing transaction.
140+
///
141+
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
142+
/// chosen to forgo their output as dust.
143+
fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction,
144+
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
145+
/// Computes the signature for a commitment transaction's anchor output used as an
146+
/// input within `anchor_tx`, which spends the commitment transaction, at index `input`.
147+
fn sign_holder_anchor_input(
148+
&self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1<secp256k1::All>,
149+
) -> Result<Signature, ()>;
150+
/// Signs a channel announcement message with our funding key proving it comes from one of the
151+
/// channel participants.
152+
///
153+
/// Channel announcements also require a signature from each node's network key. Our node
154+
/// signature is computed through [`NodeSigner::sign_gossip_message`].
155+
///
156+
/// Note that if this fails or is rejected, the channel will not be publicly announced and
157+
/// our counterparty may (though likely will not) close the channel on us for violating the
158+
/// protocol.
159+
///
160+
/// [`NodeSigner::sign_gossip_message`]: crate::sign::NodeSigner::sign_gossip_message
161+
fn sign_channel_announcement_with_funding_key(
162+
&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>
163+
) -> Result<Signature, ()>;
164+
}
165+
166+
/// A writeable signer.
167+
///
168+
/// There will always be two instances of a signer per channel, one occupied by the
169+
/// [`ChannelManager`] and another by the channel's [`ChannelMonitor`].
170+
///
171+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
172+
/// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
173+
pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable {}

0 commit comments

Comments
 (0)