Merge pull request #2217 from alecchendev/2023-04-expose-hash-in-balance
[rust-lightning] / lightning / src / chain / keysinterface.rs
index bba7d7596b2098b8dd6cfef2f8efbbf0c079f2a1..b1290708b95f70a71ebf6193cceb1677aa3150bd 100644 (file)
@@ -21,7 +21,6 @@ use bitcoin::util::sighash;
 
 use bitcoin::bech32::u5;
 use bitcoin::hashes::{Hash, HashEngine};
-use bitcoin::hashes::sha256::HashEngine as Sha256State;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::WPubkeyHash;
@@ -33,11 +32,11 @@ 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};
-#[cfg(anchors)]
-use crate::util::events::HTLCDescriptor;
+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;
 use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
 use crate::ln::{chan_utils, PaymentPreimage};
 use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction};
@@ -46,15 +45,18 @@ 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};
+use crate::util::atomic_counter::AtomicCounter;
+use crate::util::chacha20::ChaCha20;
 use crate::util::invoice::construct_invoice_preimage;
 
 /// Used as initial key material, to be expanded into multiple secret keys (but not to be used
 /// directly). This is used within LDK to encrypt/decrypt inbound payment data.
 ///
-/// (C-not exported) as we just use `[u8; 32]` directly
+/// This is not exported to bindings users as we just use `[u8; 32]` directly
 #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
 pub struct KeyMaterial(pub [u8; 32]);
 
@@ -134,7 +136,7 @@ impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, {
 /// outpoint describing which `txid` and output `index` is available, the full output which exists
 /// at that `txid`/`index`, and any keys or other information required to sign.
 ///
-/// [`SpendableOutputs`]: crate::util::events::Event::SpendableOutputs
+/// [`SpendableOutputs`]: crate::events::Event::SpendableOutputs
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum SpendableOutputDescriptor {
        /// An output to a script which was provided via [`SignerProvider`] directly, either from
@@ -424,7 +426,7 @@ pub trait EcdsaChannelSigner: ChannelSigner {
 ///
 /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
 /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
-pub trait Sign: EcdsaChannelSigner + Writeable {}
+pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable {}
 
 /// Specifies the recipient of an invoice.
 ///
@@ -505,8 +507,8 @@ pub trait NodeSigner {
 
 /// A trait that can return signer instances for individual channels.
 pub trait SignerProvider {
-       /// A type which implements [`Sign`] which will be returned by [`Self::derive_channel_signer`].
-       type Signer : Sign;
+       /// A type which implements [`WriteableEcdsaChannelSigner`] which will be returned by [`Self::derive_channel_signer`].
+       type Signer : WriteableEcdsaChannelSigner;
 
        /// Generates a unique `channel_keys_id` that can be used to obtain a [`Self::Signer`] through
        /// [`SignerProvider::derive_channel_signer`]. The `user_channel_id` is provided to allow
@@ -526,7 +528,7 @@ pub trait SignerProvider {
 
        /// Reads a [`Signer`] for this [`SignerProvider`] from the given input stream.
        /// This is only called during deserialization of other objects which contain
-       /// [`Sign`]-implementing objects (i.e., [`ChannelMonitor`]s and [`ChannelManager`]s).
+       /// [`WriteableEcdsaChannelSigner`]-implementing objects (i.e., [`ChannelMonitor`]s and [`ChannelManager`]s).
        /// The bytes are exactly those which `<Self::Signer as Writeable>::write()` writes, and
        /// contain no versioning scheme. You may wish to include your own version prefix and ensure
        /// you've read all of the provided bytes to ensure no corruption occurred.
@@ -552,8 +554,7 @@ pub trait SignerProvider {
        fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
 }
 
-#[derive(Clone)]
-/// A simple implementation of [`Sign`] that just keeps the private keys in memory.
+/// 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
 /// a secure external signer.
@@ -579,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 {
@@ -593,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,
@@ -609,6 +635,8 @@ impl InMemorySigner {
                        holder_channel_pubkeys,
                        channel_parameters: None,
                        channel_keys_id,
+                       rand_bytes_unique_start,
+                       rand_bytes_index: AtomicCounter::new(),
                }
        }
 
@@ -685,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(()); }
@@ -721,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(()); }
@@ -735,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<secp256k1::All>) -> PublicKey {
                let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap();
@@ -773,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());
@@ -798,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))
        }
 
@@ -809,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))
        }
 
@@ -825,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<secp256k1::All>) -> Result<Signature, ()> {
@@ -839,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)]
@@ -857,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<secp256k1::All>) -> Result<Signature, ()> {
@@ -868,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<secp256k1::All>) -> Result<Signature, ()> {
@@ -884,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<secp256k1::All>
        ) -> Result<Signature, ()> {
                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))
        }
 }
 
@@ -899,7 +936,7 @@ const SERIALIZATION_VERSION: u8 = 1;
 
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl Sign for InMemorySigner {}
+impl WriteableEcdsaChannelSigner for InMemorySigner {}
 
 impl Writeable for InMemorySigner {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
@@ -921,8 +958,8 @@ impl Writeable for InMemorySigner {
        }
 }
 
-impl Readable for InMemorySigner {
-       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+impl<ES: Deref> ReadableArgs<ES> for InMemorySigner where ES::Target: EntropySource {
+       fn read<R: io::Read>(reader: &mut R, entropy_source: ES) -> Result<Self, DecodeError> {
                let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
 
                let funding_key = Readable::read(reader)?;
@@ -952,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(),
                })
        }
 }
@@ -979,9 +1018,8 @@ pub struct KeysManager {
        channel_master_key: ExtendedPrivKey,
        channel_child_index: AtomicUsize,
 
-       rand_bytes_master_key: ExtendedPrivKey,
-       rand_bytes_child_index: AtomicUsize,
-       rand_bytes_unique_start: Sha256State,
+       rand_bytes_unique_start: [u8; 32],
+       rand_bytes_index: AtomicCounter,
 
        seed: [u8; 32],
        starting_time_secs: u64,
@@ -1027,15 +1065,16 @@ impl KeysManager {
                                        Err(_) => panic!("Your RNG is busted"),
                                };
                                let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()).expect("Your RNG is busted");
-                               let rand_bytes_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4).unwrap()).expect("Your RNG is busted");
                                let inbound_payment_key: SecretKey = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted").private_key;
                                let mut inbound_pmt_key_bytes = [0; 32];
                                inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]);
 
-                               let mut rand_bytes_unique_start = Sha256::engine();
-                               rand_bytes_unique_start.input(&starting_time_secs.to_be_bytes());
-                               rand_bytes_unique_start.input(&starting_time_nanos.to_be_bytes());
-                               rand_bytes_unique_start.input(seed);
+                               let mut rand_bytes_engine = Sha256::engine();
+                               rand_bytes_engine.input(&starting_time_secs.to_be_bytes());
+                               rand_bytes_engine.input(&starting_time_nanos.to_be_bytes());
+                               rand_bytes_engine.input(seed);
+                               rand_bytes_engine.input(b"LDK PRNG Seed");
+                               let rand_bytes_unique_start = Sha256::from_engine(rand_bytes_engine).into_inner();
 
                                let mut res = KeysManager {
                                        secp_ctx,
@@ -1049,9 +1088,8 @@ impl KeysManager {
                                        channel_master_key,
                                        channel_child_index: AtomicUsize::new(0),
 
-                                       rand_bytes_master_key,
-                                       rand_bytes_child_index: AtomicUsize::new(0),
                                        rand_bytes_unique_start,
+                                       rand_bytes_index: AtomicCounter::new(),
 
                                        seed: *seed,
                                        starting_time_secs,
@@ -1064,7 +1102,13 @@ impl KeysManager {
                        Err(_) => panic!("Your rng is busted"),
                }
        }
-       /// Derive an old [`Sign`] containing per-channel secrets based on a key derivation parameters.
+
+       /// Gets the "node_id" secret key used to sign gossip announcements, decode onion data, etc.
+       pub fn get_node_secret_key(&self) -> SecretKey {
+               self.node_secret
+       }
+
+       /// Derive an old [`WriteableEcdsaChannelSigner`] containing per-channel secrets based on a key derivation parameters.
        pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner {
                let chan_id = u64::from_be_bytes(params[0..8].try_into().unwrap());
                let mut unique_start = Sha256::engine();
@@ -1101,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,
@@ -1112,6 +1157,7 @@ impl KeysManager {
                        commitment_seed,
                        channel_value_satoshis,
                        params.clone(),
+                       prng_seed,
                )
        }
 
@@ -1227,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);
@@ -1248,14 +1294,10 @@ impl KeysManager {
 
 impl EntropySource for KeysManager {
        fn get_secure_random_bytes(&self) -> [u8; 32] {
-               let mut sha = self.rand_bytes_unique_start.clone();
-
-               let child_ix = self.rand_bytes_child_index.fetch_add(1, Ordering::AcqRel);
-               let child_privkey = self.rand_bytes_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
-               sha.input(&child_privkey.private_key[..]);
-
-               sha.input(b"Unique Secure Random Bytes Salt");
-               Sha256::from_engine(sha).into_inner()
+               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)
        }
 }
 
@@ -1293,7 +1335,7 @@ impl NodeSigner for KeysManager {
 
        fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
                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))
        }
 }
 
@@ -1321,7 +1363,7 @@ impl SignerProvider for KeysManager {
        }
 
        fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
-               InMemorySigner::read(&mut io::Cursor::new(reader))
+               InMemorySigner::read(&mut io::Cursor::new(reader), self)
        }
 
        fn get_destination_script(&self) -> Script {
@@ -1462,6 +1504,17 @@ impl PhantomKeysManager {
        pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner {
                self.inner.derive_channel_keys(channel_value_satoshis, params)
        }
+
+       /// Gets the "node_id" secret key used to sign gossip announcements, decode onion data, etc.
+       pub fn get_node_secret_key(&self) -> SecretKey {
+               self.inner.get_node_secret_key()
+       }
+
+       /// Gets the "node_id" secret key of the phantom node used to sign invoices, decode the
+       /// last-hop onion data, etc.
+       pub fn get_phantom_node_secret_key(&self) -> SecretKey {
+               self.phantom_secret
+       }
 }
 
 // Ensure that EcdsaChannelSigner can have a vtable
@@ -1469,3 +1522,58 @@ impl PhantomKeysManager {
 pub fn dyn_sign() {
        let _signer: Box<dyn EcdsaChannelSigner>;
 }
+
+#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
+mod benches {
+       use std::sync::{Arc, mpsc};
+       use std::sync::mpsc::TryRecvError;
+       use std::thread;
+       use std::time::Duration;
+       use bitcoin::blockdata::constants::genesis_block;
+       use bitcoin::Network;
+       use crate::chain::keysinterface::{EntropySource, KeysManager};
+
+       use test::Bencher;
+
+       #[bench]
+       fn bench_get_secure_random_bytes(bench: &mut Bencher) {
+               let seed = [0u8; 32];
+               let now = Duration::from_secs(genesis_block(Network::Testnet).header.time as u64);
+               let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_micros()));
+
+               let mut handles = Vec::new();
+               let mut stops = Vec::new();
+               for _ in 1..5 {
+                       let keys_manager_clone = Arc::clone(&keys_manager);
+                       let (stop_sender, stop_receiver) = mpsc::channel();
+                       let handle = thread::spawn(move || {
+                               loop {
+                                       keys_manager_clone.get_secure_random_bytes();
+                                       match stop_receiver.try_recv() {
+                                               Ok(_) | Err(TryRecvError::Disconnected) => {
+                                                       println!("Terminating.");
+                                                       break;
+                                               }
+                                               Err(TryRecvError::Empty) => {}
+                                       }
+                               }
+                       });
+                       handles.push(handle);
+                       stops.push(stop_sender);
+               }
+
+               bench.iter(|| {
+                       for _ in 1..100 {
+                               keys_manager.get_secure_random_bytes();
+                       }
+               });
+
+               for stop in stops {
+                       let _ = stop.send(());
+               }
+               for handle in handles {
+                       handle.join().unwrap();
+               }
+       }
+
+}