From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Mon, 28 Aug 2023 20:43:08 +0000 (+0000) Subject: Merge pull request #2536 from waterson/test-channel-signer X-Git-Tag: v0.0.117-alpha1~35 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=5626e21bea3d5dbd78740f8090910f72456022c9;hp=2c4f82478e83ccfc8948b24d7cb14ef9913e011f;p=rust-lightning Merge pull request #2536 from waterson/test-channel-signer Rename EnforcingSigner to TestChannelSigner --- diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 296b3a03e..83470bf8b 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -46,7 +46,7 @@ use lightning::ln::script::ShutdownScript; use lightning::ln::functional_test_utils::*; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; -use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; +use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState}; use lightning::util::errors::APIError; use lightning::util::logger::Logger; use lightning::util::config::UserConfig; @@ -118,7 +118,7 @@ struct TestChainMonitor { pub logger: Arc, pub keys: Arc, pub persister: Arc, - pub chain_monitor: Arc, Arc, Arc, Arc, Arc>>, + pub chain_monitor: Arc, Arc, Arc, Arc, Arc>>, // If we reload a node with an old copy of ChannelMonitors, the ChannelManager deserialization // logic will automatically force-close our channels for us (as we don't have an up-to-date // monitor implying we are not able to punish misbehaving counterparties). Because this test @@ -139,8 +139,8 @@ impl TestChainMonitor { } } } -impl chain::Watch for TestChainMonitor { - fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> chain::ChannelMonitorUpdateStatus { +impl chain::Watch for TestChainMonitor { + fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> chain::ChannelMonitorUpdateStatus { let mut ser = VecWriter(Vec::new()); monitor.write(&mut ser).unwrap(); if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) { @@ -156,7 +156,7 @@ impl chain::Watch for TestChainMonitor { hash_map::Entry::Occupied(entry) => entry, hash_map::Entry::Vacant(_) => panic!("Didn't have monitor on update call"), }; - let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: + let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: read(&mut Cursor::new(&map_entry.get().1), (&*self.keys, &*self.keys)).unwrap().1; deserialized_monitor.update_monitor(update, &&TestBroadcaster{}, &FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap(); let mut ser = VecWriter(Vec::new()); @@ -234,7 +234,7 @@ impl NodeSigner for KeyProvider { } impl SignerProvider for KeyProvider { - type Signer = EnforcingSigner; + type Signer = TestChannelSigner; fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed) as u8; @@ -257,7 +257,7 @@ impl SignerProvider for KeyProvider { channel_keys_id, ); let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed); - EnforcingSigner::new_with_revoked(keys, revoked_commitment, false) + TestChannelSigner::new_with_revoked(keys, revoked_commitment, false) } fn read_chan_signer(&self, buffer: &[u8]) -> Result { @@ -266,7 +266,7 @@ impl SignerProvider for KeyProvider { let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); - Ok(EnforcingSigner { + Ok(TestChannelSigner { inner, state, disable_revocation_policy_check: false, @@ -477,7 +477,7 @@ pub fn do_test(data: &[u8], underlying_out: Out) { let mut monitors = HashMap::new(); let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap(); for (outpoint, (update_id, monitor_ser)) in old_monitors.drain() { - monitors.insert(outpoint, <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), (&*$keys_manager, &*$keys_manager)).expect("Failed to read monitor").1); + monitors.insert(outpoint, <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), (&*$keys_manager, &*$keys_manager)).expect("Failed to read monitor").1); chain_monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser)); } let mut monitor_refs = HashMap::new(); diff --git a/fuzz/src/chanmon_deser.rs b/fuzz/src/chanmon_deser.rs index 61744ace7..8d425357c 100644 --- a/fuzz/src/chanmon_deser.rs +++ b/fuzz/src/chanmon_deser.rs @@ -4,7 +4,7 @@ use bitcoin::hash_types::BlockHash; use lightning::chain::channelmonitor; -use lightning::util::enforcing_trait_impls::EnforcingSigner; +use lightning::util::test_channel_signer::TestChannelSigner; use lightning::util::ser::{ReadableArgs, Writer, Writeable}; use lightning::util::test_utils::OnlyReadsKeysInterface; @@ -22,10 +22,10 @@ impl Writer for VecWriter { #[inline] pub fn do_test(data: &[u8], _out: Out) { - if let Ok((latest_block_hash, monitor)) = <(BlockHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})) { + if let Ok((latest_block_hash, monitor)) = <(BlockHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})) { let mut w = VecWriter(Vec::new()); monitor.write(&mut w).unwrap(); - let deserialized_copy = <(BlockHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})).unwrap(); + let deserialized_copy = <(BlockHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})).unwrap(); assert!(latest_block_hash == deserialized_copy.0); assert!(monitor == deserialized_copy.1); } diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 67ff2a587..a11e5c813 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -47,7 +47,7 @@ use lightning::routing::utxo::UtxoLookup; use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router}; use lightning::util::config::{UserConfig, MaxDustHTLCExposure}; use lightning::util::errors::APIError; -use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; +use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState}; use lightning::util::logger::Logger; use lightning::util::ser::{ReadableArgs, Writeable}; @@ -180,13 +180,13 @@ impl<'a> std::hash::Hash for Peer<'a> { } type ChannelMan<'a> = ChannelManager< - Arc, Arc, Arc, Arc, Arc>>, + Arc, Arc, Arc, Arc, Arc>>, Arc, Arc, Arc, Arc, Arc, &'a FuzzRouter, Arc>; type PeerMan<'a> = PeerManager, Arc>, Arc>>, Arc, Arc>>, IgnoringMessageHandler, Arc, IgnoringMessageHandler, Arc>; struct MoneyLossDetector<'a> { manager: Arc>, - monitor: Arc, Arc, Arc, Arc, Arc>>, + monitor: Arc, Arc, Arc, Arc, Arc>>, handler: PeerMan<'a>, peers: &'a RefCell<[bool; 256]>, @@ -200,7 +200,7 @@ struct MoneyLossDetector<'a> { impl<'a> MoneyLossDetector<'a> { pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc>, - monitor: Arc, Arc, Arc, Arc, Arc>>, + monitor: Arc, Arc, Arc, Arc, Arc>>, handler: PeerMan<'a>) -> Self { MoneyLossDetector { manager, @@ -339,7 +339,7 @@ impl NodeSigner for KeyProvider { } impl SignerProvider for KeyProvider { - type Signer = EnforcingSigner; + type Signer = TestChannelSigner; fn generate_channel_keys_id(&self, inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; @@ -351,7 +351,7 @@ impl SignerProvider for KeyProvider { let secp_ctx = Secp256k1::signing_only(); let ctr = channel_keys_id[0]; let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone(); - EnforcingSigner::new_with_revoked(if inbound { + TestChannelSigner::new_with_revoked(if inbound { InMemorySigner::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(), @@ -380,11 +380,11 @@ impl SignerProvider for KeyProvider { }, state, false) } - fn read_chan_signer(&self, mut data: &[u8]) -> Result { + fn read_chan_signer(&self, mut data: &[u8]) -> Result { let inner: InMemorySigner = ReadableArgs::read(&mut data, self)?; let state = Arc::new(Mutex::new(EnforcementState::new())); - Ok(EnforcingSigner::new_with_revoked( + Ok(TestChannelSigner::new_with_revoked( inner, state, false diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index 0ffc090ea..d2e35cd45 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -11,7 +11,7 @@ use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler}; use lightning::ln::script::ShutdownScript; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; -use lightning::util::enforcing_trait_impls::EnforcingSigner; +use lightning::util::test_channel_signer::TestChannelSigner; use lightning::util::logger::Logger; use lightning::util::ser::{Readable, Writeable, Writer}; use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessagePath, OnionMessenger}; @@ -174,7 +174,7 @@ impl NodeSigner for KeyProvider { } impl SignerProvider for KeyProvider { - type Signer = EnforcingSigner; + type Signer = TestChannelSigner; fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!() } @@ -182,7 +182,7 @@ impl SignerProvider for KeyProvider { unreachable!() } - fn read_chan_signer(&self, _data: &[u8]) -> Result { unreachable!() } + fn read_chan_signer(&self, _data: &[u8]) -> Result { unreachable!() } fn get_destination_script(&self) -> Result { unreachable!() } diff --git a/fuzz/src/utils/test_persister.rs b/fuzz/src/utils/test_persister.rs index e3635297a..89de25aa5 100644 --- a/fuzz/src/utils/test_persister.rs +++ b/fuzz/src/utils/test_persister.rs @@ -2,19 +2,19 @@ use lightning::chain; use lightning::chain::{chainmonitor, channelmonitor}; use lightning::chain::chainmonitor::MonitorUpdateId; use lightning::chain::transaction::OutPoint; -use lightning::util::enforcing_trait_impls::EnforcingSigner; +use lightning::util::test_channel_signer::TestChannelSigner; use std::sync::Mutex; pub struct TestPersister { pub update_ret: Mutex, } -impl chainmonitor::Persist for TestPersister { - fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { +impl chainmonitor::Persist for TestPersister { + fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { self.update_ret.lock().unwrap().clone() } - fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { + fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { self.update_ret.lock().unwrap().clone() } } diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 8e52af093..a9a5790b0 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -23,7 +23,7 @@ use crate::ln::channelmanager::{RAACommitmentOrder, PaymentSendFailure, PaymentI use crate::ln::channel::AnnouncementSigsState; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler}; -use crate::util::enforcing_trait_impls::EnforcingSigner; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::errors::APIError; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils::TestBroadcaster; @@ -111,7 +111,7 @@ fn test_monitor_and_persister_update_fail() { let chain_mon = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).unwrap(); - let new_monitor = <(BlockHash, ChannelMonitor)>::read( + let new_monitor = <(BlockHash, ChannelMonitor)>::read( &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; assert!(new_monitor == *monitor); new_monitor diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 80b910159..b8c2e0859 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -23,7 +23,7 @@ use crate::routing::router::{self, PaymentParameters, Route}; use crate::ln::features::InitFeatures; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; -use crate::util::enforcing_trait_impls::EnforcingSigner; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::scid_utils; use crate::util::test_utils; use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface}; @@ -520,7 +520,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { for outpoint in self.chain_monitor.chain_monitor.list_monitors() { let mut w = test_utils::TestVecWriter(Vec::new()); self.chain_monitor.chain_monitor.get_monitor(outpoint).unwrap().write(&mut w).unwrap(); - let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor)>::read( + let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor)>::read( &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap(); deserialized_monitors.push(deserialized_monitor); } @@ -952,7 +952,7 @@ pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: User let mut monitors_read = Vec::with_capacity(monitors_encoded.len()); for encoded in monitors_encoded { let mut monitor_read = &encoded[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)> + let (_, monitor) = <(BlockHash, ChannelMonitor)> ::read(&mut monitor_read, (node.keys_manager, node.keys_manager)).unwrap(); assert!(monitor_read.is_empty()); monitors_read.push(monitor); @@ -2646,7 +2646,7 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec(node_count: usize, chanmon_cfgs: &'a Vec, persisters: Vec<&'a impl Persist>) -> Vec> { +pub fn create_node_cfgs_with_persisters<'a>(node_count: usize, chanmon_cfgs: &'a Vec, persisters: Vec<&'a impl Persist>) -> Vec> { let mut nodes = Vec::new(); for i in 0..node_count { diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 506cb73d9..d3401e5f0 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -30,7 +30,7 @@ use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction}; -use crate::util::enforcing_trait_impls::EnforcingSigner; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils::{self, WatchtowerPersister}; use crate::util::errors::APIError; use crate::util::ser::{Writeable, ReadableArgs}; @@ -696,7 +696,7 @@ fn test_update_fee_that_funder_cannot_afford() { const INITIAL_COMMITMENT_NUMBER: u64 = 281474976710654; - // Get the EnforcingSigner for each channel, which will be used to (1) get the keys + // Get the TestChannelSigner for each channel, which will be used to (1) get the keys // needed to sign the new commitment tx and (2) sign the new commitment tx. let (local_revocation_basepoint, local_htlc_basepoint, local_funding) = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); @@ -1409,7 +1409,7 @@ fn test_fee_spike_violation_fails_htlc() { const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; - // Get the EnforcingSigner for each channel, which will be used to (1) get the keys + // Get the TestChannelSigner for each channel, which will be used to (1) get the keys // needed to sign the new commitment tx and (2) sign the new commitment tx. let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point, local_funding) = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); @@ -7639,7 +7639,7 @@ fn test_counterparty_raa_skip_no_crash() { // commitment transaction, we would have happily carried on and provided them the next // commitment transaction based on one RAA forward. This would probably eventually have led to // channel closure, but it would not have resulted in funds loss. Still, our - // EnforcingSigner would have panicked as it doesn't like jumps into the future. Here, we + // TestChannelSigner would have panicked as it doesn't like jumps into the future. Here, we // check simply that the channel is closed in response to such an RAA, but don't check whether // we decide to punish our counterparty for revoking their funds (as we don't currently // implement that). @@ -8350,7 +8350,7 @@ fn test_update_err_monitor_lockdown() { let watchtower = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( + let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; assert!(new_monitor == *monitor); new_monitor @@ -8420,7 +8420,7 @@ fn test_concurrent_monitor_claim() { let watchtower_alice = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( + let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; assert!(new_monitor == *monitor); new_monitor @@ -8451,7 +8451,7 @@ fn test_concurrent_monitor_claim() { let watchtower_bob = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( + let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; assert!(new_monitor == *monitor); new_monitor diff --git a/lightning/src/ln/reload_tests.rs b/lightning/src/ln/reload_tests.rs index c452630e1..eda517e08 100644 --- a/lightning/src/ln/reload_tests.rs +++ b/lightning/src/ln/reload_tests.rs @@ -18,7 +18,7 @@ use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, Mes use crate::ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RecipientOnionFields}; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction}; -use crate::util::enforcing_trait_impls::EnforcingSigner; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils; use crate::util::errors::APIError; use crate::util::ser::{Writeable, ReadableArgs}; @@ -399,7 +399,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_stale_monitors = Vec::new(); for serialized in node_0_stale_monitors_serialized.iter() { let mut read = &serialized[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); + let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); assert!(read.is_empty()); node_0_stale_monitors.push(monitor); } @@ -407,7 +407,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_monitors = Vec::new(); for serialized in node_0_monitors_serialized.iter() { let mut read = &serialized[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); + let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); assert!(read.is_empty()); node_0_monitors.push(monitor); } diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs deleted file mode 100644 index df0f13bc3..000000000 --- a/lightning/src/util/enforcing_trait_impls.rs +++ /dev/null @@ -1,297 +0,0 @@ -// This file is Copyright its original authors, visible in version control -// history. -// -// This file is licensed under the Apache License, Version 2.0 or the MIT license -// , at your option. -// You may not use this file except in accordance with one or both of these -// licenses. - -use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS}; -use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction}; -use crate::ln::{chan_utils, msgs, PaymentPreimage}; -use crate::sign::{WriteableEcdsaChannelSigner, InMemorySigner, ChannelSigner, EcdsaChannelSigner}; - -use crate::prelude::*; -use core::cmp; -use crate::sync::{Mutex, Arc}; -#[cfg(test)] use crate::sync::MutexGuard; - -use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType}; -use bitcoin::util::sighash; - -use bitcoin::secp256k1; -use bitcoin::secp256k1::{SecretKey, PublicKey}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; -use crate::events::bump_transaction::HTLCDescriptor; -use crate::util::ser::{Writeable, Writer}; -use crate::io::Error; -use crate::ln::features::ChannelTypeFeatures; - -/// Initial value for revoked commitment downward counter -pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48; - -/// An implementation of Sign that enforces some policy checks. The current checks -/// are an incomplete set. They include: -/// -/// - When signing, the holder transaction has not been revoked -/// - When revoking, the holder transaction has not been signed -/// - The holder commitment number is monotonic and without gaps -/// - The revoked holder commitment number is monotonic and without gaps -/// - There is at least one unrevoked holder transaction at all times -/// - The counterparty commitment number is monotonic and without gaps -/// - The pre-derived keys and pre-built transaction in CommitmentTransaction were correctly built -/// -/// 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. -/// -/// Note that counterparty signatures on the holder transaction are not checked, but it should -/// be in a complete implementation. -/// -/// Note that before we do so we should ensure its serialization format has backwards- and -/// forwards-compatibility prefix/suffixes! -#[derive(Clone)] -pub struct EnforcingSigner { - pub inner: InMemorySigner, - /// Channel state used for policy enforcement - pub state: Arc>, - pub disable_revocation_policy_check: bool, -} - -impl PartialEq for EnforcingSigner { - fn eq(&self, o: &Self) -> bool { - Arc::ptr_eq(&self.state, &o.state) - } -} - -impl EnforcingSigner { - /// Construct an EnforcingSigner - pub fn new(inner: InMemorySigner) -> Self { - let state = Arc::new(Mutex::new(EnforcementState::new())); - Self { - inner, - state, - disable_revocation_policy_check: false - } - } - - /// Construct an EnforcingSigner with externally managed storage - /// - /// Since there are multiple copies of this struct for each channel, some coordination is needed - /// so that all copies are aware of enforcement state. A pointer to this state is provided - /// here, usually by an implementation of KeysInterface. - pub fn new_with_revoked(inner: InMemorySigner, state: Arc>, disable_revocation_policy_check: bool) -> Self { - Self { - inner, - state, - disable_revocation_policy_check - } - } - - pub fn channel_type_features(&self) -> &ChannelTypeFeatures { self.inner.channel_type_features() } - - #[cfg(test)] - pub fn get_enforcement_state(&self) -> MutexGuard { - self.state.lock().unwrap() - } -} - -impl ChannelSigner for EnforcingSigner { - fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { - self.inner.get_per_commitment_point(idx, secp_ctx) - } - - fn release_commitment_secret(&self, idx: u64) -> [u8; 32] { - { - let mut state = self.state.lock().unwrap(); - assert!(idx == state.last_holder_revoked_commitment || idx == state.last_holder_revoked_commitment - 1, "can only revoke the current or next unrevoked commitment - trying {}, last revoked {}", idx, state.last_holder_revoked_commitment); - assert!(idx > state.last_holder_commitment, "cannot revoke the last holder commitment - attempted to revoke {} last commitment {}", idx, state.last_holder_commitment); - state.last_holder_revoked_commitment = idx; - } - self.inner.release_commitment_secret(idx) - } - - fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _preimages: Vec) -> Result<(), ()> { - let mut state = self.state.lock().unwrap(); - let idx = holder_tx.commitment_number(); - assert!(idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, "expecting to validate the current or next holder commitment - trying {}, current {}", idx, state.last_holder_commitment); - state.last_holder_commitment = idx; - Ok(()) - } - - fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() } - - fn channel_keys_id(&self) -> [u8; 32] { self.inner.channel_keys_id() } - - fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { - self.inner.provide_channel_parameters(channel_parameters) - } -} - -impl EcdsaChannelSigner for EnforcingSigner { - fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { - self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx); - - { - let mut state = self.state.lock().unwrap(); - let actual_commitment_number = commitment_tx.commitment_number(); - let last_commitment_number = state.last_counterparty_commitment; - // These commitment numbers are backwards counting. We expect either the same as the previously encountered, - // or the next one. - assert!(last_commitment_number == actual_commitment_number || last_commitment_number - 1 == actual_commitment_number, "{} doesn't come after {}", actual_commitment_number, last_commitment_number); - // Ensure that the counterparty doesn't get more than two broadcastable commitments - - // the last and the one we are trying to sign - assert!(actual_commitment_number >= state.last_counterparty_revoked_commitment - 2, "cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}", actual_commitment_number, state.last_counterparty_revoked_commitment); - state.last_counterparty_commitment = cmp::min(last_commitment_number, actual_commitment_number) - } - - Ok(self.inner.sign_counterparty_commitment(commitment_tx, preimages, secp_ctx).unwrap()) - } - - fn validate_counterparty_revocation(&self, idx: u64, _secret: &SecretKey) -> Result<(), ()> { - let mut state = self.state.lock().unwrap(); - assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment); - state.last_counterparty_revoked_commitment = idx; - Ok(()) - } - - fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { - let trusted_tx = self.verify_holder_commitment_tx(commitment_tx, secp_ctx); - let commitment_txid = trusted_tx.txid(); - let holder_csv = self.inner.counterparty_selected_contest_delay(); - - let state = self.state.lock().unwrap(); - let commitment_number = trusted_tx.commitment_number(); - if state.last_holder_revoked_commitment - 1 != commitment_number && state.last_holder_revoked_commitment - 2 != commitment_number { - if !self.disable_revocation_policy_check { - panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", - state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0]) - } - } - - for (this_htlc, sig) in trusted_tx.htlcs().iter().zip(&commitment_tx.counterparty_htlc_sigs) { - assert!(this_htlc.transaction_output_index.is_some()); - let keys = trusted_tx.keys(); - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, trusted_tx.feerate_per_kw(), holder_csv, &this_htlc, self.channel_type_features(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key); - - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&this_htlc, self.channel_type_features(), &keys); - - let sighash_type = if self.channel_type_features().supports_anchors_zero_fee_htlc_tx() { - EcdsaSighashType::SinglePlusAnyoneCanPay - } else { - EcdsaSighashType::All - }; - let sighash = hash_to_message!( - &sighash::SighashCache::new(&htlc_tx).segwit_signature_hash( - 0, &htlc_redeemscript, this_htlc.amount_msat / 1000, sighash_type, - ).unwrap()[..] - ); - secp_ctx.verify_ecdsa(&sighash, sig, &keys.countersignatory_htlc_key).unwrap(); - } - - Ok(self.inner.sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap()) - } - - #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] - fn unsafe_sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { - Ok(self.inner.unsafe_sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap()) - } - - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { - Ok(self.inner.sign_justice_revoked_output(justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap()) - } - - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap()) - } - - fn sign_holder_htlc_transaction( - &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, - secp_ctx: &Secp256k1 - ) -> Result { - assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input()); - assert_eq!(htlc_tx.output[input], htlc_descriptor.tx_output(secp_ctx)); - Ok(self.inner.sign_holder_htlc_transaction(htlc_tx, input, htlc_descriptor, secp_ctx).unwrap()) - } - - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap()) - } - - fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { - closing_tx.verify(self.inner.funding_outpoint().into_bitcoin_outpoint()) - .expect("derived different closing transaction"); - Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap()) - } - - fn sign_holder_anchor_input( - &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, - ) -> Result { - debug_assert!(MIN_CHAN_DUST_LIMIT_SATOSHIS > ANCHOR_OUTPUT_VALUE_SATOSHI); - // As long as our minimum dust limit is enforced and is greater than our anchor output - // value, an anchor output can only have an index within [0, 1]. - assert!(anchor_tx.input[input].previous_output.vout == 0 || anchor_tx.input[input].previous_output.vout == 1); - self.inner.sign_holder_anchor_input(anchor_tx, input, secp_ctx) - } - - fn sign_channel_announcement_with_funding_key( - &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 - ) -> Result { - self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx) - } -} - -impl WriteableEcdsaChannelSigner for EnforcingSigner {} - -impl Writeable for EnforcingSigner { - fn write(&self, writer: &mut W) -> Result<(), Error> { - // EnforcingSigner has two fields - `inner` ([`InMemorySigner`]) and `state` - // ([`EnforcementState`]). `inner` is serialized here and deserialized by - // [`SignerProvider::read_chan_signer`]. `state` is managed by [`SignerProvider`] - // and will be serialized as needed by the implementation of that trait. - self.inner.write(writer)?; - Ok(()) - } -} - -impl EnforcingSigner { - fn verify_counterparty_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { - commitment_tx.verify(&self.inner.get_channel_parameters().as_counterparty_broadcastable(), - self.inner.counterparty_pubkeys(), self.inner.pubkeys(), secp_ctx) - .expect("derived different per-tx keys or built transaction") - } - - fn verify_holder_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { - commitment_tx.verify(&self.inner.get_channel_parameters().as_holder_broadcastable(), - self.inner.pubkeys(), self.inner.counterparty_pubkeys(), secp_ctx) - .expect("derived different per-tx keys or built transaction") - } -} - -/// The state used by [`EnforcingSigner`] in order to enforce policy checks -/// -/// This structure is maintained by KeysInterface since we may have multiple copies of -/// the signer and they must coordinate their state. -#[derive(Clone)] -pub struct EnforcementState { - /// The last counterparty commitment number we signed, backwards counting - pub last_counterparty_commitment: u64, - /// The last counterparty commitment they revoked, backwards counting - pub last_counterparty_revoked_commitment: u64, - /// The last holder commitment number we revoked, backwards counting - pub last_holder_revoked_commitment: u64, - /// The last validated holder commitment number, backwards counting - pub last_holder_commitment: u64, -} - -impl EnforcementState { - /// Enforcement state for a new channel - pub fn new() -> Self { - EnforcementState { - last_counterparty_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, - last_counterparty_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, - last_holder_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, - last_holder_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, - } - } -} diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index dd9d2744e..cc1b5f581 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -56,5 +56,5 @@ pub 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 = "_test_utils"))] -pub mod enforcing_trait_impls; +pub mod test_channel_signer; diff --git a/lightning/src/util/test_channel_signer.rs b/lightning/src/util/test_channel_signer.rs new file mode 100644 index 000000000..2fb1c494f --- /dev/null +++ b/lightning/src/util/test_channel_signer.rs @@ -0,0 +1,297 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS}; +use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction}; +use crate::ln::{chan_utils, msgs, PaymentPreimage}; +use crate::sign::{WriteableEcdsaChannelSigner, InMemorySigner, ChannelSigner, EcdsaChannelSigner}; + +use crate::prelude::*; +use core::cmp; +use crate::sync::{Mutex, Arc}; +#[cfg(test)] use crate::sync::MutexGuard; + +use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType}; +use bitcoin::util::sighash; + +use bitcoin::secp256k1; +use bitcoin::secp256k1::{SecretKey, PublicKey}; +use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; +use crate::events::bump_transaction::HTLCDescriptor; +use crate::util::ser::{Writeable, Writer}; +use crate::io::Error; +use crate::ln::features::ChannelTypeFeatures; + +/// Initial value for revoked commitment downward counter +pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48; + +/// An implementation of Sign that enforces some policy checks. The current checks +/// are an incomplete set. They include: +/// +/// - When signing, the holder transaction has not been revoked +/// - When revoking, the holder transaction has not been signed +/// - The holder commitment number is monotonic and without gaps +/// - The revoked holder commitment number is monotonic and without gaps +/// - There is at least one unrevoked holder transaction at all times +/// - The counterparty commitment number is monotonic and without gaps +/// - The pre-derived keys and pre-built transaction in CommitmentTransaction were correctly built +/// +/// 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. +/// +/// Note that counterparty signatures on the holder transaction are not checked, but it should +/// be in a complete implementation. +/// +/// Note that before we do so we should ensure its serialization format has backwards- and +/// forwards-compatibility prefix/suffixes! +#[derive(Clone)] +pub struct TestChannelSigner { + pub inner: InMemorySigner, + /// Channel state used for policy enforcement + pub state: Arc>, + pub disable_revocation_policy_check: bool, +} + +impl PartialEq for TestChannelSigner { + fn eq(&self, o: &Self) -> bool { + Arc::ptr_eq(&self.state, &o.state) + } +} + +impl TestChannelSigner { + /// Construct an TestChannelSigner + pub fn new(inner: InMemorySigner) -> Self { + let state = Arc::new(Mutex::new(EnforcementState::new())); + Self { + inner, + state, + disable_revocation_policy_check: false + } + } + + /// Construct an TestChannelSigner with externally managed storage + /// + /// Since there are multiple copies of this struct for each channel, some coordination is needed + /// so that all copies are aware of enforcement state. A pointer to this state is provided + /// here, usually by an implementation of KeysInterface. + pub fn new_with_revoked(inner: InMemorySigner, state: Arc>, disable_revocation_policy_check: bool) -> Self { + Self { + inner, + state, + disable_revocation_policy_check + } + } + + pub fn channel_type_features(&self) -> &ChannelTypeFeatures { self.inner.channel_type_features() } + + #[cfg(test)] + pub fn get_enforcement_state(&self) -> MutexGuard { + self.state.lock().unwrap() + } +} + +impl ChannelSigner for TestChannelSigner { + fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { + self.inner.get_per_commitment_point(idx, secp_ctx) + } + + fn release_commitment_secret(&self, idx: u64) -> [u8; 32] { + { + let mut state = self.state.lock().unwrap(); + assert!(idx == state.last_holder_revoked_commitment || idx == state.last_holder_revoked_commitment - 1, "can only revoke the current or next unrevoked commitment - trying {}, last revoked {}", idx, state.last_holder_revoked_commitment); + assert!(idx > state.last_holder_commitment, "cannot revoke the last holder commitment - attempted to revoke {} last commitment {}", idx, state.last_holder_commitment); + state.last_holder_revoked_commitment = idx; + } + self.inner.release_commitment_secret(idx) + } + + fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _preimages: Vec) -> Result<(), ()> { + let mut state = self.state.lock().unwrap(); + let idx = holder_tx.commitment_number(); + assert!(idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, "expecting to validate the current or next holder commitment - trying {}, current {}", idx, state.last_holder_commitment); + state.last_holder_commitment = idx; + Ok(()) + } + + fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() } + + fn channel_keys_id(&self) -> [u8; 32] { self.inner.channel_keys_id() } + + fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { + self.inner.provide_channel_parameters(channel_parameters) + } +} + +impl EcdsaChannelSigner for TestChannelSigner { + fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx); + + { + let mut state = self.state.lock().unwrap(); + let actual_commitment_number = commitment_tx.commitment_number(); + let last_commitment_number = state.last_counterparty_commitment; + // These commitment numbers are backwards counting. We expect either the same as the previously encountered, + // or the next one. + assert!(last_commitment_number == actual_commitment_number || last_commitment_number - 1 == actual_commitment_number, "{} doesn't come after {}", actual_commitment_number, last_commitment_number); + // Ensure that the counterparty doesn't get more than two broadcastable commitments - + // the last and the one we are trying to sign + assert!(actual_commitment_number >= state.last_counterparty_revoked_commitment - 2, "cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}", actual_commitment_number, state.last_counterparty_revoked_commitment); + state.last_counterparty_commitment = cmp::min(last_commitment_number, actual_commitment_number) + } + + Ok(self.inner.sign_counterparty_commitment(commitment_tx, preimages, secp_ctx).unwrap()) + } + + fn validate_counterparty_revocation(&self, idx: u64, _secret: &SecretKey) -> Result<(), ()> { + let mut state = self.state.lock().unwrap(); + assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment); + state.last_counterparty_revoked_commitment = idx; + Ok(()) + } + + fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + let trusted_tx = self.verify_holder_commitment_tx(commitment_tx, secp_ctx); + let commitment_txid = trusted_tx.txid(); + let holder_csv = self.inner.counterparty_selected_contest_delay(); + + let state = self.state.lock().unwrap(); + let commitment_number = trusted_tx.commitment_number(); + if state.last_holder_revoked_commitment - 1 != commitment_number && state.last_holder_revoked_commitment - 2 != commitment_number { + if !self.disable_revocation_policy_check { + panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", + state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0]) + } + } + + for (this_htlc, sig) in trusted_tx.htlcs().iter().zip(&commitment_tx.counterparty_htlc_sigs) { + assert!(this_htlc.transaction_output_index.is_some()); + let keys = trusted_tx.keys(); + let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, trusted_tx.feerate_per_kw(), holder_csv, &this_htlc, self.channel_type_features(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + + let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&this_htlc, self.channel_type_features(), &keys); + + let sighash_type = if self.channel_type_features().supports_anchors_zero_fee_htlc_tx() { + EcdsaSighashType::SinglePlusAnyoneCanPay + } else { + EcdsaSighashType::All + }; + let sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx).segwit_signature_hash( + 0, &htlc_redeemscript, this_htlc.amount_msat / 1000, sighash_type, + ).unwrap()[..] + ); + secp_ctx.verify_ecdsa(&sighash, sig, &keys.countersignatory_htlc_key).unwrap(); + } + + Ok(self.inner.sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap()) + } + + #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] + fn unsafe_sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + Ok(self.inner.unsafe_sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap()) + } + + fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { + Ok(self.inner.sign_justice_revoked_output(justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap()) + } + + fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap()) + } + + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1 + ) -> Result { + assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input()); + assert_eq!(htlc_tx.output[input], htlc_descriptor.tx_output(secp_ctx)); + Ok(self.inner.sign_holder_htlc_transaction(htlc_tx, input, htlc_descriptor, secp_ctx).unwrap()) + } + + fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap()) + } + + fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { + closing_tx.verify(self.inner.funding_outpoint().into_bitcoin_outpoint()) + .expect("derived different closing transaction"); + Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap()) + } + + fn sign_holder_anchor_input( + &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, + ) -> Result { + debug_assert!(MIN_CHAN_DUST_LIMIT_SATOSHIS > ANCHOR_OUTPUT_VALUE_SATOSHI); + // As long as our minimum dust limit is enforced and is greater than our anchor output + // value, an anchor output can only have an index within [0, 1]. + assert!(anchor_tx.input[input].previous_output.vout == 0 || anchor_tx.input[input].previous_output.vout == 1); + self.inner.sign_holder_anchor_input(anchor_tx, input, secp_ctx) + } + + fn sign_channel_announcement_with_funding_key( + &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + ) -> Result { + self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx) + } +} + +impl WriteableEcdsaChannelSigner for TestChannelSigner {} + +impl Writeable for TestChannelSigner { + fn write(&self, writer: &mut W) -> Result<(), Error> { + // TestChannelSigner has two fields - `inner` ([`InMemorySigner`]) and `state` + // ([`EnforcementState`]). `inner` is serialized here and deserialized by + // [`SignerProvider::read_chan_signer`]. `state` is managed by [`SignerProvider`] + // and will be serialized as needed by the implementation of that trait. + self.inner.write(writer)?; + Ok(()) + } +} + +impl TestChannelSigner { + fn verify_counterparty_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { + commitment_tx.verify(&self.inner.get_channel_parameters().as_counterparty_broadcastable(), + self.inner.counterparty_pubkeys(), self.inner.pubkeys(), secp_ctx) + .expect("derived different per-tx keys or built transaction") + } + + fn verify_holder_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { + commitment_tx.verify(&self.inner.get_channel_parameters().as_holder_broadcastable(), + self.inner.pubkeys(), self.inner.counterparty_pubkeys(), secp_ctx) + .expect("derived different per-tx keys or built transaction") + } +} + +/// The state used by [`TestChannelSigner`] in order to enforce policy checks +/// +/// This structure is maintained by KeysInterface since we may have multiple copies of +/// the signer and they must coordinate their state. +#[derive(Clone)] +pub struct EnforcementState { + /// The last counterparty commitment number we signed, backwards counting + pub last_counterparty_commitment: u64, + /// The last counterparty commitment they revoked, backwards counting + pub last_counterparty_revoked_commitment: u64, + /// The last holder commitment number we revoked, backwards counting + pub last_holder_revoked_commitment: u64, + /// The last validated holder commitment number, backwards counting + pub last_holder_commitment: u64, +} + +impl EnforcementState { + /// Enforcement state for a new channel + pub fn new() -> Self { + EnforcementState { + last_counterparty_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, + last_counterparty_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, + last_holder_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, + last_holder_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER, + } + } +} diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 8cd95f62a..7a9ce0691 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -35,7 +35,7 @@ use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParame use crate::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp}; use crate::sync::RwLock; use crate::util::config::UserConfig; -use crate::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; +use crate::util::test_channel_signer::{TestChannelSigner, EnforcementState}; use crate::util::logger::{Logger, Level, Record}; use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable}; @@ -175,7 +175,7 @@ impl EntropySource for OnlyReadsKeysInterface { fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }} impl SignerProvider for OnlyReadsKeysInterface { - type Signer = EnforcingSigner; + type Signer = TestChannelSigner; fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!(); } @@ -185,7 +185,7 @@ impl SignerProvider for OnlyReadsKeysInterface { let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = Arc::new(Mutex::new(EnforcementState::new())); - Ok(EnforcingSigner::new_with_revoked( + Ok(TestChannelSigner::new_with_revoked( inner, state, false @@ -197,10 +197,10 @@ impl SignerProvider for OnlyReadsKeysInterface { } pub struct TestChainMonitor<'a> { - pub added_monitors: Mutex)>>, + pub added_monitors: Mutex)>>, pub monitor_updates: Mutex>>, pub latest_monitor_update_id: Mutex>, - pub chain_monitor: chainmonitor::ChainMonitor>, + pub chain_monitor: chainmonitor::ChainMonitor>, pub keys_manager: &'a TestKeysInterface, /// If this is set to Some(), the next update_channel call (not watch_channel) must be a /// ChannelForceClosed event for the given channel_id with should_broadcast set to the given @@ -208,7 +208,7 @@ pub struct TestChainMonitor<'a> { pub expect_channel_force_closed: Mutex>, } impl<'a> TestChainMonitor<'a> { - pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a chainmonitor::Persist, keys_manager: &'a TestKeysInterface) -> Self { + pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a chainmonitor::Persist, keys_manager: &'a TestKeysInterface) -> Self { Self { added_monitors: Mutex::new(Vec::new()), monitor_updates: Mutex::new(HashMap::new()), @@ -224,13 +224,13 @@ impl<'a> TestChainMonitor<'a> { self.chain_monitor.channel_monitor_updated(outpoint, latest_update).unwrap(); } } -impl<'a> chain::Watch for TestChainMonitor<'a> { - fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> chain::ChannelMonitorUpdateStatus { +impl<'a> chain::Watch for TestChainMonitor<'a> { + fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> chain::ChannelMonitorUpdateStatus { // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... let mut w = TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( + let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap().1; assert!(new_monitor == monitor); self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), @@ -264,7 +264,7 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { let monitor = self.chain_monitor.get_monitor(funding_txo).unwrap(); w.0.clear(); monitor.write(&mut w).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( + let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap().1; assert!(new_monitor == *monitor); self.added_monitors.lock().unwrap().push((funding_txo, new_monitor)); @@ -979,16 +979,16 @@ impl NodeSigner for TestKeysInterface { } impl SignerProvider for TestKeysInterface { - type Signer = EnforcingSigner; + type Signer = TestChannelSigner; fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] { self.backing.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) } - fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> EnforcingSigner { + fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> TestChannelSigner { let keys = self.backing.derive_channel_signer(channel_value_satoshis, channel_keys_id); let state = self.make_enforcement_state_cell(keys.commitment_seed); - EnforcingSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) + TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) } fn read_chan_signer(&self, buffer: &[u8]) -> Result { @@ -997,7 +997,7 @@ impl SignerProvider for TestKeysInterface { let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); - Ok(EnforcingSigner::new_with_revoked( + Ok(TestChannelSigner::new_with_revoked( inner, state, self.disable_revocation_policy_check @@ -1038,10 +1038,10 @@ impl TestKeysInterface { self } - pub fn derive_channel_keys(&self, channel_value_satoshis: u64, id: &[u8; 32]) -> EnforcingSigner { + pub fn derive_channel_keys(&self, channel_value_satoshis: u64, id: &[u8; 32]) -> TestChannelSigner { let keys = self.backing.derive_channel_keys(channel_value_satoshis, id); let state = self.make_enforcement_state_cell(keys.commitment_seed); - EnforcingSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) + TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) } fn make_enforcement_state_cell(&self, commitment_seed: [u8; 32]) -> Arc> {