Skip to content

Commit 6ea5589

Browse files
committed
Move commitment tx sig validation from FundedChannel to ChannelSigner
1 parent fd1a47a commit 6ea5589

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

lightning/src/ln/channel.rs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
18301830
context.counterparty_funding_pubkey()
18311831
);
18321832

1833-
if context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()).is_err() {
1833+
if context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new(), &context.secp_ctx).is_err() {
18341834
return Err(ChannelError::close("Failed to validate our commitment".to_owned()));
18351835
}
18361836

@@ -5245,23 +5245,28 @@ impl<SP: Deref> FundedChannel<SP> where
52455245
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
52465246
}
52475247

5248-
let funding_script = self.context.get_funding_redeemscript();
5249-
52505248
let keys = self.context.build_holder_transaction_keys(self.holder_commitment_point.current_point());
52515249

52525250
let commitment_stats = self.context.build_commitment_transaction(self.holder_commitment_point.transaction_number(), &keys, true, false, logger);
5251+
5252+
if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs {
5253+
return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
5254+
}
5255+
5256+
let holder_commitment_tx = HolderCommitmentTransaction::new(
5257+
commitment_stats.tx.clone(),
5258+
msg.signature,
5259+
msg.htlc_signatures.clone(),
5260+
&self.context.get_holder_pubkeys().funding_pubkey,
5261+
self.context.counterparty_funding_pubkey()
5262+
);
5263+
5264+
self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages, &self.context.secp_ctx)
5265+
.map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
5266+
52535267
let commitment_txid = {
52545268
let trusted_tx = commitment_stats.tx.trust();
52555269
let bitcoin_tx = trusted_tx.built_transaction();
5256-
let sighash = bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis);
5257-
5258-
log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}",
5259-
log_bytes!(msg.signature.serialize_compact()[..]),
5260-
log_bytes!(self.context.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction),
5261-
log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.context.channel_id());
5262-
if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.counterparty_funding_pubkey()) {
5263-
return Err(ChannelError::close("Invalid commitment tx signature from peer".to_owned()));
5264-
}
52655270
bitcoin_tx.txid
52665271
};
52675272
let mut htlcs_cloned: Vec<_> = commitment_stats.htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
@@ -5296,10 +5301,6 @@ impl<SP: Deref> FundedChannel<SP> where
52965301
}
52975302
}
52985303

5299-
if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs {
5300-
return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
5301-
}
5302-
53035304
// Up to LDK 0.0.115, HTLC information was required to be duplicated in the
53045305
// `htlcs_and_sigs` vec and in the `holder_commitment_tx` itself, both of which were passed
53055306
// in the `ChannelMonitorUpdate`. In 0.0.115, support for having a separate set of
@@ -5346,17 +5347,6 @@ impl<SP: Deref> FundedChannel<SP> where
53465347
debug_assert!(source_opt.is_none(), "HTLCSource should have been put somewhere");
53475348
}
53485349

5349-
let holder_commitment_tx = HolderCommitmentTransaction::new(
5350-
commitment_stats.tx,
5351-
msg.signature,
5352-
msg.htlc_signatures.clone(),
5353-
&self.context.get_holder_pubkeys().funding_pubkey,
5354-
self.context.counterparty_funding_pubkey()
5355-
);
5356-
5357-
self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages)
5358-
.map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
5359-
53605350
// Update state now that we've passed all the can-fail calls...
53615351
let mut need_commitment = false;
53625352
if let &mut Some((_, ref mut update_state)) = &mut self.context.pending_update_fee {

lightning/src/sign/mod.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,24 @@ pub trait ChannelSigner {
697697
/// and pause future signing operations until this validation completes.
698698
fn validate_holder_commitment(
699699
&self, holder_tx: &HolderCommitmentTransaction,
700-
outbound_htlc_preimages: Vec<PaymentPreimage>,
701-
) -> Result<(), ()>;
700+
_outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>,
701+
) -> Result<(), ()> {
702+
let channel_value_satoshis = self.get_channel_value_satoshis();
703+
let params = self.get_channel_parameters().unwrap();
704+
let holder_pubkey = params.holder_pubkeys.funding_pubkey;
705+
let counterparty_pubkey =
706+
params.counterparty_parameters.as_ref().unwrap().pubkeys.funding_pubkey;
707+
let funding_redeemscript = make_funding_redeemscript(&holder_pubkey, &counterparty_pubkey);
708+
let trusted_tx = holder_tx.trust();
709+
let bitcoin_tx = trusted_tx.built_transaction();
710+
let sighash = bitcoin_tx.get_sighash_all(&funding_redeemscript, channel_value_satoshis);
711+
if let Err(_) =
712+
secp_ctx.verify_ecdsa(&sighash, &holder_tx.counterparty_sig, &counterparty_pubkey)
713+
{
714+
return Err(());
715+
}
716+
Ok(())
717+
}
702718

703719
/// Validate the counterparty's revocation.
704720
///
@@ -736,6 +752,9 @@ pub trait ChannelSigner {
736752
/// Returns the parameters of this signer
737753
fn get_channel_parameters(&self) -> Option<&ChannelTransactionParameters>;
738754

755+
/// Return the channel value
756+
fn get_channel_value_satoshis(&self) -> u64;
757+
739758
/// Returns the script pubkey that should be placed in the `to_remote` output of commitment
740759
/// transactions.
741760
///
@@ -1602,13 +1621,6 @@ impl ChannelSigner for InMemorySigner {
16021621
Ok(chan_utils::build_commitment_secret(&self.commitment_seed, idx))
16031622
}
16041623

1605-
fn validate_holder_commitment(
1606-
&self, _holder_tx: &HolderCommitmentTransaction,
1607-
_outbound_htlc_preimages: Vec<PaymentPreimage>,
1608-
) -> Result<(), ()> {
1609-
Ok(())
1610-
}
1611-
16121624
fn validate_counterparty_revocation(&self, _idx: u64, _secret: &SecretKey) -> Result<(), ()> {
16131625
Ok(())
16141626
}
@@ -1851,6 +1863,10 @@ impl ChannelSigner for InMemorySigner {
18511863
sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key, &self);
18521864
Ok(chan_utils::build_anchor_input_witness(funding_pubkey, &sig))
18531865
}
1866+
1867+
fn get_channel_value_satoshis(&self) -> u64 {
1868+
self.channel_value_satoshis
1869+
}
18541870
}
18551871

18561872
const MISSING_PARAMS_ERR: &'static str =

lightning/src/util/test_channel_signer.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,12 @@ impl ChannelSigner for TestChannelSigner {
191191
self.inner.release_commitment_secret(idx)
192192
}
193193

194-
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
194+
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(), ()> {
195195
let mut state = self.state.lock().unwrap();
196196
let idx = holder_tx.commitment_number();
197197
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);
198198
state.last_holder_commitment = idx;
199-
Ok(())
199+
self.inner.validate_holder_commitment(holder_tx, outbound_htlc_preimages, secp_ctx)
200200
}
201201

202202
fn validate_counterparty_revocation(&self, idx: u64, _secret: &SecretKey) -> Result<(), ()> {
@@ -331,6 +331,10 @@ impl ChannelSigner for TestChannelSigner {
331331
) -> Result<Witness, ()> {
332332
self.inner.spend_holder_anchor_output(anchor_tx, input_idx, secp_ctx)
333333
}
334+
335+
fn get_channel_value_satoshis(&self) -> u64 {
336+
self.inner.get_channel_value_satoshis()
337+
}
334338
}
335339

336340
impl EcdsaChannelSigner for TestChannelSigner {

0 commit comments

Comments
 (0)