Skip to content

Commit 12c2086

Browse files
authored
Merge pull request lightningdevkit#2753 from TheBlueMatt/2023-11-inbound-preimages
Provide inbound HTLC preimages to the `EcdsaChannelSigner`
2 parents 7f96446 + 262072d commit 12c2086

File tree

6 files changed

+44
-30
lines changed

6 files changed

+44
-30
lines changed

lightning/src/ln/channel.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,8 @@ struct CommitmentStats<'a> {
512512
htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
513513
local_balance_msat: u64, // local balance before fees but considering dust limits
514514
remote_balance_msat: u64, // remote balance before fees but considering dust limits
515-
preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
515+
outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
516+
inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
516517
}
517518

518519
/// Used when calculating whether we or the remote can afford an additional HTLC.
@@ -1428,6 +1429,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14281429
}
14291430
}
14301431

1432+
let mut inbound_htlc_preimages: Vec<PaymentPreimage> = Vec::new();
1433+
14311434
for ref htlc in self.pending_inbound_htlcs.iter() {
14321435
let (include, state_name) = match htlc.state {
14331436
InboundHTLCState::RemoteAnnounced(_) => (!generated_by_local, "RemoteAnnounced"),
@@ -1445,7 +1448,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14451448
match &htlc.state {
14461449
&InboundHTLCState::LocalRemoved(ref reason) => {
14471450
if generated_by_local {
1448-
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
1451+
if let &InboundHTLCRemovalReason::Fulfill(preimage) = reason {
1452+
inbound_htlc_preimages.push(preimage);
14491453
value_to_self_msat_offset += htlc.amount_msat as i64;
14501454
}
14511455
}
@@ -1455,7 +1459,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14551459
}
14561460
}
14571461

1458-
let mut preimages: Vec<PaymentPreimage> = Vec::new();
1462+
1463+
let mut outbound_htlc_preimages: Vec<PaymentPreimage> = Vec::new();
14591464

14601465
for ref htlc in self.pending_outbound_htlcs.iter() {
14611466
let (include, state_name) = match htlc.state {
@@ -1474,7 +1479,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14741479
};
14751480

14761481
if let Some(preimage) = preimage_opt {
1477-
preimages.push(preimage);
1482+
outbound_htlc_preimages.push(preimage);
14781483
}
14791484

14801485
if include {
@@ -1580,7 +1585,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
15801585
htlcs_included,
15811586
local_balance_msat: value_to_self_msat as u64,
15821587
remote_balance_msat: value_to_remote_msat as u64,
1583-
preimages
1588+
inbound_htlc_preimages,
1589+
outbound_htlc_preimages,
15841590
}
15851591
}
15861592

@@ -2178,7 +2184,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
21782184
let signature = match &self.holder_signer {
21792185
// TODO (taproot|arik): move match into calling method for Taproot
21802186
ChannelSignerType::Ecdsa(ecdsa) => {
2181-
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.secp_ctx)
2187+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx)
21822188
.map(|(sig, _)| sig).ok()?
21832189
},
21842190
// TODO (taproot|arik)
@@ -2216,7 +2222,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
22162222
match &self.holder_signer {
22172223
// TODO (arik): move match into calling method for Taproot
22182224
ChannelSignerType::Ecdsa(ecdsa) => {
2219-
let funding_signed = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.secp_ctx)
2225+
let funding_signed = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx)
22202226
.map(|(signature, _)| msgs::FundingSigned {
22212227
channel_id: self.channel_id(),
22222228
signature,
@@ -3247,7 +3253,7 @@ impl<SP: Deref> Channel<SP> where
32473253
self.context.counterparty_funding_pubkey()
32483254
);
32493255

3250-
self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.preimages)
3256+
self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages)
32513257
.map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?;
32523258

32533259
// Update state now that we've passed all the can-fail calls...
@@ -5780,8 +5786,12 @@ impl<SP: Deref> Channel<SP> where
57805786
htlcs.push(htlc);
57815787
}
57825788

5783-
let res = ecdsa.sign_counterparty_commitment(&commitment_stats.tx, commitment_stats.preimages, &self.context.secp_ctx)
5784-
.map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
5789+
let res = ecdsa.sign_counterparty_commitment(
5790+
&commitment_stats.tx,
5791+
commitment_stats.inbound_htlc_preimages,
5792+
commitment_stats.outbound_htlc_preimages,
5793+
&self.context.secp_ctx,
5794+
).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
57855795
signature = res.0;
57865796
htlc_signatures = res.1;
57875797

lightning/src/ln/functional_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ fn test_update_fee_that_funder_cannot_afford() {
746746
&mut htlcs,
747747
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
748748
);
749-
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap()
749+
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
750750
};
751751

752752
let commit_signed_msg = msgs::CommitmentSigned {
@@ -1494,7 +1494,7 @@ fn test_fee_spike_violation_fails_htlc() {
14941494
&mut vec![(accepted_htlc_info, ())],
14951495
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
14961496
);
1497-
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap()
1497+
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
14981498
};
14991499

15001500
let commit_signed_msg = msgs::CommitmentSigned {

lightning/src/sign/ecdsa.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,18 @@ pub trait EcdsaChannelSigner: ChannelSigner {
2929
/// Policy checks should be implemented in this function, including checking the amount
3030
/// sent to us and checking the HTLCs.
3131
///
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.
32+
/// The preimages of outbound and inbound HTLCs that were fulfilled since the last commitment
33+
/// are provided. A validating signer should ensure that an outbound HTLC output is removed
34+
/// only when the matching preimage is provided and after the corresponding inbound HTLC has
35+
/// been removed for forwarded payments.
3536
///
3637
/// Note that all the relevant preimages will be provided, but there may also be additional
3738
/// irrelevant or duplicate preimages.
3839
//
3940
// TODO: Document the things someone using this interface should enforce before signing.
4041
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction,
41-
preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>
42+
inbound_htlc_preimages: Vec<PaymentPreimage>,
43+
outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>,
4244
) -> Result<(Signature, Vec<Signature>), ()>;
4345
/// Creates a signature for a holder's commitment transaction.
4446
///

lightning/src/sign/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -594,14 +594,14 @@ pub trait ChannelSigner {
594594
/// Policy checks should be implemented in this function, including checking the amount
595595
/// sent to us and checking the HTLCs.
596596
///
597-
/// The preimages of outgoing HTLCs that were fulfilled since the last commitment are provided.
597+
/// The preimages of outbound HTLCs that were fulfilled since the last commitment are provided.
598598
/// A validating signer should ensure that an HTLC output is removed only when the matching
599599
/// preimage is provided, or when the value to holder is restored.
600600
///
601601
/// Note that all the relevant preimages will be provided, but there may also be additional
602602
/// irrelevant or duplicate preimages.
603603
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction,
604-
preimages: Vec<PaymentPreimage>) -> Result<(), ()>;
604+
outbound_htlc_preimages: Vec<PaymentPreimage>) -> Result<(), ()>;
605605

606606
/// Validate the counterparty's revocation.
607607
///
@@ -1086,7 +1086,7 @@ impl ChannelSigner for InMemorySigner {
10861086
chan_utils::build_commitment_secret(&self.commitment_seed, idx)
10871087
}
10881088

1089-
fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction, _preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
1089+
fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
10901090
Ok(())
10911091
}
10921092

@@ -1112,7 +1112,7 @@ impl ChannelSigner for InMemorySigner {
11121112
const MISSING_PARAMS_ERR: &'static str = "ChannelSigner::provide_channel_parameters must be called before signing operations";
11131113

11141114
impl EcdsaChannelSigner for InMemorySigner {
1115-
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
1115+
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _inbound_htlc_preimages: Vec<PaymentPreimage>, _outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
11161116
let trusted_tx = commitment_tx.trust();
11171117
let keys = trusted_tx.keys();
11181118

@@ -1260,7 +1260,7 @@ impl TaprootChannelSigner for InMemorySigner {
12601260
todo!()
12611261
}
12621262

1263-
fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<schnorr::Signature>), ()> {
1263+
fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec<PaymentPreimage>, outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<schnorr::Signature>), ()> {
12641264
todo!()
12651265
}
12661266

lightning/src/sign/taproot.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,19 @@ pub trait TaprootChannelSigner: ChannelSigner {
2727
/// Policy checks should be implemented in this function, including checking the amount
2828
/// sent to us and checking the HTLCs.
2929
///
30-
/// The preimages of outgoing HTLCs that were fulfilled since the last commitment are provided.
31-
/// A validating signer should ensure that an HTLC output is removed only when the matching
32-
/// preimage is provided, or when the value to holder is restored.
30+
/// The preimages of outbound and inbound HTLCs that were fulfilled since the last commitment
31+
/// are provided. A validating signer should ensure that an outbound HTLC output is removed
32+
/// only when the matching preimage is provided and after the corresponding inbound HTLC has
33+
/// been removed for forwarded payments.
3334
///
3435
/// Note that all the relevant preimages will be provided, but there may also be additional
3536
/// irrelevant or duplicate preimages.
3637
//
3738
// TODO: Document the things someone using this interface should enforce before signing.
3839
fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce,
39-
commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>,
40-
secp_ctx: &Secp256k1<secp256k1::All>,
40+
commitment_tx: &CommitmentTransaction,
41+
inbound_htlc_preimages: Vec<PaymentPreimage>,
42+
outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>,
4143
) -> Result<(PartialSignatureWithNonce, Vec<Signature>), ()>;
4244

4345
/// Creates a signature for a holder's commitment transaction.

lightning/src/util/test_channel_signer.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl ChannelSigner for TestChannelSigner {
138138
self.inner.release_commitment_secret(idx)
139139
}
140140

141-
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
141+
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
142142
let mut state = self.state.lock().unwrap();
143143
let idx = holder_tx.commitment_number();
144144
assert!(idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, "expecting to validate the current or next holder commitment - trying {}, current {}", idx, state.last_holder_commitment);
@@ -166,7 +166,7 @@ impl ChannelSigner for TestChannelSigner {
166166
}
167167

168168
impl EcdsaChannelSigner for TestChannelSigner {
169-
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
169+
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec<PaymentPreimage>, outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
170170
self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx);
171171

172172
{
@@ -185,7 +185,7 @@ impl EcdsaChannelSigner for TestChannelSigner {
185185
state.last_counterparty_commitment = cmp::min(last_commitment_number, actual_commitment_number)
186186
}
187187

188-
Ok(self.inner.sign_counterparty_commitment(commitment_tx, preimages, secp_ctx).unwrap())
188+
Ok(self.inner.sign_counterparty_commitment(commitment_tx, inbound_htlc_preimages, outbound_htlc_preimages, secp_ctx).unwrap())
189189
}
190190

191191
fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
@@ -288,7 +288,7 @@ impl TaprootChannelSigner for TestChannelSigner {
288288
todo!()
289289
}
290290

291-
fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<secp256k1::schnorr::Signature>), ()> {
291+
fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec<PaymentPreimage>, outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<secp256k1::schnorr::Signature>), ()> {
292292
todo!()
293293
}
294294

0 commit comments

Comments
 (0)