diff --git a/ci/ci-tests.sh b/ci/ci-tests.sh index 7dad1436e98..e0e66861fa9 100755 --- a/ci/ci-tests.sh +++ b/ci/ci-tests.sh @@ -35,13 +35,14 @@ for DIR in lightning lightning-invoice lightning-rapid-gossip-sync; do cargo test --verbose --color always --no-default-features --features no-std # check if there is a conflict between no-std and the default std feature cargo test --verbose --color always --features no-std - # check that things still pass without grind_signatures - # note that outbound_commitment_test only runs in this mode, because of hardcoded signature values - cargo test --verbose --color always --no-default-features --features std # check if there is a conflict between no-std and the c_bindings cfg RUSTFLAGS="--cfg=c_bindings" cargo test --verbose --color always --no-default-features --features=no-std popd done +# Note that outbound_commitment_test only runs in this mode because of hardcoded signature values +pushd lightning +cargo test --verbose --color always --no-default-features --features=std,_test_vectors +popd # This one only works for lightning-invoice pushd lightning-invoice # check that compile with no-std and serde works in lightning-invoice diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index c10b5c0e364..a00404497fa 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -240,6 +240,7 @@ impl SignerProvider for KeyProvider { [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_secret[31]], channel_value_satoshis, channel_keys_id, + channel_keys_id, ); let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed); EnforcingSigner::new_with_revoked(keys, revoked_commitment, false) @@ -248,7 +249,7 @@ impl SignerProvider for KeyProvider { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = std::io::Cursor::new(buffer); - let inner: InMemorySigner = Readable::read(&mut reader)?; + let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner { diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 59cb41dbb45..876a412da5f 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -48,7 +48,7 @@ use lightning::util::config::UserConfig; use lightning::util::errors::APIError; use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; use lightning::util::logger::Logger; -use lightning::util::ser::{Readable, Writeable}; +use lightning::util::ser::{Readable, ReadableArgs, Writeable}; use crate::utils::test_logger; use crate::utils::test_persister::TestPersister; @@ -347,6 +347,7 @@ impl SignerProvider for KeyProvider { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr], channel_value_satoshis, channel_keys_id, + channel_keys_id, ) } else { InMemorySigner::new( @@ -359,12 +360,13 @@ impl SignerProvider for KeyProvider { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr], channel_value_satoshis, channel_keys_id, + channel_keys_id, ) }, state, false) } fn read_chan_signer(&self, mut data: &[u8]) -> Result { - let inner: InMemorySigner = Readable::read(&mut data)?; + let inner: InMemorySigner = ReadableArgs::read(&mut data, self)?; let state = Arc::new(Mutex::new(EnforcementState::new())); Ok(EnforcingSigner::new_with_revoked( diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index 17896ecb387..32755a7e43f 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -29,6 +29,8 @@ max_level_trace = [] # This is unsafe to use in production because it may result in the counterparty publishing taking our funds. unsafe_revoked_tx_signing = [] _bench_unstable = [] +# Override signing to not include randomness when generating signatures for test vectors. +_test_vectors = [] no-std = ["hashbrown", "bitcoin/no-std", "core2/alloc"] std = ["bitcoin/std"] diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 82fae49f7ce..5ff297b1af7 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -4235,6 +4235,7 @@ mod tests { [41; 32], 0, [0; 32], + [0; 32], ); let counterparty_pubkeys = ChannelPublicKeys { diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 4ad15db876b..b1290708b95 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -32,8 +32,8 @@ use bitcoin::secp256k1::ecdsa::RecoverableSignature; use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; use crate::util::transaction_utils; -use crate::util::crypto::{hkdf_extract_expand_twice, sign}; -use crate::util::ser::{Writeable, Writer, Readable}; +use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; +use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; use crate::chain::transaction::OutPoint; #[cfg(anchors)] use crate::events::bump_transaction::HTLCDescriptor; @@ -45,6 +45,7 @@ use crate::ln::script::ShutdownScript; use crate::prelude::*; use core::convert::TryInto; +use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; use crate::io::{self, Error}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; @@ -553,7 +554,6 @@ pub trait SignerProvider { fn get_shutdown_scriptpubkey(&self) -> ShutdownScript; } -#[derive(Clone)] /// A simple implementation of [`WriteableEcdsaChannelSigner`] that just keeps the private keys in memory. /// /// This implementation performs no policy checks and is insufficient by itself as @@ -580,6 +580,30 @@ pub struct InMemorySigner { channel_value_satoshis: u64, /// Key derivation parameters. channel_keys_id: [u8; 32], + /// Seed from which all randomness produced is derived from. + rand_bytes_unique_start: [u8; 32], + /// Tracks the number of times we've produced randomness to ensure we don't return the same + /// bytes twice. + rand_bytes_index: AtomicCounter, +} + +impl Clone for InMemorySigner { + fn clone(&self) -> Self { + Self { + funding_key: self.funding_key.clone(), + revocation_base_key: self.revocation_base_key.clone(), + payment_key: self.payment_key.clone(), + delayed_payment_base_key: self.delayed_payment_base_key.clone(), + htlc_base_key: self.htlc_base_key.clone(), + commitment_seed: self.commitment_seed.clone(), + holder_channel_pubkeys: self.holder_channel_pubkeys.clone(), + channel_parameters: self.channel_parameters.clone(), + channel_value_satoshis: self.channel_value_satoshis, + channel_keys_id: self.channel_keys_id, + rand_bytes_unique_start: self.get_secure_random_bytes(), + rand_bytes_index: AtomicCounter::new(), + } + } } impl InMemorySigner { @@ -594,6 +618,7 @@ impl InMemorySigner { commitment_seed: [u8; 32], channel_value_satoshis: u64, channel_keys_id: [u8; 32], + rand_bytes_unique_start: [u8; 32], ) -> InMemorySigner { let holder_channel_pubkeys = InMemorySigner::make_holder_keys(secp_ctx, &funding_key, &revocation_base_key, @@ -610,6 +635,8 @@ impl InMemorySigner { holder_channel_pubkeys, channel_parameters: None, channel_keys_id, + rand_bytes_unique_start, + rand_bytes_index: AtomicCounter::new(), } } @@ -686,7 +713,7 @@ impl InMemorySigner { let remotepubkey = self.pubkeys().payment_point; let witness_script = bitcoin::Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: remotepubkey}, Network::Testnet).script_pubkey(); let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); - let remotesig = sign(secp_ctx, &sighash, &self.payment_key); + let remotesig = sign_with_aux_rand(secp_ctx, &sighash, &self.payment_key, &self); let payment_script = bitcoin::Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, inner: remotepubkey}, Network::Bitcoin).unwrap().script_pubkey(); if payment_script != descriptor.output.script_pubkey { return Err(()); } @@ -722,7 +749,7 @@ impl InMemorySigner { let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx, &delayed_payment_key); let witness_script = chan_utils::get_revokeable_redeemscript(&descriptor.revocation_pubkey, descriptor.to_self_delay, &delayed_payment_pubkey); let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); - let local_delayedsig = sign(secp_ctx, &sighash, &delayed_payment_key); + let local_delayedsig = sign_with_aux_rand(secp_ctx, &sighash, &delayed_payment_key, &self); let payment_script = bitcoin::Address::p2wsh(&witness_script, Network::Bitcoin).script_pubkey(); if descriptor.output.script_pubkey != payment_script { return Err(()); } @@ -736,6 +763,15 @@ impl InMemorySigner { } } +impl EntropySource for InMemorySigner { + fn get_secure_random_bytes(&self) -> [u8; 32] { + let index = self.rand_bytes_index.get_increment(); + let mut nonce = [0u8; 16]; + nonce[..8].copy_from_slice(&index.to_be_bytes()); + ChaCha20::get_single_block(&self.rand_bytes_unique_start, &nonce) + } +} + impl ChannelSigner for InMemorySigner { fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap(); @@ -774,7 +810,7 @@ impl EcdsaChannelSigner for InMemorySigner { let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let built_tx = trusted_tx.built_transaction(); - let commitment_sig = built_tx.sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let commitment_sig = built_tx.sign_counterparty_commitment(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); let commitment_txid = built_tx.txid; let mut htlc_sigs = Vec::with_capacity(commitment_tx.htlcs().len()); @@ -799,9 +835,9 @@ impl EcdsaChannelSigner for InMemorySigner { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let trusted_tx = commitment_tx.trust(); - let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let sig = trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx); let channel_parameters = self.get_channel_parameters(); - let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?; + let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), &self, secp_ctx)?; Ok((sig, htlc_sigs)) } @@ -810,9 +846,9 @@ impl EcdsaChannelSigner for InMemorySigner { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let trusted_tx = commitment_tx.trust(); - let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let sig = trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx); let channel_parameters = self.get_channel_parameters(); - let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?; + let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), &self, secp_ctx)?; Ok((sig, htlc_sigs)) } @@ -826,7 +862,7 @@ impl EcdsaChannelSigner for InMemorySigner { }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign(secp_ctx, &sighash, &revocation_key)) + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) } fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { @@ -840,7 +876,7 @@ impl EcdsaChannelSigner for InMemorySigner { }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign(secp_ctx, &sighash, &revocation_key)) + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) } #[cfg(anchors)] @@ -858,7 +894,7 @@ impl EcdsaChannelSigner for InMemorySigner { let our_htlc_private_key = chan_utils::derive_private_key( &secp_ctx, &per_commitment_point, &self.htlc_base_key ); - Ok(sign(&secp_ctx, &hash_to_message!(sighash), &our_htlc_private_key)) + Ok(sign_with_aux_rand(&secp_ctx, &hash_to_message!(sighash), &our_htlc_private_key, &self)) } fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { @@ -869,7 +905,7 @@ impl EcdsaChannelSigner for InMemorySigner { let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, self.opt_anchors(), &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey); let mut sighash_parts = sighash::SighashCache::new(htlc_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - Ok(sign(secp_ctx, &sighash, &htlc_key)) + Ok(sign_with_aux_rand(secp_ctx, &sighash, &htlc_key, &self)) } fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { @@ -885,14 +921,14 @@ impl EcdsaChannelSigner for InMemorySigner { let sighash = sighash::SighashCache::new(&*anchor_tx).segwit_signature_hash( input, &witness_script, ANCHOR_OUTPUT_VALUE_SATOSHI, EcdsaSighashType::All, ).unwrap(); - Ok(sign(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key)) + Ok(sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key, &self)) } fn sign_channel_announcement_with_funding_key( &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 ) -> Result { let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - Ok(sign(secp_ctx, &msghash, &self.funding_key)) + Ok(secp_ctx.sign_ecdsa(&msghash, &self.funding_key)) } } @@ -922,8 +958,8 @@ impl Writeable for InMemorySigner { } } -impl Readable for InMemorySigner { - fn read(reader: &mut R) -> Result { +impl ReadableArgs for InMemorySigner where ES::Target: EntropySource { + fn read(reader: &mut R, entropy_source: ES) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let funding_key = Readable::read(reader)?; @@ -953,6 +989,8 @@ impl Readable for InMemorySigner { holder_channel_pubkeys, channel_parameters: counterparty_channel_data, channel_keys_id: keys_id, + rand_bytes_unique_start: entropy_source.get_secure_random_bytes(), + rand_bytes_index: AtomicCounter::new(), }) } } @@ -1107,6 +1145,7 @@ impl KeysManager { let payment_key = key_step!(b"payment key", revocation_base_key); let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_key); let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key); + let prng_seed = self.get_secure_random_bytes(); InMemorySigner::new( &self.secp_ctx, @@ -1118,6 +1157,7 @@ impl KeysManager { commitment_seed, channel_value_satoshis, params.clone(), + prng_seed, ) } @@ -1233,7 +1273,7 @@ impl KeysManager { if payment_script != output.script_pubkey { return Err(()); }; let sighash = hash_to_message!(&sighash::SighashCache::new(&spend_tx).segwit_signature_hash(input_idx, &witness_script, output.value, EcdsaSighashType::All).unwrap()[..]); - let sig = sign(secp_ctx, &sighash, &secret.private_key); + let sig = sign_with_aux_rand(secp_ctx, &sighash, &secret.private_key, &self); let mut sig_ser = sig.serialize_der().to_vec(); sig_ser.push(EcdsaSighashType::All as u8); spend_tx.input[input_idx].witness.push(sig_ser); @@ -1295,7 +1335,7 @@ impl NodeSigner for KeysManager { fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result { let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - Ok(sign(&self.secp_ctx, &msg_hash, &self.node_secret)) + Ok(self.secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) } } @@ -1323,7 +1363,7 @@ impl SignerProvider for KeysManager { } fn read_chan_signer(&self, reader: &[u8]) -> Result { - InMemorySigner::read(&mut io::Cursor::new(reader)) + InMemorySigner::read(&mut io::Cursor::new(reader), self) } fn get_destination_script(&self) -> Script { diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 533da9772a2..9699cc78a1a 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -21,6 +21,7 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::ripemd160::Hash as Ripemd160; use bitcoin::hash_types::{Txid, PubkeyHash}; +use crate::chain::keysinterface::EntropySource; use crate::ln::{PaymentHash, PaymentPreimage}; use crate::ln::msgs::DecodeError; use crate::util::ser::{Readable, Writeable, Writer}; @@ -39,7 +40,7 @@ use crate::util::transaction_utils::sort_outputs; use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}; use core::ops::Deref; use crate::chain; -use crate::util::crypto::sign; +use crate::util::crypto::{sign, sign_with_aux_rand}; /// Maximum number of one-way in-flight HTLC (protocol-level value). pub const MAX_HTLCS: u16 = 483; @@ -1081,12 +1082,20 @@ impl BuiltCommitmentTransaction { hash_to_message!(sighash) } - /// Sign a transaction, either because we are counter-signing the counterparty's transaction or - /// because we are about to broadcast a holder transaction. - pub fn sign(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { + /// Signs the counterparty's commitment transaction. + pub fn sign_counterparty_commitment(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); sign(secp_ctx, &sighash, funding_key) } + + /// Signs the holder commitment transaction because we are about to broadcast it. + pub fn sign_holder_commitment( + &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, + entropy_source: &ES, secp_ctx: &Secp256k1 + ) -> Signature where ES::Target: EntropySource { + let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); + sign_with_aux_rand(secp_ctx, &sighash, funding_key, entropy_source) + } } /// This class tracks the per-transaction information needed to build a closing transaction and will @@ -1563,7 +1572,10 @@ impl<'a> TrustedCommitmentTransaction<'a> { /// The returned Vec has one entry for each HTLC, and in the same order. /// /// This function is only valid in the holder commitment context, it always uses EcdsaSighashType::All. - pub fn get_htlc_sigs(&self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1) -> Result, ()> { + pub fn get_htlc_sigs( + &self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, + entropy_source: &ES, secp_ctx: &Secp256k1, + ) -> Result, ()> where ES::Target: EntropySource { let inner = self.inner; let keys = &inner.keys; let txid = inner.built.txid; @@ -1577,7 +1589,7 @@ impl<'a> TrustedCommitmentTransaction<'a> { let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]); - ret.push(sign(secp_ctx, &sighash, &holder_htlc_key)); + ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source)); } Ok(ret) } diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index c67b7f695a5..dd553c1ff86 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -7516,7 +7516,7 @@ mod tests { } } - #[cfg(not(feature = "grind_signatures"))] + #[cfg(feature = "_test_vectors")] #[test] fn outbound_commitment_test() { use bitcoin::util::sighash; @@ -7549,6 +7549,7 @@ mod tests { [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], 10_000_000, [0; 32], + [0; 32], ); assert_eq!(signer.pubkeys().funding_pubkey.serialize()[..], diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index f2b05b6e1ed..401667f31f6 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -3461,7 +3461,7 @@ fn test_htlc_ignore_latest_remote_commitment() { let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn[0], node_txn[1]); + assert_eq!(node_txn[0].txid(), node_txn[1].txid()); let mut header = BlockHeader { version: 0x20000000, prev_blockhash: nodes[1].best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: 42, bits: 42, nonce: 42 }; connect_block(&nodes[1], &Block { header, txdata: vec![node_txn[0].clone(), node_txn[1].clone()]}); @@ -9248,7 +9248,7 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t // We should broadcast an HTLC transaction spending our funding transaction first let spending_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(spending_txn.len(), 2); - assert_eq!(spending_txn[0], node_txn[0]); + assert_eq!(spending_txn[0].txid(), node_txn[0].txid()); check_spends!(spending_txn[1], node_txn[0]); // We should also generate a SpendableOutputs event with the to_self output (as its // timelock is up). diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index 65b0fc00628..51811ec6329 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -343,7 +343,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { if !confirm_before_reload { let as_broadcasted_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(as_broadcasted_txn.len(), 1); - assert_eq!(as_broadcasted_txn[0], as_commitment_tx); + assert_eq!(as_broadcasted_txn[0].txid(), as_commitment_tx.txid()); } else { assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty()); } @@ -684,7 +684,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn[0], node_txn[1]); + assert_eq!(node_txn[0].txid(), node_txn[1].txid()); check_spends!(node_txn[1], funding_tx); check_spends!(node_txn[2], node_txn[1]); let timeout_txn = vec![node_txn[2].clone()]; diff --git a/lightning/src/util/crypto.rs b/lightning/src/util/crypto.rs index 2f2d33b29f7..ac159519c59 100644 --- a/lightning/src/util/crypto.rs +++ b/lightning/src/util/crypto.rs @@ -3,6 +3,10 @@ use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing}; +use crate::chain::keysinterface::EntropySource; + +use core::ops::Deref; + macro_rules! hkdf_extract_expand { ($salt: expr, $ikm: expr) => {{ let mut hmac = HmacEngine::::new($salt); @@ -46,3 +50,21 @@ pub fn sign(ctx: &Secp256k1, msg: &Message, sk: &SecretKey) -> Si let sig = ctx.sign_ecdsa(msg, sk); sig } + +#[inline] +pub fn sign_with_aux_rand( + ctx: &Secp256k1, msg: &Message, sk: &SecretKey, entropy_source: &ES +) -> Signature where ES::Target: EntropySource { + #[cfg(feature = "grind_signatures")] + let sig = loop { + let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes()); + if sig.serialize_compact()[0] < 0x80 { + break sig; + } + }; + #[cfg(all(not(feature = "grind_signatures"), not(feature = "_test_vectors")))] + let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes()); + #[cfg(all(not(feature = "grind_signatures"), feature = "_test_vectors"))] + let sig = sign(ctx, msg, sk); + sig +} diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 46a7bb34007..679652b2da4 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -161,7 +161,7 @@ impl SignerProvider for OnlyReadsKeysInterface { fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { unreachable!(); } fn read_chan_signer(&self, mut reader: &[u8]) -> Result { - let inner: InMemorySigner = Readable::read(&mut reader)?; + let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = Arc::new(Mutex::new(EnforcementState::new())); Ok(EnforcingSigner::new_with_revoked( @@ -783,7 +783,7 @@ impl SignerProvider for TestKeysInterface { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = io::Cursor::new(buffer); - let inner: InMemorySigner = Readable::read(&mut reader)?; + let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner::new_with_revoked(