Skip to content

Commit 9d8efec

Browse files
committed
Use rust-bitcoin's new SigHashCache instead of SignatureHashComp's
Thew new API is a bit harder to misuse by taking a reference to the transaction to require the inputs match the input being signed.
1 parent b9707da commit 9d8efec

File tree

6 files changed

+55
-49
lines changed

6 files changed

+55
-49
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
1212
//! on-chain output which is theirs.
1313
14-
use bitcoin::blockdata::transaction::{Transaction, TxOut};
14+
use bitcoin::blockdata::transaction::{Transaction, TxOut, SigHashType};
1515
use bitcoin::blockdata::script::{Script, Builder};
1616
use bitcoin::blockdata::opcodes;
1717
use bitcoin::network::constants::Network;
@@ -477,7 +477,7 @@ impl ChannelKeys for InMemoryChannelKeys {
477477
let accepted_data = self.accepted_channel_data.as_ref().expect("must accept before signing");
478478
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &accepted_data.remote_channel_pubkeys.funding_pubkey);
479479

480-
let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
480+
let commitment_sighash = hash_to_message!(&bip143::SigHashCache::new(commitment_tx).signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
481481
let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
482482

483483
let commitment_txid = commitment_tx.txid();
@@ -487,7 +487,7 @@ impl ChannelKeys for InMemoryChannelKeys {
487487
if let Some(_) = htlc.transaction_output_index {
488488
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, accepted_data.local_to_self_delay, htlc, &keys.a_delayed_payment_key, &keys.revocation_key);
489489
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
490-
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
490+
let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]);
491491
let our_htlc_key = match chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key) {
492492
Ok(s) => s,
493493
Err(_) => return Err(()),
@@ -548,8 +548,8 @@ impl ChannelKeys for InMemoryChannelKeys {
548548
};
549549
chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.local_to_self_delay(), &remote_delayedpubkey)
550550
};
551-
let sighash_parts = bip143::SighashComponents::new(&justice_tx);
552-
let sighash = hash_to_message!(&sighash_parts.sighash_all(&justice_tx.input[input], &witness_script, amount)[..]);
551+
let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
552+
let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
553553
return Ok(secp_ctx.sign(&sighash, &revocation_key))
554554
}
555555

@@ -562,8 +562,8 @@ impl ChannelKeys for InMemoryChannelKeys {
562562
} else { return Err(()) }
563563
} else { return Err(()) }
564564
} else { return Err(()) };
565-
let sighash_parts = bip143::SighashComponents::new(&htlc_tx);
566-
let sighash = hash_to_message!(&sighash_parts.sighash_all(&htlc_tx.input[input], &witness_script, amount)[..]);
565+
let mut sighash_parts = bip143::SigHashCache::new(htlc_tx);
566+
let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
567567
return Ok(secp_ctx.sign(&sighash, &htlc_key))
568568
}
569569
Err(())
@@ -578,8 +578,8 @@ impl ChannelKeys for InMemoryChannelKeys {
578578
let remote_channel_data = self.accepted_channel_data.as_ref().expect("must accept before signing");
579579
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_data.remote_channel_pubkeys.funding_pubkey);
580580

581-
let sighash = hash_to_message!(&bip143::SighashComponents::new(closing_tx)
582-
.sighash_all(&closing_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
581+
let sighash = hash_to_message!(&bip143::SigHashCache::new(closing_tx)
582+
.signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
583583
Ok(secp_ctx.sign(&sighash, &self.funding_key))
584584
}
585585

lightning/src/ln/chan_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,8 +651,8 @@ impl LocalCommitmentTransaction {
651651
/// ChannelKeys::sign_local_commitment() calls directly.
652652
/// Channel value is amount locked in funding_outpoint.
653653
pub fn get_local_sig<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
654-
let sighash = hash_to_message!(&bip143::SighashComponents::new(&self.unsigned_tx)
655-
.sighash_all(&self.unsigned_tx.input[0], funding_redeemscript, channel_value_satoshis)[..]);
654+
let sighash = hash_to_message!(&bip143::SigHashCache::new(&self.unsigned_tx)
655+
.signature_hash(0, funding_redeemscript, channel_value_satoshis, SigHashType::All)[..]);
656656
secp_ctx.sign(&sighash, funding_key)
657657
}
658658

@@ -692,7 +692,7 @@ impl LocalCommitmentTransaction {
692692

693693
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.a_htlc_key, &self.local_keys.b_htlc_key, &self.local_keys.revocation_key);
694694

695-
let sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, this_htlc.0.amount_msat / 1000)[..]);
695+
let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.0.amount_msat / 1000, SigHashType::All)[..]);
696696
ret.push(Some(secp_ctx.sign(&sighash, &our_htlc_key)));
697697
} else {
698698
ret.push(None);

lightning/src/ln/channel.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
14761476

14771477
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
14781478
let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw, logger).0;
1479-
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
1479+
let local_sighash = hash_to_message!(&bip143::SigHashCache::new(&local_initial_commitment_tx).signature_hash(0, &funding_script, self.channel_value_satoshis, SigHashType::All)[..]);
14801480

14811481
// They sign the "local" commitment transaction...
14821482
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey().serialize()), encode::serialize_hex(&local_initial_commitment_tx), log_bytes!(local_sighash[..]), encode::serialize_hex(&funding_script));
@@ -1580,7 +1580,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
15801580

15811581
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
15821582
let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw, logger).0;
1583-
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
1583+
let local_sighash = hash_to_message!(&bip143::SigHashCache::new(&local_initial_commitment_tx).signature_hash(0, &funding_script, self.channel_value_satoshis, SigHashType::All)[..]);
15841584

15851585
let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey;
15861586

@@ -1981,7 +1981,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
19811981
(commitment_tx.0, commitment_tx.1, htlcs_cloned)
19821982
};
19831983
let local_commitment_txid = local_commitment_tx.0.txid();
1984-
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]);
1984+
let local_sighash = hash_to_message!(&bip143::SigHashCache::new(&local_commitment_tx.0).signature_hash(0, &funding_script, self.channel_value_satoshis, SigHashType::All)[..]);
19851985
log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey().serialize()), encode::serialize_hex(&local_commitment_tx.0), log_bytes!(local_sighash[..]), encode::serialize_hex(&funding_script));
19861986
if let Err(_) = self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey()) {
19871987
return Err((None, ChannelError::Close("Invalid commitment tx signature from peer".to_owned())));
@@ -2010,7 +2010,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
20102010
if let Some(_) = htlc.transaction_output_index {
20112011
let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
20122012
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
2013-
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
2013+
let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]);
20142014
log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript));
20152015
if let Err(_) = self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key) {
20162016
return Err((None, ChannelError::Close("Invalid HTLC tx signature from peer".to_owned())));
@@ -3014,7 +3014,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
30143014
if used_total_fee != msg.fee_satoshis {
30153015
return Err(ChannelError::Close(format!("Remote sent us a closing_signed with a fee greater than the value they can claim. Fee in message: {}", msg.fee_satoshis)));
30163016
}
3017-
let mut sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
3017+
let mut sighash = hash_to_message!(&bip143::SigHashCache::new(&closing_tx).signature_hash(0, &funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
30183018

30193019
let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey;
30203020

@@ -3024,7 +3024,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
30243024
// The remote end may have decided to revoke their output due to inconsistent dust
30253025
// limits, so check for that case by re-checking the signature here.
30263026
closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
3027-
sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
3027+
sighash = hash_to_message!(&bip143::SigHashCache::new(&closing_tx).signature_hash(0, &funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
30283028
secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, self.their_funding_pubkey()), "Invalid closing tx signature from peer".to_owned());
30293029
},
30303030
};
@@ -4453,7 +4453,7 @@ mod tests {
44534453
use bitcoin::util::bip143;
44544454
use bitcoin::consensus::encode::serialize;
44554455
use bitcoin::blockdata::script::{Script, Builder};
4456-
use bitcoin::blockdata::transaction::{Transaction, TxOut};
4456+
use bitcoin::blockdata::transaction::{Transaction, TxOut, SigHashType};
44574457
use bitcoin::blockdata::constants::genesis_block;
44584458
use bitcoin::blockdata::opcodes;
44594459
use bitcoin::network::constants::Network;
@@ -4691,7 +4691,7 @@ mod tests {
46914691
};
46924692
let redeemscript = chan.get_funding_redeemscript();
46934693
let their_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap();
4694-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &redeemscript, chan.channel_value_satoshis)[..]).unwrap();
4694+
let sighash = Message::from_slice(&bip143::SigHashCache::new(&unsigned_tx.0).signature_hash(0, &redeemscript, chan.channel_value_satoshis, SigHashType::All)[..]).unwrap();
46954695
secp_ctx.verify(&sighash, &their_signature, chan.their_funding_pubkey()).unwrap();
46964696

46974697
let mut per_htlc = Vec::new();
@@ -4718,7 +4718,7 @@ mod tests {
47184718
let ref htlc = unsigned_tx.1[$htlc_idx];
47194719
let htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw);
47204720
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
4721-
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
4721+
let htlc_sighash = Message::from_slice(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]).unwrap();
47224722
secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();
47234723

47244724
let mut preimage: Option<PaymentPreimage> = None;

lightning/src/ln/channelmonitor.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,33 +2705,33 @@ mod tests {
27052705
let mut sum_actual_sigs = 0;
27062706

27072707
macro_rules! sign_input {
2708-
($sighash_parts: expr, $input: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
2708+
($sighash_parts: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
27092709
let htlc = HTLCOutputInCommitment {
27102710
offered: if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::OfferedHTLC { true } else { false },
27112711
amount_msat: 0,
27122712
cltv_expiry: 2 << 16,
27132713
payment_hash: PaymentHash([1; 32]),
2714-
transaction_output_index: Some($idx),
2714+
transaction_output_index: Some($idx as u32),
27152715
};
27162716
let redeem_script = if *$input_type == InputDescriptors::RevokedOutput { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
2717-
let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeem_script, $amount)[..]);
2717+
let sighash = hash_to_message!(&$sighash_parts.signature_hash($idx, &redeem_script, $amount, SigHashType::All)[..]);
27182718
let sig = secp_ctx.sign(&sighash, &privkey);
2719-
$input.witness.push(sig.serialize_der().to_vec());
2720-
$input.witness[0].push(SigHashType::All as u8);
2721-
sum_actual_sigs += $input.witness[0].len();
2719+
$sighash_parts.access_witness($idx).push(sig.serialize_der().to_vec());
2720+
$sighash_parts.access_witness($idx)[0].push(SigHashType::All as u8);
2721+
sum_actual_sigs += $sighash_parts.access_witness($idx)[0].len();
27222722
if *$input_type == InputDescriptors::RevokedOutput {
2723-
$input.witness.push(vec!(1));
2723+
$sighash_parts.access_witness($idx).push(vec!(1));
27242724
} else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
2725-
$input.witness.push(pubkey.clone().serialize().to_vec());
2725+
$sighash_parts.access_witness($idx).push(pubkey.clone().serialize().to_vec());
27262726
} else if *$input_type == InputDescriptors::ReceivedHTLC {
2727-
$input.witness.push(vec![0]);
2727+
$sighash_parts.access_witness($idx).push(vec![0]);
27282728
} else {
2729-
$input.witness.push(PaymentPreimage([1; 32]).0.to_vec());
2729+
$sighash_parts.access_witness($idx).push(PaymentPreimage([1; 32]).0.to_vec());
27302730
}
2731-
$input.witness.push(redeem_script.into_bytes());
2732-
println!("witness[0] {}", $input.witness[0].len());
2733-
println!("witness[1] {}", $input.witness[1].len());
2734-
println!("witness[2] {}", $input.witness[2].len());
2731+
$sighash_parts.access_witness($idx).push(redeem_script.into_bytes());
2732+
println!("witness[0] {}", $sighash_parts.access_witness($idx)[0].len());
2733+
println!("witness[1] {}", $sighash_parts.access_witness($idx)[1].len());
2734+
println!("witness[2] {}", $sighash_parts.access_witness($idx)[2].len());
27352735
}
27362736
}
27372737

@@ -2756,10 +2756,12 @@ mod tests {
27562756
value: 0,
27572757
});
27582758
let base_weight = claim_tx.get_weight();
2759-
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
27602759
let inputs_des = vec![InputDescriptors::RevokedOutput, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedReceivedHTLC];
2761-
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2762-
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2760+
{
2761+
let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
2762+
for (idx, inp) in inputs_des.iter().enumerate() {
2763+
sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
2764+
}
27632765
}
27642766
assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
27652767

@@ -2778,10 +2780,12 @@ mod tests {
27782780
});
27792781
}
27802782
let base_weight = claim_tx.get_weight();
2781-
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
27822783
let inputs_des = vec![InputDescriptors::OfferedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC];
2783-
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2784-
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2784+
{
2785+
let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
2786+
for (idx, inp) in inputs_des.iter().enumerate() {
2787+
sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
2788+
}
27852789
}
27862790
assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
27872791

@@ -2798,10 +2802,12 @@ mod tests {
27982802
witness: Vec::new(),
27992803
});
28002804
let base_weight = claim_tx.get_weight();
2801-
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
28022805
let inputs_des = vec![InputDescriptors::RevokedOutput];
2803-
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2804-
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2806+
{
2807+
let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
2808+
for (idx, inp) in inputs_des.iter().enumerate() {
2809+
sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
2810+
}
28052811
}
28062812
assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() - sum_actual_sigs));
28072813
}

0 commit comments

Comments
 (0)