Skip to content

Commit e2f73a5

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

File tree

2 files changed

+57
-20
lines changed

2 files changed

+57
-20
lines changed

lightning/src/ln/channel.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use bitcoin::amount::Amount;
1111
use bitcoin::constants::ChainHash;
1212
use bitcoin::script::{Script, ScriptBuf, Builder, WScriptHash};
1313
use bitcoin::transaction::{Transaction, TxIn};
14-
use bitcoin::sighash;
1514
use bitcoin::sighash::EcdsaSighashType;
1615
use bitcoin::consensus::encode;
1716
use bitcoin::absolute::LockTime;
@@ -5254,7 +5253,7 @@ impl<SP: Deref> FundedChannel<SP> where
52545253
}
52555254

52565255
let holder_commitment_tx = HolderCommitmentTransaction::new(
5257-
commitment_stats.tx.clone(),
5256+
commitment_stats.tx,
52585257
msg.signature,
52595258
msg.htlc_signatures.clone(),
52605259
&self.context.get_holder_pubkeys().funding_pubkey,
@@ -5264,11 +5263,6 @@ impl<SP: Deref> FundedChannel<SP> where
52645263
self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages, &self.context.secp_ctx)
52655264
.map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
52665265

5267-
let commitment_txid = {
5268-
let trusted_tx = commitment_stats.tx.trust();
5269-
let bitcoin_tx = trusted_tx.built_transaction();
5270-
bitcoin_tx.txid
5271-
};
52725266
let mut htlcs_cloned: Vec<_> = commitment_stats.htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
52735267

52745268
// If our counterparty updated the channel fee in this commitment transaction, check that
@@ -5318,21 +5312,8 @@ impl<SP: Deref> FundedChannel<SP> where
53185312

53195313
let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
53205314
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
5321-
let revokeable_spk = self.context.holder_signer.as_ref().get_revokeable_spk(true, commitment_stats.tx.commitment_number(), &commitment_stats.tx.per_commitment_point(), &self.context.secp_ctx);
53225315
for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
53235316
if let Some(_) = htlc.transaction_output_index {
5324-
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
5325-
&htlc, &self.context.channel_type, revokeable_spk.clone());
5326-
5327-
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys);
5328-
let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
5329-
let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
5330-
log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
5331-
log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
5332-
encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
5333-
if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
5334-
return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned()));
5335-
}
53365317
if !separate_nondust_htlc_sources {
53375318
htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source_opt.take()));
53385319
}

lightning/src/sign/mod.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,62 @@ pub trait ChannelSigner {
713713
{
714714
return Err(());
715715
}
716+
717+
if holder_tx.htlcs().len() != holder_tx.counterparty_htlc_sigs.len() {
718+
return Err(());
719+
}
720+
721+
let commitment_txid = bitcoin_tx.txid;
722+
let revokeable_spk = self.get_revokeable_spk(
723+
true,
724+
holder_tx.commitment_number(),
725+
&holder_tx.per_commitment_point(),
726+
secp_ctx,
727+
);
728+
let params = self.get_channel_parameters().unwrap().as_holder_broadcastable();
729+
let keys = TxCreationKeys::from_channel_static_keys(
730+
&holder_tx.per_commitment_point(),
731+
params.broadcaster_pubkeys(),
732+
params.countersignatory_pubkeys(),
733+
secp_ctx,
734+
);
735+
for (idx, htlc) in holder_tx.htlcs().iter().enumerate() {
736+
if let Some(_) = htlc.transaction_output_index {
737+
let htlc_tx = chan_utils::build_htlc_transaction(
738+
&commitment_txid,
739+
holder_tx.feerate_per_kw(),
740+
&htlc,
741+
params.channel_type_features(),
742+
revokeable_spk.clone(),
743+
);
744+
let htlc_redeemscript =
745+
chan_utils::get_htlc_redeemscript(&htlc, params.channel_type_features(), &keys);
746+
let htlc_sighashtype =
747+
if params.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
748+
EcdsaSighashType::SinglePlusAnyoneCanPay
749+
} else {
750+
EcdsaSighashType::All
751+
};
752+
let htlc_sighash = hash_to_message!(
753+
&sighash::SighashCache::new(&htlc_tx)
754+
.p2wsh_signature_hash(
755+
0,
756+
&htlc_redeemscript,
757+
htlc.to_bitcoin_amount(),
758+
htlc_sighashtype
759+
)
760+
.unwrap()[..]
761+
);
762+
secp_ctx
763+
.verify_ecdsa(
764+
&htlc_sighash,
765+
&holder_tx.counterparty_htlc_sigs[idx],
766+
&keys.countersignatory_htlc_key.to_public_key(),
767+
)
768+
.map_err(|_| ())?;
769+
}
770+
}
771+
716772
Ok(())
717773
}
718774

0 commit comments

Comments
 (0)