From c20e930b31e973e0fb290322c9ac425002e3b672 Mon Sep 17 00:00:00 2001 From: Devrandom Date: Tue, 4 Feb 2020 09:15:59 -0800 Subject: [PATCH] Add ChannelKeys to ChannelMonitor --- fuzz/src/chanmon_consistency.rs | 33 +++-- fuzz/src/chanmon_deser.rs | 5 +- fuzz/src/full_stack.rs | 54 +++---- lightning/src/chain/keysinterface.rs | 137 +++++++++++++---- lightning/src/ln/chan_utils.rs | 2 +- lightning/src/ln/channel.rs | 110 +++++++------- lightning/src/ln/channelmanager.rs | 36 ++--- lightning/src/ln/channelmonitor.rs | 154 +++++++++++++------- lightning/src/ln/functional_tests.rs | 18 +-- lightning/src/util/enforcing_trait_impls.rs | 40 +++-- lightning/src/util/test_utils.rs | 13 +- 11 files changed, 386 insertions(+), 216 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index b01fabad3..b961b23ac 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -75,7 +75,7 @@ impl Writer for VecWriter { static mut IN_RESTORE: bool = false; pub struct TestChannelMonitor { - pub simple_monitor: Arc>, + pub simple_monitor: Arc>, pub update_ret: Mutex>, pub latest_good_update: Mutex>>, pub latest_update_good: Mutex>, @@ -94,8 +94,8 @@ impl TestChannelMonitor { } } } -impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { - fn add_update_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { +impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { + fn add_update_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { let ret = self.update_ret.lock().unwrap().clone(); if let Ok(()) = ret { let mut ser = VecWriter(Vec::new()); @@ -151,16 +151,17 @@ impl KeysInterface for KeyProvider { } fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys { - EnforcingChannelKeys::new(InMemoryChannelKeys { - funding_key: SecretKey::from_slice(&[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, 4, self.node_id]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[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, 5, self.node_id]).unwrap(), - payment_base_key: SecretKey::from_slice(&[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, self.node_id]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[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, 7, self.node_id]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[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, 8, self.node_id]).unwrap(), - commitment_seed: [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, 9, self.node_id], - remote_channel_pubkeys: None, + let secp_ctx = Secp256k1::signing_only(); + EnforcingChannelKeys::new(InMemoryChannelKeys::new( + &secp_ctx, + SecretKey::from_slice(&[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, 4, self.node_id]).unwrap(), + SecretKey::from_slice(&[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, 5, self.node_id]).unwrap(), + SecretKey::from_slice(&[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, self.node_id]).unwrap(), + SecretKey::from_slice(&[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, 7, self.node_id]).unwrap(), + SecretKey::from_slice(&[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, 8, self.node_id]).unwrap(), + [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, 9, self.node_id], channel_value_satoshis, - }) + )) } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { @@ -191,7 +192,7 @@ pub fn do_test(data: &[u8]) { config.channel_options.fee_proportional_millionths = 0; config.channel_options.announced_channel = true; config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - (Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone() as Arc, broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap()), + (Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone() as Arc>, broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap()), monitor) } } } @@ -211,7 +212,7 @@ pub fn do_test(data: &[u8]) { let mut monitors = HashMap::new(); let mut old_monitors = $old_monitors.latest_good_update.lock().unwrap(); for (outpoint, monitor_ser) in old_monitors.drain() { - monitors.insert(outpoint, <(Sha256d, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), Arc::clone(&logger)).expect("Failed to read monitor").1); + monitors.insert(outpoint, <(Sha256d, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), Arc::clone(&logger)).expect("Failed to read monitor").1); monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser); } let mut monitor_refs = HashMap::new(); @@ -222,14 +223,14 @@ pub fn do_test(data: &[u8]) { let read_args = ChannelManagerReadArgs { keys_manager, fee_estimator: fee_est.clone(), - monitor: monitor.clone() as Arc, + monitor: monitor.clone() as Arc>, tx_broadcaster: broadcast.clone(), logger, default_config: config, channel_monitors: &mut monitor_refs, }; - let res = (<(Sha256d, ChannelManager>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor); + let res = (<(Sha256d, ChannelManager>>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor); for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() { if !was_good { // If the last time we updated a monitor we didn't successfully update (and we diff --git a/fuzz/src/chanmon_deser.rs b/fuzz/src/chanmon_deser.rs index 5dde4a2ea..dbd302660 100644 --- a/fuzz/src/chanmon_deser.rs +++ b/fuzz/src/chanmon_deser.rs @@ -3,6 +3,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash; +use lightning::util::enforcing_trait_impls::EnforcingChannelKeys; use lightning::ln::channelmonitor; use lightning::util::ser::{ReadableArgs, Writer}; @@ -25,10 +26,10 @@ impl Writer for VecWriter { #[inline] pub fn do_test(data: &[u8]) { let logger = Arc::new(test_logger::TestLogger::new("".to_owned())); - if let Ok((latest_block_hash, monitor)) = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), logger.clone()) { + if let Ok((latest_block_hash, monitor)) = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), logger.clone()) { let mut w = VecWriter(Vec::new()); monitor.write_for_disk(&mut w).unwrap(); - let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap(); + let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap(); assert!(latest_block_hash == deserialized_copy.0); assert!(monitor == deserialized_copy.1); w.0.clear(); diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index b39d061b7..36e6d7318 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -136,9 +136,9 @@ impl<'a> Hash for Peer<'a> { } struct MoneyLossDetector<'a> { - manager: Arc>>, - monitor: Arc>, - handler: PeerManager, Arc>>>, + manager: Arc>>>, + monitor: Arc>, + handler: PeerManager, Arc>>>>, peers: &'a RefCell<[bool; 256]>, funding_txn: Vec, @@ -149,7 +149,10 @@ struct MoneyLossDetector<'a> { blocks_connected: u32, } impl<'a> MoneyLossDetector<'a> { - pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc>>, monitor: Arc>, handler: PeerManager, Arc>>>) -> Self { + pub fn new(peers: &'a RefCell<[bool; 256]>, + manager: Arc>>>, + monitor: Arc>, + handler: PeerManager, Arc>>>>) -> Self { MoneyLossDetector { manager, monitor, @@ -249,28 +252,29 @@ impl KeysInterface for KeyProvider { fn get_channel_keys(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys { let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; + let secp_ctx = Secp256k1::signing_only(); EnforcingChannelKeys::new(if inbound { - InMemoryChannelKeys { - funding_key: SecretKey::from_slice(&[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, 1, ctr]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[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, 2, ctr]).unwrap(), - payment_base_key: SecretKey::from_slice(&[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, 3, ctr]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[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, 4, ctr]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[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, 5, ctr]).unwrap(), - commitment_seed: [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], - remote_channel_pubkeys: None, - channel_value_satoshis: channel_value_satoshis, - } + InMemoryChannelKeys::new( + &secp_ctx, + SecretKey::from_slice(&[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, 1, ctr]).unwrap(), + SecretKey::from_slice(&[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, 2, ctr]).unwrap(), + SecretKey::from_slice(&[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, 3, ctr]).unwrap(), + SecretKey::from_slice(&[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, 4, ctr]).unwrap(), + SecretKey::from_slice(&[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, 5, ctr]).unwrap(), + [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, + ) } else { - InMemoryChannelKeys { - funding_key: SecretKey::from_slice(&[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, 7, ctr]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[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, 8, ctr]).unwrap(), - payment_base_key: SecretKey::from_slice(&[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, 9, ctr]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[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, 10, ctr]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[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, 11, ctr]).unwrap(), - commitment_seed: [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], - remote_channel_pubkeys: None, - channel_value_satoshis: channel_value_satoshis, - } + InMemoryChannelKeys::new( + &secp_ctx, + SecretKey::from_slice(&[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, 7, ctr]).unwrap(), + SecretKey::from_slice(&[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, 8, ctr]).unwrap(), + SecretKey::from_slice(&[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, 9, ctr]).unwrap(), + SecretKey::from_slice(&[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, 10, ctr]).unwrap(), + SecretKey::from_slice(&[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, 11, ctr]).unwrap(), + [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, + ) }) } @@ -329,7 +333,7 @@ pub fn do_test(data: &[u8], logger: &Arc) { config.channel_options.fee_proportional_millionths = slice_to_be32(get_slice!(4)); config.channel_options.announced_channel = get_slice!(1)[0] != 0; config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - let channelmanager = Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone() as Arc, broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap()); + let channelmanager = Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone() as Arc>, broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap()); let router = Arc::new(Router::new(PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret()), watch.clone(), Arc::clone(&logger))); let peers = RefCell::new([false; 256]); diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index f5a919bc2..158f71dba 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -16,12 +16,12 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash; use bitcoin_hashes::hash160::Hash as Hash160; use secp256k1::key::{SecretKey, PublicKey}; -use secp256k1::{Secp256k1, Signature}; +use secp256k1::{Secp256k1, Signature, Signing}; use secp256k1; use util::byte_utils; use util::logger::Logger; -use util::ser::Writeable; +use util::ser::{Writeable, Writer, Readable}; use ln::chan_utils; use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys}; @@ -29,6 +29,8 @@ use ln::msgs; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::io::Error; +use ln::msgs::DecodeError; /// When on-chain outputs are created by rust-lightning (which our counterparty is not able to /// claim at any point in the future) an event is generated which you must track and be able to @@ -133,7 +135,8 @@ pub trait KeysInterface: Send + Sync { /// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly /// to the possibility of reentrancy issues by calling the user's code during our deserialization /// routine). -pub trait ChannelKeys : Send { +/// TODO: remove Clone once we start returning ChannelUpdate objects instead of copying ChannelMonitor +pub trait ChannelKeys : Send+Clone { /// Gets the private key for the anchor tx fn funding_key<'a>(&'a self) -> &'a SecretKey; /// Gets the local secret key for blinded revocation pubkey @@ -147,6 +150,8 @@ pub trait ChannelKeys : Send { fn htlc_base_key<'a>(&'a self) -> &'a SecretKey; /// Gets the commitment seed fn commitment_seed<'a>(&'a self) -> &'a [u8; 32]; + /// Gets the local channel public keys and basepoints + fn pubkeys<'a>(&'a self) -> &'a ChannelPublicKeys; /// Create a signature for a remote commitment transaction and associated HTLC transactions. /// @@ -182,21 +187,68 @@ pub trait ChannelKeys : Send { /// A simple implementation of ChannelKeys that just keeps the private keys in memory. pub struct InMemoryChannelKeys { /// Private key of anchor tx - pub funding_key: SecretKey, + funding_key: SecretKey, /// Local secret key for blinded revocation pubkey - pub revocation_base_key: SecretKey, + revocation_base_key: SecretKey, /// Local secret key used in commitment tx htlc outputs - pub payment_base_key: SecretKey, + payment_base_key: SecretKey, /// Local secret key used in HTLC tx - pub delayed_payment_base_key: SecretKey, + delayed_payment_base_key: SecretKey, /// Local htlc secret key used in commitment tx htlc outputs - pub htlc_base_key: SecretKey, + htlc_base_key: SecretKey, /// Commitment seed - pub commitment_seed: [u8; 32], + commitment_seed: [u8; 32], + /// Local public keys and basepoints + pub(crate) local_channel_pubkeys: ChannelPublicKeys, /// Remote public keys and base points - pub remote_channel_pubkeys: Option, + pub(crate) remote_channel_pubkeys: Option, /// The total value of this channel - pub channel_value_satoshis: u64, + channel_value_satoshis: u64, +} + +impl InMemoryChannelKeys { + /// Create a new InMemoryChannelKeys + pub fn new( + secp_ctx: &Secp256k1, + funding_key: SecretKey, + revocation_base_key: SecretKey, + payment_base_key: SecretKey, + delayed_payment_base_key: SecretKey, + htlc_base_key: SecretKey, + commitment_seed: [u8; 32], + channel_value_satoshis: u64) -> InMemoryChannelKeys { + let local_channel_pubkeys = + InMemoryChannelKeys::make_local_keys(secp_ctx, &funding_key, &revocation_base_key, + &payment_base_key, &delayed_payment_base_key, + &htlc_base_key); + InMemoryChannelKeys { + funding_key, + revocation_base_key, + payment_base_key, + delayed_payment_base_key, + htlc_base_key, + commitment_seed, + channel_value_satoshis, + local_channel_pubkeys, + remote_channel_pubkeys: None, + } + } + + fn make_local_keys(secp_ctx: &Secp256k1, + funding_key: &SecretKey, + revocation_base_key: &SecretKey, + payment_base_key: &SecretKey, + delayed_payment_base_key: &SecretKey, + htlc_base_key: &SecretKey) -> ChannelPublicKeys { + let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s); + ChannelPublicKeys { + funding_pubkey: from_secret(&funding_key), + revocation_basepoint: from_secret(&revocation_base_key), + payment_basepoint: from_secret(&payment_base_key), + delayed_payment_basepoint: from_secret(&delayed_payment_base_key), + htlc_basepoint: from_secret(&htlc_base_key), + } + } } impl ChannelKeys for InMemoryChannelKeys { @@ -206,6 +258,7 @@ impl ChannelKeys for InMemoryChannelKeys { fn delayed_payment_base_key(&self) -> &SecretKey { &self.delayed_payment_base_key } fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key } fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed } + fn pubkeys<'a>(&'a self) -> &'a ChannelPublicKeys { &self.local_channel_pubkeys } fn sign_remote_commitment(&self, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { if commitment_tx.input.len() != 1 { return Err(()); } @@ -261,16 +314,50 @@ impl ChannelKeys for InMemoryChannelKeys { } } -impl_writeable!(InMemoryChannelKeys, 0, { - funding_key, - revocation_base_key, - payment_base_key, - delayed_payment_base_key, - htlc_base_key, - commitment_seed, - remote_channel_pubkeys, - channel_value_satoshis -}); +impl Writeable for InMemoryChannelKeys { + fn write(&self, writer: &mut W) -> Result<(), Error> { + self.funding_key.write(writer)?; + self.revocation_base_key.write(writer)?; + self.payment_base_key.write(writer)?; + self.delayed_payment_base_key.write(writer)?; + self.htlc_base_key.write(writer)?; + self.commitment_seed.write(writer)?; + self.remote_channel_pubkeys.write(writer)?; + self.channel_value_satoshis.write(writer)?; + + Ok(()) + } +} + +impl Readable for InMemoryChannelKeys { + fn read(reader: &mut R) -> Result { + let funding_key = Readable::read(reader)?; + let revocation_base_key = Readable::read(reader)?; + let payment_base_key = Readable::read(reader)?; + let delayed_payment_base_key = Readable::read(reader)?; + let htlc_base_key = Readable::read(reader)?; + let commitment_seed = Readable::read(reader)?; + let remote_channel_pubkeys = Readable::read(reader)?; + let channel_value_satoshis = Readable::read(reader)?; + let secp_ctx = Secp256k1::signing_only(); + let local_channel_pubkeys = + InMemoryChannelKeys::make_local_keys(&secp_ctx, &funding_key, &revocation_base_key, + &payment_base_key, &delayed_payment_base_key, + &htlc_base_key); + + Ok(InMemoryChannelKeys { + funding_key, + revocation_base_key, + payment_base_key, + delayed_payment_base_key, + htlc_base_key, + commitment_seed, + channel_value_satoshis, + local_channel_pubkeys, + remote_channel_pubkeys + }) + } +} /// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key /// and derives keys from that. @@ -411,16 +498,16 @@ impl KeysInterface for KeysManager { let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_base_key); let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key); - InMemoryChannelKeys { + InMemoryChannelKeys::new( + &self.secp_ctx, funding_key, revocation_base_key, payment_base_key, delayed_payment_base_key, htlc_base_key, commitment_seed, - remote_channel_pubkeys: None, - channel_value_satoshis, - } + channel_value_satoshis + ) } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 51a2c4b04..e7bea9091 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -155,7 +155,7 @@ pub struct TxCreationKeys { } /// One counterparty's public keys which do not change over the life of a channel. -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct ChannelPublicKeys { /// The public key which is used to sign all commitment transactions, as it appears in the /// on-chain channel lock-in 2-of-2 multisig output. diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 164a128ac..c86136d60 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -344,7 +344,7 @@ pub(super) struct Channel { their_shutdown_scriptpubkey: Option