X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fsign%2Fmod.rs;h=2a5d19efd1c59f119fc1554cc60190c5cd239060;hb=9f1ffab24c4870d0f9846d75a693f2a784648a60;hp=d8f71f590534555988d5f06d4a9757b70baa4f8c;hpb=2659a2375eb819fe050f057b068c3e27f98a30f7;p=rust-lightning diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index d8f71f59..2a5d19ef 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -38,7 +38,7 @@ use bitcoin::secp256k1::schnorr; use bitcoin::{secp256k1, Sequence, Witness, Txid}; use crate::util::transaction_utils; -use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; +use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; use crate::chain::transaction::OutPoint; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; @@ -53,11 +53,10 @@ use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::invoice_request::UnsignedInvoiceRequest; use crate::prelude::*; -use core::convert::TryInto; use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; #[cfg(taproot)] -use musig2::types::{PartialSignature, PublicNonce, SecretNonce}; +use musig2::types::{PartialSignature, PublicNonce}; use crate::io::{self, Error}; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; @@ -65,7 +64,7 @@ use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; #[cfg(taproot)] use crate::sign::taproot::TaprootChannelSigner; use crate::util::atomic_counter::AtomicCounter; -use crate::util::chacha20::ChaCha20; +use crate::crypto::chacha20::ChaCha20; use crate::util::invoice::construct_invoice_preimage; pub(crate) mod type_resolver; @@ -350,7 +349,7 @@ impl SpendableOutputDescriptor { let mut input = Vec::with_capacity(descriptors.len()); let mut input_value = 0; let mut witness_weight = 0; - let mut output_set = HashSet::with_capacity(descriptors.len()); + let mut output_set = hash_set_with_capacity(descriptors.len()); for outp in descriptors { match outp { SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => { @@ -594,14 +593,20 @@ pub trait ChannelSigner { /// Policy checks should be implemented in this function, including checking the amount /// sent to us and checking the HTLCs. /// - /// The preimages of outgoing HTLCs that were fulfilled since the last commitment are provided. + /// The preimages of outbound HTLCs that were fulfilled since the last commitment are provided. /// A validating signer should ensure that an HTLC output is removed only when the matching /// preimage is provided, or when the value to holder is restored. /// /// Note that all the relevant preimages will be provided, but there may also be additional /// irrelevant or duplicate preimages. fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, - preimages: Vec) -> Result<(), ()>; + outbound_htlc_preimages: Vec) -> Result<(), ()>; + + /// Validate the counterparty's revocation. + /// + /// This is required in order for the signer to make sure that the state has moved + /// forward and it is safe to sign the next counterparty commitment. + fn validate_counterparty_revocation(&self, idx: u64, secret: &SecretKey) -> Result<(), ()>; /// Returns the holder's channel public keys and basepoints. fn pubkeys(&self) -> &ChannelPublicKeys; @@ -730,6 +735,19 @@ pub trait NodeSigner { fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result; } +// Primarily needed in doctests because of https://github.com/rust-lang/rust/issues/67295 +/// A dynamic [`SignerProvider`] temporarily needed for doc tests. +#[cfg(taproot)] +#[doc(hidden)] +#[deprecated(note = "Remove once taproot cfg is removed")] +pub type DynSignerProvider = dyn SignerProvider; + +/// A dynamic [`SignerProvider`] temporarily needed for doc tests. +#[cfg(not(taproot))] +#[doc(hidden)] +#[deprecated(note = "Remove once taproot cfg is removed")] +pub type DynSignerProvider = dyn SignerProvider; + /// A trait that can return signer instances for individual channels. pub trait SignerProvider { /// A type which implements [`WriteableEcdsaChannelSigner`] which will be returned by [`Self::derive_channel_signer`]. @@ -816,11 +834,8 @@ 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, + /// A source of random bytes. + entropy_source: RandomBytes, } impl PartialEq for InMemorySigner { @@ -851,8 +866,7 @@ impl Clone for InMemorySigner { 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(), + entropy_source: RandomBytes::new(self.get_secure_random_bytes()), } } } @@ -886,8 +900,7 @@ impl InMemorySigner { holder_channel_pubkeys, channel_parameters: None, channel_keys_id, - rand_bytes_unique_start, - rand_bytes_index: AtomicCounter::new(), + entropy_source: RandomBytes::new(rand_bytes_unique_start), } } @@ -1063,10 +1076,7 @@ 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) + self.entropy_source.get_secure_random_bytes() } } @@ -1080,7 +1090,11 @@ impl ChannelSigner for InMemorySigner { chan_utils::build_commitment_secret(&self.commitment_seed, idx) } - fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction, _preimages: Vec) -> Result<(), ()> { + fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec) -> Result<(), ()> { + Ok(()) + } + + fn validate_counterparty_revocation(&self, _idx: u64, _secret: &SecretKey) -> Result<(), ()> { Ok(()) } @@ -1102,7 +1116,7 @@ impl ChannelSigner for InMemorySigner { const MISSING_PARAMS_ERR: &'static str = "ChannelSigner::provide_channel_parameters must be called before signing operations"; impl EcdsaChannelSigner for InMemorySigner { - fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _inbound_htlc_preimages: Vec, _outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { let trusted_tx = commitment_tx.trust(); let keys = trusted_tx.keys(); @@ -1131,10 +1145,6 @@ impl EcdsaChannelSigner for InMemorySigner { Ok((commitment_sig, htlc_sigs)) } - fn validate_counterparty_revocation(&self, _idx: u64, _secret: &SecretKey) -> Result<(), ()> { - Ok(()) - } - fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); @@ -1254,11 +1264,11 @@ impl TaprootChannelSigner for InMemorySigner { todo!() } - fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, preimages: Vec, secp_ctx: &Secp256k1) -> Result<(PartialSignatureWithNonce, Vec), ()> { + fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(PartialSignatureWithNonce, Vec), ()> { todo!() } - fn finalize_holder_commitment(&self, commitment_number: u64, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1) -> Result { + fn finalize_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1) -> Result { todo!() } @@ -1344,8 +1354,7 @@ impl ReadableArgs for InMemorySigner where ES::Target: EntropySou 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(), + entropy_source: RandomBytes::new(entropy_source.get_secure_random_bytes()), }) } } @@ -1373,8 +1382,7 @@ pub struct KeysManager { channel_master_key: ExtendedPrivKey, channel_child_index: AtomicUsize, - rand_bytes_unique_start: [u8; 32], - rand_bytes_index: AtomicCounter, + entropy_source: RandomBytes, seed: [u8; 32], starting_time_secs: u64, @@ -1443,8 +1451,7 @@ impl KeysManager { channel_master_key, channel_child_index: AtomicUsize::new(0), - rand_bytes_unique_start, - rand_bytes_index: AtomicCounter::new(), + entropy_source: RandomBytes::new(rand_bytes_unique_start), seed: *seed, starting_time_secs, @@ -1625,10 +1632,7 @@ impl KeysManager { impl EntropySource for KeysManager { 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) + self.entropy_source.get_secure_random_bytes() } } @@ -1882,6 +1886,35 @@ impl PhantomKeysManager { } } +/// An implementation of [`EntropySource`] using ChaCha20. +#[derive(Debug)] +pub struct RandomBytes { + /// Seed from which all randomness produced is derived from. + seed: [u8; 32], + /// Tracks the number of times we've produced randomness to ensure we don't return the same + /// bytes twice. + index: AtomicCounter, +} + +impl RandomBytes { + /// Creates a new instance using the given seed. + pub fn new(seed: [u8; 32]) -> Self { + Self { + seed, + index: AtomicCounter::new(), + } + } +} + +impl EntropySource for RandomBytes { + fn get_secure_random_bytes(&self) -> [u8; 32] { + let index = self.index.get_increment(); + let mut nonce = [0u8; 16]; + nonce[..8].copy_from_slice(&index.to_be_bytes()); + ChaCha20::get_single_block(&self.seed, &nonce) + } +} + // Ensure that EcdsaChannelSigner can have a vtable #[test] pub fn dyn_sign() {