diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 4db35d957..9cdeace66 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -24,7 +24,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256d; use lightning::chain::chaininterface; use lightning::chain::transaction::OutPoint; use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; -use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; +use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use lightning::ln::channelmonitor; use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate}; use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs}; @@ -130,6 +130,8 @@ struct KeyProvider { channel_id: atomic::AtomicU8, } impl KeysInterface for KeyProvider { + type ChanKeySigner = InMemoryChannelKeys; + fn get_node_secret(&self) -> SecretKey { 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, self.node_id]).unwrap() } @@ -146,8 +148,8 @@ impl KeysInterface for KeyProvider { PublicKey::from_secret_key(&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, 3, self.node_id]).unwrap()) } - fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { - ChannelKeys { + fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys { + 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(), @@ -223,7 +225,7 @@ pub fn do_test(data: &[u8]) { channel_monitors: &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/full_stack.rs b/fuzz/src/full_stack.rs index 4c3989d66..4408c4392 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -20,7 +20,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash; use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; use lightning::chain::transaction::OutPoint; -use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; +use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use lightning::ln::channelmonitor; use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage}; use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; @@ -135,7 +135,7 @@ impl<'a> Hash for Peer<'a> { } struct MoneyLossDetector<'a, 'b> { - manager: Arc>, + manager: Arc>, monitor: Arc>, handler: PeerManager>, @@ -148,7 +148,7 @@ struct MoneyLossDetector<'a, 'b> { blocks_connected: u32, } impl<'a, 'b> MoneyLossDetector<'a, 'b> { - pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc>, monitor: Arc>, handler: PeerManager>) -> Self { + pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc>, monitor: Arc>, handler: PeerManager>) -> Self { MoneyLossDetector { manager, monitor, @@ -228,6 +228,8 @@ struct KeyProvider { counter: AtomicU64, } impl KeysInterface for KeyProvider { + type ChanKeySigner = InMemoryChannelKeys; + fn get_node_secret(&self) -> SecretKey { self.node_secret.clone() } @@ -244,10 +246,10 @@ impl KeysInterface for KeyProvider { PublicKey::from_secret_key(&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, 0, 0]).unwrap()) } - fn get_channel_keys(&self, inbound: bool) -> ChannelKeys { + fn get_channel_keys(&self, inbound: bool) -> InMemoryChannelKeys { let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; if inbound { - ChannelKeys { + 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(), @@ -256,7 +258,7 @@ impl KeysInterface for KeyProvider { 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], } } else { - ChannelKeys { + 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(), diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index c71d30ccb..5ffdc7130 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -68,6 +68,9 @@ pub enum SpendableOutputDescriptor { /// A trait to describe an object which can get user secrets and key material. pub trait KeysInterface: Send + Sync { + /// A type which implements ChannelKeys which will be returned by get_channel_keys. + type ChanKeySigner : ChannelKeys; + /// Get node secret key (aka node_id or network_key) fn get_node_secret(&self) -> SecretKey; /// Get destination redeemScript to encumber static protocol exit points. @@ -76,7 +79,7 @@ pub trait KeysInterface: Send + Sync { fn get_shutdown_pubkey(&self) -> PublicKey; /// Get a new set of ChannelKeys for per-channel secrets. These MUST be unique even if you /// restarted with some stale data! - fn get_channel_keys(&self, inbound: bool) -> ChannelKeys; + fn get_channel_keys(&self, inbound: bool) -> Self::ChanKeySigner; /// Get a secret and PRNG seed for construting an onion packet fn get_onion_rand(&self) -> (SecretKey, [u8; 32]); /// Get a unique temporary channel id. Channels will be referred to by this until the funding @@ -85,9 +88,33 @@ pub trait KeysInterface: Send + Sync { fn get_channel_id(&self) -> [u8; 32]; } -/// Set of lightning keys needed to operate a channel as described in BOLT 3 +/// Set of lightning keys needed to operate a channel as described in BOLT 3. +/// +/// If you're implementing a custom signer, you almost certainly want to implement +/// Readable/Writable to serialize out a unique reference to this set of keys so +/// that you can serialize the full ChannelManager object. +/// +/// (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 { + /// 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 + fn revocation_base_key<'a>(&'a self) -> &'a SecretKey; + /// Gets the local secret key used in commitment tx htlc outputs + fn payment_base_key<'a>(&'a self) -> &'a SecretKey; + /// Gets the local secret key used in HTLC tx + fn delayed_payment_base_key<'a>(&'a self) -> &'a SecretKey; + /// Gets the local htlc secret key used in commitment tx htlc outputs + fn htlc_base_key<'a>(&'a self) -> &'a SecretKey; + /// Gets the commitment seed + fn commitment_seed<'a>(&'a self) -> &'a [u8; 32]; +} + #[derive(Clone)] -pub struct ChannelKeys { +/// 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, /// Local secret key for blinded revocation pubkey @@ -102,7 +129,16 @@ pub struct ChannelKeys { pub commitment_seed: [u8; 32], } -impl_writeable!(ChannelKeys, 0, { +impl ChannelKeys for InMemoryChannelKeys { + fn funding_key(&self) -> &SecretKey { &self.funding_key } + fn revocation_base_key(&self) -> &SecretKey { &self.revocation_base_key } + fn payment_base_key(&self) -> &SecretKey { &self.payment_base_key } + 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 } +} + +impl_writeable!(InMemoryChannelKeys, 0, { funding_key, revocation_base_key, payment_base_key, @@ -203,6 +239,8 @@ impl KeysManager { } impl KeysInterface for KeysManager { + type ChanKeySigner = InMemoryChannelKeys; + fn get_node_secret(&self) -> SecretKey { self.node_secret.clone() } @@ -215,7 +253,7 @@ impl KeysInterface for KeysManager { self.shutdown_pubkey.clone() } - fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { + fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys { // We only seriously intend to rely on the channel_master_key for true secure // entropy, everything else just ensures uniqueness. We rely on the unique_start (ie // starting_time provided in the constructor) to be unique. @@ -248,7 +286,7 @@ 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); - ChannelKeys { + InMemoryChannelKeys { funding_key, revocation_base_key, payment_base_key, diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 1d8dd3076..b69cee080 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -20,8 +20,8 @@ pub const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; // Various functions for key derivation and transaction creation for use within channels. Primarily // used in Channel and ChannelMonitor. -pub fn build_commitment_secret(commitment_seed: [u8; 32], idx: u64) -> [u8; 32] { - let mut res: [u8; 32] = commitment_seed; +pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] { + let mut res: [u8; 32] = commitment_seed.clone(); for i in 0..48 { let bitpos = 47 - i; if idx & (1 << bitpos) == (1 << bitpos) { diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e3edc0e9a..ca4dc89c3 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -228,7 +228,7 @@ enum UpdateStatus { // has been completed, and then turn into a Channel to get compiler-time enforcement of things like // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. -pub(super) struct Channel { +pub(super) struct Channel { config: ChannelConfig, user_id: u64, @@ -239,7 +239,7 @@ pub(super) struct Channel { secp_ctx: Secp256k1, channel_value_satoshis: u64, - local_keys: ChannelKeys, + local_keys: ChanSigner, shutdown_pubkey: PublicKey, // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction @@ -410,7 +410,7 @@ macro_rules! secp_check { }; } -impl Channel { +impl Channel { // Convert constants + channel value to limits: fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 { channel_value_satoshis * 1000 / 10 //TODO @@ -433,7 +433,7 @@ impl Channel { } // Constructors: - pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result { + pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result, APIError> { let chan_keys = keys_provider.get_channel_keys(false); if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { @@ -449,15 +449,15 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if Channel::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::derive_our_dust_limit_satoshis(background_feerate) { + if Channel::::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::::derive_our_dust_limit_satoshis(background_feerate) { return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate}); } let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); let secp_ctx = Secp256k1::new(); - let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, - &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, + let channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, keys_provider.get_destination_script(), logger.clone()); Ok(Channel { @@ -509,11 +509,11 @@ impl Channel { feerate_per_kw: feerate, their_dust_limit_satoshis: 0, - our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate), + our_dust_limit_satoshis: Channel::::derive_our_dust_limit_satoshis(background_feerate), their_max_htlc_value_in_flight_msat: 0, their_channel_reserve_satoshis: 0, their_htlc_minimum_msat: 0, - our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate), + our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(feerate), their_to_self_delay: 0, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: 0, @@ -551,7 +551,7 @@ impl Channel { /// Creates a new channel from a remote sides' request for one. /// Assumes chain_hash has already been checked and corresponds with what we expect! - pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, their_local_features: LocalFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result { + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc>, their_node_id: PublicKey, their_local_features: LocalFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result, ChannelError> { let chan_keys = keys_provider.get_channel_keys(true); let mut local_config = (*config).channel_options.clone(); @@ -578,7 +578,7 @@ impl Channel { if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 { return Err(ChannelError::Close("Minimum htlc value is full channel value")); } - Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; + Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; if msg.to_self_delay > config.peer_channel_config_limits.their_to_self_delay || msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT { return Err(ChannelError::Close("They wanted our payments to be delayed by a needlessly long period")); @@ -626,8 +626,8 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - let our_dust_limit_satoshis = Channel::derive_our_dust_limit_satoshis(background_feerate); - let our_channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(msg.funding_satoshis); + let our_dust_limit_satoshis = Channel::::derive_our_dust_limit_satoshis(background_feerate); + let our_channel_reserve_satoshis = Channel::::get_our_channel_reserve_satoshis(msg.funding_satoshis); if our_channel_reserve_satoshis < our_dust_limit_satoshis { return Err(ChannelError::Close("Suitable channel reserve not found. aborting")); } @@ -652,8 +652,8 @@ impl Channel { } let secp_ctx = Secp256k1::new(); - let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, - &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, + let mut channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, keys_provider.get_destination_script(), logger.clone()); channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); channel_monitor.set_their_to_self_delay(msg.to_self_delay); @@ -732,7 +732,7 @@ impl Channel { their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), their_channel_reserve_satoshis: msg.channel_reserve_satoshis, their_htlc_minimum_msat: msg.htlc_minimum_msat, - our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), + our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), their_to_self_delay: msg.to_self_delay, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: msg.max_accepted_htlcs, @@ -766,7 +766,7 @@ impl Channel { // Utilities to derive keys: fn build_local_commitment_secret(&self, idx: u64) -> SecretKey { - let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, idx); + let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), idx); SecretKey::from_slice(&res).unwrap() } @@ -774,7 +774,7 @@ impl Channel { fn get_commitment_transaction_number_obscure_factor(&self) -> u64 { let mut sha = Sha256::engine(); - let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key); + let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()); if self.channel_outbound { sha.input(&our_payment_basepoint.serialize()); @@ -952,7 +952,7 @@ impl Channel { }; debug_assert!(max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.their_channel_reserve_satoshis as i64); max_commitment_tx_output.0 = cmp::max(max_commitment_tx_output.0, value_to_self_msat as u64); - debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis) as i64); + debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis) as i64); max_commitment_tx_output.1 = cmp::max(max_commitment_tx_output.1, value_to_remote_msat as u64); } @@ -1097,8 +1097,8 @@ impl Channel { /// TODO Some magic rust shit to compile-time check this? fn build_local_transaction_keys(&self, commitment_number: u64) -> Result { let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(commitment_number)); - let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key); + let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()); + let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &self.their_revocation_basepoint.unwrap(), &self.their_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap()), "Local tx keys generation got bogus keys")) } @@ -1110,9 +1110,9 @@ impl Channel { fn build_remote_transaction_keys(&self) -> Result { //TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we //may see payments to it! - let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key); - let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key); + let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()); + let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()); + let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &self.their_delayed_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap(), &revocation_basepoint, &payment_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys")) } @@ -1122,7 +1122,7 @@ impl Channel { /// Panics if called before accept_channel/new_from_req pub fn get_funding_redeemscript(&self) -> Script { let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2); - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize(); + let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); let their_funding_key = self.their_funding_pubkey.expect("get_funding_redeemscript only allowed after accept_channel").serialize(); if our_funding_key[..] < their_funding_key[..] { builder.push_slice(&our_funding_key) @@ -1144,11 +1144,11 @@ impl Channel { let funding_redeemscript = self.get_funding_redeemscript(); let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key); + let our_sig = self.secp_ctx.sign(&sighash, self.local_keys.funding_key()); tx.input[0].witness.push(Vec::new()); // First is the multisig dummy - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize(); + let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); let their_funding_key = self.their_funding_pubkey.unwrap().serialize(); if our_funding_key[..] < their_funding_key[..] { tx.input[0].witness.push(our_sig.serialize_der().to_vec()); @@ -1179,7 +1179,7 @@ impl Channel { let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); - let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters"); + let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, self.local_keys.htlc_base_key()), "Derived invalid key, peer is maliciously selecting parameters"); let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key) == keys.a_htlc_key; Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx)) @@ -1417,7 +1417,7 @@ impl Channel { if msg.channel_reserve_satoshis < self.our_dust_limit_satoshis { return Err(ChannelError::Close("Peer never wants payout outputs?")); } - if msg.dust_limit_satoshis > Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis) { + if msg.dust_limit_satoshis > Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis) { return Err(ChannelError::Close("Dust limit is bigger than our channel reverse")); } if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 { @@ -1521,7 +1521,7 @@ impl Channel { let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), local_keys)) + Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), local_keys)) } pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> { @@ -1695,7 +1695,7 @@ impl Channel { return Err(ChannelError::Close("Remote tried to push more than our max accepted HTLCs")); } // Check our_max_htlc_value_in_flight_msat - if htlc_inbound_value_msat + msg.amount_msat > Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) { + if htlc_inbound_value_msat + msg.amount_msat > Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) { return Err(ChannelError::Close("Remote HTLC add would put them over our max HTLC value")); } // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet @@ -1718,7 +1718,7 @@ impl Channel { removed_outbound_total_msat += htlc.amount_msat; } } - if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat { + if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat { return Err(ChannelError::Close("Remote HTLC add would put them over their reserve value")); } if self.next_remote_htlc_id != msg.htlc_id { @@ -1884,7 +1884,7 @@ impl Channel { } let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1)); - let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1); + let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 1); // Update state now that we've passed all the can-fail calls... let mut need_our_commitment = false; @@ -2444,7 +2444,7 @@ impl Channel { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish")); } - Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; + Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; self.pending_update_fee = Some(msg.feerate_per_kw as u64); self.channel_update_count += 1; Ok(()) @@ -2452,7 +2452,7 @@ impl Channel { fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number)); - let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 2); + let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 2); msgs::RevokeAndACK { channel_id: self.channel_id, per_commitment_secret, @@ -2535,7 +2535,7 @@ impl Channel { if msg.next_remote_commitment_number > 0 { match msg.data_loss_protect { OptionalField::Present(ref data_loss) => { - if chan_utils::build_commitment_secret(self.local_keys.commitment_seed, INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret { + if chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret { return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided")); } if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { @@ -2671,7 +2671,7 @@ impl Channel { Some(msgs::ClosingSigned { channel_id: self.channel_id, fee_satoshis: total_fee_satoshis, - signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key), + signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key()), }) } @@ -2794,7 +2794,7 @@ impl Channel { let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap()); let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate * closing_tx_max_weight / 1000, false); sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key); + let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key()); self.last_sent_closing_fee = Some(($new_feerate, used_total_fee)); return Ok((Some(msgs::ClosingSigned { channel_id: self.channel_id, @@ -2912,7 +2912,7 @@ impl Channel { } #[cfg(test)] - pub fn get_local_keys(&self) -> &ChannelKeys { + pub fn get_local_keys(&self) -> &ChanSigner { &self.local_keys } @@ -3171,17 +3171,17 @@ impl Channel { funding_satoshis: self.channel_value_satoshis, push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat, dust_limit_satoshis: self.our_dust_limit_satoshis, - max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), - channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis), + max_htlc_value_in_flight_msat: Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), + channel_reserve_satoshis: Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.our_htlc_minimum_msat, feerate_per_kw: fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u32, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key), - payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key), + funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), + revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), + payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()), + delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), + htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), channel_flags: if self.config.announced_channel {1} else {0}, shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) @@ -3204,17 +3204,17 @@ impl Channel { msgs::AcceptChannel { temporary_channel_id: self.channel_id, dust_limit_satoshis: self.our_dust_limit_satoshis, - max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), - channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis), + max_htlc_value_in_flight_msat: Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), + channel_reserve_satoshis: Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.our_htlc_minimum_msat, minimum_depth: self.minimum_depth, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key), - payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key), + funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), + revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), + payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()), + delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), + htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) } @@ -3229,7 +3229,7 @@ impl Channel { let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), remote_initial_commitment_tx)) + Ok((self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), remote_initial_commitment_tx)) } /// Updates channel state with knowledge of the funding transaction's txid/index, and generates @@ -3300,7 +3300,7 @@ impl Channel { } let were_node_one = our_node_id.serialize()[..] < self.their_node_id.serialize()[..]; - let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key); + let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()); let msg = msgs::UnsignedChannelAnnouncement { features: msgs::GlobalFeatures::new(), @@ -3314,7 +3314,7 @@ impl Channel { }; let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - let sig = self.secp_ctx.sign(&msghash, &self.local_keys.funding_key); + let sig = self.secp_ctx.sign(&msghash, self.local_keys.funding_key()); Ok((msg, sig)) } @@ -3532,8 +3532,8 @@ impl Channel { let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw); let remote_commitment_txid = remote_commitment_tx.0.txid(); let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key); - log_trace!(self, "Signing remote commitment tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&remote_commitment_tx.0), encode::serialize_hex(&funding_script), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize()), log_bytes!(our_sig.serialize_compact()[..])); + let our_sig = self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()); + log_trace!(self, "Signing remote commitment tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&remote_commitment_tx.0), encode::serialize_hex(&funding_script), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize()), log_bytes!(our_sig.serialize_compact()[..])); let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1); for &(ref htlc, _) in remote_commitment_tx.2.iter() { @@ -3541,7 +3541,7 @@ impl Channel { let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys); let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); - let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters"); + let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, self.local_keys.htlc_base_key()), "Derived invalid key, peer is maliciously selecting parameters"); htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key)); log_trace!(self, "Signing remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).serialize()), log_bytes!(htlc_sigs.last().unwrap().serialize_compact()[..])); } @@ -3688,7 +3688,7 @@ impl Readable for InboundHTLCRemovalReason { } } -impl Writeable for Channel { +impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called but include holding cell updates (and obviously we don't modify self). @@ -3892,7 +3892,7 @@ impl Writeable for Channel { } } -impl ReadableArgs> for Channel { +impl> ReadableArgs> for Channel { fn read(reader: &mut R, logger: Arc) -> Result { let _ver: u8 = Readable::read(reader)?; let min_ver: u8 = Readable::read(reader)?; @@ -4152,7 +4152,7 @@ mod tests { use ln::channel::MAX_FUNDING_SATOSHIS; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; - use chain::keysinterface::KeysInterface; + use chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::test_utils; @@ -4181,9 +4181,11 @@ mod tests { } struct Keys { - chan_keys: ChannelKeys, + chan_keys: InMemoryChannelKeys, } impl KeysInterface for Keys { + type ChanKeySigner = InMemoryChannelKeys; + fn get_node_secret(&self) -> SecretKey { panic!(); } fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); @@ -4198,7 +4200,7 @@ mod tests { PublicKey::from_secret_key(&secp_ctx, &channel_close_key) } - fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { self.chan_keys.clone() } + fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys { self.chan_keys.clone() } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { panic!(); } fn get_channel_id(&self) -> [u8; 32] { [0; 32] } } @@ -4210,7 +4212,7 @@ mod tests { let logger : Arc = Arc::new(test_utils::TestLogger::new()); let secp_ctx = Secp256k1::new(); - let chan_keys = ChannelKeys { + let chan_keys = InMemoryChannelKeys { funding_key: SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(), payment_base_key: SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(), delayed_payment_base_key: SecretKey::from_slice(&hex::decode("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap(), @@ -4220,14 +4222,14 @@ mod tests { revocation_base_key: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), commitment_seed: [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], }; - assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).serialize()[..], + assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..], hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); - let keys_provider: Arc = Arc::new(Keys { chan_keys }); + let keys_provider: Arc> = Arc::new(Keys { chan_keys }); let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut config = UserConfig::default(); config.channel_options.announced_channel = false; - let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test + let mut chan = Channel::::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546; @@ -4251,10 +4253,10 @@ mod tests { // We can't just use build_local_transaction_keys here as the per_commitment_secret is not // derived from a commitment_seed, so instead we copy it here and call // build_commitment_transaction. - let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.delayed_payment_base_key); + let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.delayed_payment_base_key()); let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); - let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.htlc_base_key); + let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.htlc_base_key()); let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint.unwrap(), &chan.their_payment_basepoint.unwrap(), &chan.their_htlc_basepoint.unwrap()).unwrap(); let mut unsigned_tx: (Transaction, Vec); @@ -4699,21 +4701,21 @@ mod tests { let mut seed = [0; 32]; seed[0..32].clone_from_slice(&hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655), + assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()[..]); seed[0..32].clone_from_slice(&hex::decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655), + assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()[..]); - assert_eq!(chan_utils::build_commitment_secret(seed, 0xaaaaaaaaaaa), + assert_eq!(chan_utils::build_commitment_secret(&seed, 0xaaaaaaaaaaa), hex::decode("56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528").unwrap()[..]); - assert_eq!(chan_utils::build_commitment_secret(seed, 0x555555555555), + assert_eq!(chan_utils::build_commitment_secret(&seed, 0x555555555555), hex::decode("9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31").unwrap()[..]); seed[0..32].clone_from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 1), + assert_eq!(chan_utils::build_commitment_secret(&seed, 1), hex::decode("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c").unwrap()[..]); } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5a59d0c45..8ff6918d4 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -34,7 +34,7 @@ use ln::msgs; use ln::msgs::LocalFeatures; use ln::onion_utils; use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; -use chain::keysinterface::KeysInterface; +use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::config::UserConfig; use util::{byte_utils, events}; use util::ser::{Readable, ReadableArgs, Writeable, Writer}; @@ -49,6 +49,8 @@ use std::sync::{Arc, Mutex, MutexGuard, RwLock}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; +const SIXTY_FIVE_ZEROS: [u8; 65] = [0; 65]; + // We hold various information about HTLC relay in the HTLC objects in Channel itself: // // Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should @@ -254,8 +256,8 @@ pub(super) enum RAACommitmentOrder { } // Note this is only exposed in cfg(test): -pub(super) struct ChannelHolder { - pub(super) by_id: HashMap<[u8; 32], Channel>, +pub(super) struct ChannelHolder { + pub(super) by_id: HashMap<[u8; 32], Channel>, pub(super) short_to_id: HashMap, /// short channel id -> forward infos. Key of 0 means payments received /// Note that while this is held in the same mutex as the channels themselves, no consistency @@ -272,15 +274,15 @@ pub(super) struct ChannelHolder { /// for broadcast messages, where ordering isn't as strict). pub(super) pending_msg_events: Vec, } -pub(super) struct MutChannelHolder<'a> { - pub(super) by_id: &'a mut HashMap<[u8; 32], Channel>, +pub(super) struct MutChannelHolder<'a, ChanSigner: ChannelKeys + 'a> { + pub(super) by_id: &'a mut HashMap<[u8; 32], Channel>, pub(super) short_to_id: &'a mut HashMap, pub(super) forward_htlcs: &'a mut HashMap>, pub(super) claimable_htlcs: &'a mut HashMap>, pub(super) pending_msg_events: &'a mut Vec, } -impl ChannelHolder { - pub(super) fn borrow_parts(&mut self) -> MutChannelHolder { +impl ChannelHolder { + pub(super) fn borrow_parts(&mut self) -> MutChannelHolder { MutChannelHolder { by_id: &mut self.by_id, short_to_id: &mut self.short_to_id, @@ -324,7 +326,7 @@ const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assum /// spam due to quick disconnection/reconnection, updates are not sent until the channel has been /// offline for a full minute. In order to track this, you must call /// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfec. -pub struct ChannelManager<'a> { +pub struct ChannelManager<'a, ChanSigner: ChannelKeys> { default_configuration: UserConfig, genesis_hash: Sha256dHash, fee_estimator: Arc, @@ -339,9 +341,9 @@ pub struct ChannelManager<'a> { secp_ctx: Secp256k1, #[cfg(test)] - pub(super) channel_state: Mutex, + pub(super) channel_state: Mutex>, #[cfg(not(test))] - channel_state: Mutex, + channel_state: Mutex>, our_network_key: SecretKey, pending_events: Mutex>, @@ -350,7 +352,7 @@ pub struct ChannelManager<'a> { /// Taken first everywhere where we are making changes before any other locks. total_consistency_lock: RwLock<()>, - keys_manager: Arc, + keys_manager: Arc>, logger: Arc, } @@ -581,7 +583,7 @@ macro_rules! maybe_break_monitor_err { } } -impl<'a> ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys> ChannelManager<'a, ChanSigner> { /// Constructs a new ChannelManager to hold several channels and route between them. /// /// This is the main "logic hub" for all channel-related actions, and implements @@ -600,7 +602,7 @@ impl<'a> ChannelManager<'a> { /// the ChannelManager as a listener to the BlockNotifier and call the BlockNotifier's /// `block_(dis)connected` methods, which will notify all registered listeners in one /// go. - pub fn new(network: Network, feeest: Arc, monitor: Arc, tx_broadcaster: Arc, logger: Arc,keys_manager: Arc, config: UserConfig, current_blockchain_height: usize) -> Result>, secp256k1::Error> { + pub fn new(network: Network, feeest: Arc, monitor: Arc, tx_broadcaster: Arc, logger: Arc,keys_manager: Arc>, config: UserConfig, current_blockchain_height: usize) -> Result>, secp256k1::Error> { let secp_ctx = Secp256k1::new(); let res = Arc::new(ChannelManager { @@ -818,8 +820,7 @@ impl<'a> ChannelManager<'a> { } } - const ZERO:[u8; 65] = [0; 65]; - fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, MutexGuard) { + fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, MutexGuard>) { macro_rules! return_malformed_err { ($msg: expr, $err_code: expr) => { { @@ -941,7 +942,7 @@ impl<'a> ChannelManager<'a> { } else { let mut new_packet_data = [0; 20*65]; chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]); - chacha.process(&ChannelManager::ZERO[..], &mut new_packet_data[19*65..]); + chacha.process(&SIXTY_FIVE_ZEROS[..], &mut new_packet_data[19*65..]); let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap(); @@ -1038,7 +1039,7 @@ impl<'a> ChannelManager<'a> { /// only fails if the channel does not yet have an assigned short_id /// May be called with channel_state already locked! - fn get_channel_update(&self, chan: &Channel) -> Result { + fn get_channel_update(&self, chan: &Channel) -> Result { let short_channel_id = match chan.get_short_channel_id() { None => return Err(LightningError{err: "Channel not yet established", action: msgs::ErrorAction::IgnoreError}), Some(id) => id, @@ -1267,7 +1268,7 @@ impl<'a> ChannelManager<'a> { } } - fn get_announcement_sigs(&self, chan: &Channel) -> Option { + fn get_announcement_sigs(&self, chan: &Channel) -> Option { if !chan.should_announce() { return None } let (announcement, our_bitcoin_sig) = match chan.get_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone()) { @@ -1561,7 +1562,7 @@ impl<'a> ChannelManager<'a> { /// to fail and take the channel_state lock for each iteration (as we take ownership and may /// drop it). In other words, no assumptions are made that entries in claimable_htlcs point to /// still-available channels. - fn fail_htlc_backwards_internal(&self, mut channel_state_lock: MutexGuard, source: HTLCSource, payment_hash: &PaymentHash, onion_error: HTLCFailReason) { + fn fail_htlc_backwards_internal(&self, mut channel_state_lock: MutexGuard>, source: HTLCSource, payment_hash: &PaymentHash, onion_error: HTLCFailReason) { //TODO: There is a timing attack here where if a node fails an HTLC back to us they can //identify whether we sent it or not based on the (I presume) very different runtime //between the branches here. We should make this async and move it into the forward HTLCs @@ -1689,7 +1690,7 @@ impl<'a> ChannelManager<'a> { true } else { false } } - fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard, source: HTLCSource, payment_preimage: PaymentPreimage) { + fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard>, source: HTLCSource, payment_preimage: PaymentPreimage) { let (their_node_id, err) = loop { match source { HTLCSource::OutboundRoute { .. } => { @@ -2566,7 +2567,7 @@ impl<'a> ChannelManager<'a> { } } -impl<'a> events::MessageSendEventsProvider for ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys> events::MessageSendEventsProvider for ChannelManager<'a, ChanSigner> { fn get_and_clear_pending_msg_events(&self) -> Vec { // TODO: Event release to users and serialization is currently race-y: it's very easy for a // user to serialize a ChannelManager with pending events in it and lose those events on @@ -2591,7 +2592,7 @@ impl<'a> events::MessageSendEventsProvider for ChannelManager<'a> { } } -impl<'a> events::EventsProvider for ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys> events::EventsProvider for ChannelManager<'a, ChanSigner> { fn get_and_clear_pending_events(&self) -> Vec { // TODO: Event release to users and serialization is currently race-y: it's very easy for a // user to serialize a ChannelManager with pending events in it and lose those events on @@ -2616,7 +2617,7 @@ impl<'a> events::EventsProvider for ChannelManager<'a> { } } -impl<'a> ChainListener for ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys> ChainListener for ChannelManager<'a, ChanSigner> { fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) { let header_hash = header.bitcoin_hash(); log_trace!(self, "Block {} at height {} connected with {} txn matched", header_hash, height, txn_matched.len()); @@ -2730,7 +2731,7 @@ impl<'a> ChainListener for ChannelManager<'a> { } } -impl<'a> ChannelMessageHandler for ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<'a, ChanSigner> { //TODO: Handle errors and close channel (or so) fn handle_open_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &msgs::OpenChannel) -> Result<(), LightningError> { let _ = self.total_consistency_lock.read().unwrap(); @@ -3115,7 +3116,7 @@ impl Readable for HTLCForwardInfo { } } -impl<'a> Writeable for ChannelManager<'a> { +impl<'a, ChanSigner: ChannelKeys + Writeable> Writeable for ChannelManager<'a, ChanSigner> { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { let _ = self.total_consistency_lock.write().unwrap(); @@ -3178,10 +3179,10 @@ impl<'a> Writeable for ChannelManager<'a> { /// 5) Move the ChannelMonitors into your local ManyChannelMonitor. /// 6) Disconnect/connect blocks on the ChannelManager. /// 7) Register the new ChannelManager with your ChainWatchInterface. -pub struct ChannelManagerReadArgs<'a, 'b> { +pub struct ChannelManagerReadArgs<'a, 'b, ChanSigner: ChannelKeys> { /// The keys provider which will give us relevant keys. Some keys will be loaded during /// deserialization. - pub keys_manager: Arc, + pub keys_manager: Arc>, /// The fee_estimator for use in the ChannelManager in the future. /// @@ -3218,8 +3219,8 @@ pub struct ChannelManagerReadArgs<'a, 'b> { pub channel_monitors: &'a HashMap, } -impl<'a, 'b, R : ::std::io::Read> ReadableArgs> for (Sha256dHash, ChannelManager<'b>) { - fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, 'b>) -> Result { +impl<'a, 'b, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable> ReadableArgs> for (Sha256dHash, ChannelManager<'b, ChanSigner>) { + fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, 'b, ChanSigner>) -> Result { let _ver: u8 = Readable::read(reader)?; let min_ver: u8 = Readable::read(reader)?; if min_ver > SERIALIZATION_VERSION { @@ -3237,7 +3238,7 @@ impl<'a, 'b, R : ::std::io::Read> ReadableArgs let mut by_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); for _ in 0..channel_count { - let mut channel: Channel = ReadableArgs::read(reader, args.logger.clone())?; + let mut channel: Channel = ReadableArgs::read(reader, args.logger.clone())?; if channel.last_block_connected != last_block_hash { return Err(DecodeError::InvalidValue); } diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 7e11c521c..108bbc137 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -8,6 +8,7 @@ use ln::channelmanager::{ChannelManager,RAACommitmentOrder, PaymentPreimage, Pay use ln::router::{Route, Router}; use ln::msgs; use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler, LocalFeatures}; +use util::enforcing_trait_impls::EnforcingChannelKeys; use util::test_utils; use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; use util::errors::APIError; @@ -60,7 +61,7 @@ pub struct Node<'a, 'b: 'a> { pub tx_broadcaster: Arc, pub chan_monitor: Arc, pub keys_manager: Arc, - pub node: Arc>, + pub node: Arc>, pub router: Router, pub node_seed: [u8; 32], pub network_payment_count: Rc>, diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 3be08a372..4e5d72639 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -4,8 +4,7 @@ use chain::transaction::OutPoint; use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil}; -use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor, KeysManager}; -use chain::keysinterface; +use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor}; use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC}; use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT}; use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY}; @@ -14,6 +13,7 @@ use ln::onion_utils; use ln::router::{Route, RouteHop}; use ln::msgs; use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, LocalFeatures, ErrorAction}; +use util::enforcing_trait_impls::EnforcingChannelKeys; use util::test_utils; use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; use util::errors::APIError; @@ -57,7 +57,7 @@ fn test_insane_channel_opens() { // Instantiate channel parameters where we push the maximum msats given our // funding satoshis let channel_value_sat = 31337; // same as funding satoshis - let channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(channel_value_sat); + let channel_reserve_satoshis = Channel::::get_our_channel_reserve_satoshis(channel_value_sat); let push_msat = (channel_value_sat - channel_reserve_satoshis) * 1000; // Have node0 initiate a channel to node1 with aforementioned parameters @@ -3324,8 +3324,8 @@ fn test_invalid_channel_announcement() { let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap(), is_permanent: false } ); - let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().funding_key); - let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().funding_key); + let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().inner.funding_key); + let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().inner.funding_key); let as_network_key = nodes[0].node.get_our_node_id(); let bs_network_key = nodes[1].node.get_our_node_id(); @@ -3352,8 +3352,8 @@ fn test_invalid_channel_announcement() { macro_rules! sign_msg { ($unsigned_msg: expr) => { let msghash = Message::from_slice(&Sha256dHash::hash(&$unsigned_msg.encode()[..])[..]).unwrap(); - let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().funding_key); - let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().funding_key); + let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().inner.funding_key); + let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().inner.funding_key); let as_node_sig = secp_ctx.sign(&msghash, &nodes[0].keys_manager.get_node_secret()); let bs_node_sig = secp_ctx.sign(&msghash, &nodes[1].keys_manager.get_node_secret()); chan_announcement = msgs::ChannelAnnouncement { @@ -3406,7 +3406,7 @@ fn test_no_txn_manager_serialize_deserialize() { let (_, nodes_0_deserialized) = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor); - <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { default_config: config, keys_manager, fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }), @@ -3470,7 +3470,7 @@ fn test_simple_manager_serialize_deserialize() { let (_, nodes_0_deserialized) = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor); - <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { default_config: UserConfig::default(), keys_manager, fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }), @@ -3530,7 +3530,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut nodes_0_read = &nodes_0_serialized[..]; let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()))); - let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { default_config: UserConfig::default(), keys_manager, fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }), @@ -6067,7 +6067,7 @@ fn test_user_configurable_csv_delay() { let nodes = create_network(2, &cfgs); // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound() - let keys_manager: Arc = Arc::new(KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()), 10, 20)); + let keys_manager: Arc> = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()))); if let Err(error) = Channel::new_outbound(&test_utils::TestFeeEstimator { sat_per_kw: 253 }, &keys_manager, nodes[1].node.get_our_node_id(), 1000000, 1000000, 0, Arc::new(test_utils::TestLogger::new()), &low_our_to_self_config) { match error { APIError::APIMisuseError { err } => { assert_eq!(err, "Configured with an unreasonable our_to_self_delay putting user funds at risks"); }, @@ -6142,8 +6142,8 @@ fn test_data_loss_protect() { let monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone())); let mut channel_monitors = HashMap::new(); channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &chan_monitor); - let node_state_0 = <(Sha256dHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs { - keys_manager: Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger), 42, 21)), + let node_state_0 = <(Sha256dHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs { + keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))), fee_estimator: feeest.clone(), monitor: monitor.clone(), logger: Arc::clone(&logger), diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs new file mode 100644 index 000000000..728caed09 --- /dev/null +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -0,0 +1,29 @@ +use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys}; + +use secp256k1::key::SecretKey; + +/// Enforces some rules on ChannelKeys calls. Eventually we will probably want to expose a variant +/// of this which would essentially be what you'd want to run on a hardware wallet. +pub struct EnforcingChannelKeys { + pub inner: InMemoryChannelKeys, +} + +impl EnforcingChannelKeys { + pub fn new(inner: InMemoryChannelKeys) -> Self { + Self { + inner, + } + } +} +impl ChannelKeys for EnforcingChannelKeys { + fn funding_key(&self) -> &SecretKey { self.inner.funding_key() } + fn revocation_base_key(&self) -> &SecretKey { self.inner.revocation_base_key() } + fn payment_base_key(&self) -> &SecretKey { self.inner.payment_base_key() } + fn delayed_payment_base_key(&self) -> &SecretKey { self.inner.delayed_payment_base_key() } + fn htlc_base_key(&self) -> &SecretKey { self.inner.htlc_base_key() } + fn commitment_seed(&self) -> &[u8; 32] { self.inner.commitment_seed() } +} + +impl_writeable!(EnforcingChannelKeys, 0, { + inner +}); diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index aab77035d..8c94ac5ca 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -23,5 +23,10 @@ pub mod config; #[cfg(test)] pub(crate) mod test_utils; +/// impls of traits that add exra enforcement on the way they're called. Useful for detecting state +/// machine errors and used in fuzz targets and tests. +#[cfg(any(test, feature = "fuzztarget"))] +pub mod enforcing_trait_impls; + #[macro_use] pub(crate) mod fuzz_wrappers; diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 0d5a6917d..6ea1265c3 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -7,6 +7,7 @@ use ln::msgs; use ln::msgs::LocalFeatures; use ln::msgs::{LightningError}; use ln::channelmonitor::HTLCUpdate; +use util::enforcing_trait_impls::EnforcingChannelKeys; use util::events; use util::logger::{Logger, Level, Record}; use util::ser::{ReadableArgs, Writer}; @@ -221,10 +222,12 @@ pub struct TestKeysInterface { } impl keysinterface::KeysInterface for TestKeysInterface { + type ChanKeySigner = EnforcingChannelKeys; + fn get_node_secret(&self) -> SecretKey { self.backing.get_node_secret() } fn get_destination_script(&self) -> Script { self.backing.get_destination_script() } fn get_shutdown_pubkey(&self) -> PublicKey { self.backing.get_shutdown_pubkey() } - fn get_channel_keys(&self, inbound: bool) -> keysinterface::ChannelKeys { self.backing.get_channel_keys(inbound) } + fn get_channel_keys(&self, inbound: bool) -> EnforcingChannelKeys { EnforcingChannelKeys::new(self.backing.get_channel_keys(inbound)) } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { match *self.override_session_priv.lock().unwrap() {