Merge pull request #2506 from tnull/2023-08-dont-leak-internal-macros
[rust-lightning] / lightning / src / util / test_utils.rs
index e39e894f5e7961c0df1eec33568d72cd6fcb76ec..65c0483a59c9906e36b4a42587698362bd77702c 100644 (file)
@@ -16,8 +16,9 @@ use crate::chain::chainmonitor::MonitorUpdateId;
 use crate::chain::channelmonitor;
 use crate::chain::channelmonitor::MonitorEvent;
 use crate::chain::transaction::OutPoint;
-use crate::chain::keysinterface;
+use crate::sign;
 use crate::events;
+use crate::events::bump_transaction::{WalletSource, Utxo};
 use crate::ln::channelmanager;
 use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use crate::ln::{msgs, wire};
@@ -32,6 +33,8 @@ use crate::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
 use crate::util::logger::{Logger, Level, Record};
 use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
 
+use bitcoin::EcdsaSighashType;
+use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::{Builder, Script};
@@ -39,27 +42,39 @@ use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::block::Block;
 use bitcoin::network::constants::Network;
 use bitcoin::hash_types::{BlockHash, Txid};
+use bitcoin::util::sighash::SighashCache;
 
 use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, ecdsa::Signature, Scalar};
 use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1::ecdsa::RecoverableSignature;
 
+#[cfg(any(test, feature = "_test_utils"))]
 use regex;
 
 use crate::io;
 use crate::prelude::*;
 use core::cell::RefCell;
+use core::ops::DerefMut;
 use core::time::Duration;
 use crate::sync::{Mutex, Arc};
 use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use core::mem;
 use bitcoin::bech32::u5;
-use crate::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider};
+use crate::sign::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider};
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
 use bitcoin::Sequence;
 
+pub fn pubkey(byte: u8) -> PublicKey {
+       let secp_ctx = Secp256k1::new();
+       PublicKey::from_secret_key(&secp_ctx, &privkey(byte))
+}
+
+pub fn privkey(byte: u8) -> SecretKey {
+       SecretKey::from_slice(&[byte; 32]).unwrap()
+}
+
 pub struct TestVecWriter(pub Vec<u8>);
 impl Writer for TestVecWriter {
        fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> {
@@ -97,13 +112,13 @@ impl<'a> TestRouter<'a> {
 impl<'a> Router for TestRouter<'a> {
        fn find_route(
                &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&channelmanager::ChannelDetails]>,
-               inflight_htlcs: &InFlightHtlcs
+               inflight_htlcs: InFlightHtlcs
        ) -> Result<Route, msgs::LightningError> {
                if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() {
                        assert_eq!(find_route_query, *params);
                        if let Ok(ref route) = find_route_res {
-                               let locked_scorer = self.scorer.lock().unwrap();
-                               let scorer = ScorerAccountingForInFlightHtlcs::new(locked_scorer, inflight_htlcs);
+                               let mut binding = self.scorer.lock().unwrap();
+                               let scorer = ScorerAccountingForInFlightHtlcs::new(binding.deref_mut(), &inflight_htlcs);
                                for path in &route.paths {
                                        let mut aggregate_msat = 0u64;
                                        for (idx, hop) in path.hops.iter().rev().enumerate() {
@@ -117,10 +132,10 @@ impl<'a> Router for TestRouter<'a> {
                                                // Since the path is reversed, the last element in our iteration is the first
                                                // hop.
                                                if idx == path.hops.len() - 1 {
-                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage);
+                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage, &());
                                                } else {
                                                        let curr_hop_path_idx = path.hops.len() - 1 - idx;
-                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage);
+                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage, &());
                                                }
                                        }
                                }
@@ -128,10 +143,9 @@ impl<'a> Router for TestRouter<'a> {
                        return find_route_res;
                }
                let logger = TestLogger::new();
-               let scorer = self.scorer.lock().unwrap();
                find_route(
                        payer, params, &self.network_graph, first_hops, &logger,
-                       &ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs),
+                       &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock().unwrap().deref_mut(), &inflight_htlcs), &(),
                        &[42; 32]
                )
        }
@@ -161,7 +175,7 @@ impl SignerProvider for OnlyReadsKeysInterface {
        fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { unreachable!(); }
 
        fn read_chan_signer(&self, mut reader: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
-               let inner: InMemorySigner = Readable::read(&mut reader)?;
+               let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?;
                let state = Arc::new(Mutex::new(EnforcementState::new()));
 
                Ok(EnforcingSigner::new_with_revoked(
@@ -171,8 +185,8 @@ impl SignerProvider for OnlyReadsKeysInterface {
                ))
        }
 
-       fn get_destination_script(&self) -> Script { unreachable!(); }
-       fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!(); }
+       fn get_destination_script(&self) -> Result<Script, ()> { Err(()) }
+       fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> { Err(()) }
 }
 
 pub struct TestChainMonitor<'a> {
@@ -280,7 +294,7 @@ impl TestPersister {
                self.update_rets.lock().unwrap().push_back(next_ret);
        }
 }
-impl<Signer: keysinterface::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for TestPersister {
+impl<Signer: sign::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for TestPersister {
        fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>, _id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
                if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() {
                        return update_ret
@@ -308,8 +322,15 @@ pub struct TestBroadcaster {
 }
 
 impl TestBroadcaster {
-       pub fn new(blocks: Arc<Mutex<Vec<(Block, u32)>>>) -> TestBroadcaster {
-               TestBroadcaster { txn_broadcasted: Mutex::new(Vec::new()), blocks }
+       pub fn new(network: Network) -> Self {
+               Self {
+                       txn_broadcasted: Mutex::new(Vec::new()),
+                       blocks: Arc::new(Mutex::new(vec![(genesis_block(network), 0)])),
+               }
+       }
+
+       pub fn with_blocks(blocks: Arc<Mutex<Vec<(Block, u32)>>>) -> Self {
+               Self { txn_broadcasted: Mutex::new(Vec::new()), blocks }
        }
 
        pub fn txn_broadcast(&self) -> Vec<Transaction> {
@@ -325,17 +346,20 @@ impl TestBroadcaster {
 }
 
 impl chaininterface::BroadcasterInterface for TestBroadcaster {
-       fn broadcast_transaction(&self, tx: &Transaction) {
-               let lock_time = tx.lock_time.0;
-               assert!(lock_time < 1_500_000_000);
-               if lock_time > self.blocks.lock().unwrap().len() as u32 + 1 && lock_time < 500_000_000 {
-                       for inp in tx.input.iter() {
-                               if inp.sequence != Sequence::MAX {
-                                       panic!("We should never broadcast a transaction before its locktime ({})!", tx.lock_time);
+       fn broadcast_transactions(&self, txs: &[&Transaction]) {
+               for tx in txs {
+                       let lock_time = tx.lock_time.0;
+                       assert!(lock_time < 1_500_000_000);
+                       if bitcoin::LockTime::from(tx.lock_time).is_block_height() && lock_time > self.blocks.lock().unwrap().last().unwrap().1 {
+                               for inp in tx.input.iter() {
+                                       if inp.sequence != Sequence::MAX {
+                                               panic!("We should never broadcast a transaction before its locktime ({})!", tx.lock_time);
+                                       }
                                }
                        }
                }
-               self.txn_broadcasted.lock().unwrap().push(tx.clone());
+               let owned_txs: Vec<Transaction> = txs.iter().map(|tx| (*tx).clone()).collect();
+               self.txn_broadcasted.lock().unwrap().extend(owned_txs);
        }
 }
 
@@ -343,14 +367,18 @@ pub struct TestChannelMessageHandler {
        pub pending_events: Mutex<Vec<events::MessageSendEvent>>,
        expected_recv_msgs: Mutex<Option<Vec<wire::Message<()>>>>,
        connected_peers: Mutex<HashSet<PublicKey>>,
+       pub message_fetch_counter: AtomicUsize,
+       genesis_hash: ChainHash,
 }
 
 impl TestChannelMessageHandler {
-       pub fn new() -> Self {
+       pub fn new(genesis_hash: ChainHash) -> Self {
                TestChannelMessageHandler {
                        pending_events: Mutex::new(Vec::new()),
                        expected_recv_msgs: Mutex::new(None),
                        connected_peers: Mutex::new(HashSet::new()),
+                       message_fetch_counter: AtomicUsize::new(0),
+                       genesis_hash,
                }
        }
 
@@ -453,10 +481,59 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
        fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures {
                channelmanager::provided_init_features(&UserConfig::default())
        }
+
+       fn get_genesis_hashes(&self) -> Option<Vec<ChainHash>> {
+               Some(vec![self.genesis_hash])
+       }
+
+       fn handle_open_channel_v2(&self, _their_node_id: &PublicKey, msg: &msgs::OpenChannelV2) {
+               self.received_msg(wire::Message::OpenChannelV2(msg.clone()));
+       }
+
+       fn handle_accept_channel_v2(&self, _their_node_id: &PublicKey, msg: &msgs::AcceptChannelV2) {
+               self.received_msg(wire::Message::AcceptChannelV2(msg.clone()));
+       }
+
+       fn handle_tx_add_input(&self, _their_node_id: &PublicKey, msg: &msgs::TxAddInput) {
+               self.received_msg(wire::Message::TxAddInput(msg.clone()));
+       }
+
+       fn handle_tx_add_output(&self, _their_node_id: &PublicKey, msg: &msgs::TxAddOutput) {
+               self.received_msg(wire::Message::TxAddOutput(msg.clone()));
+       }
+
+       fn handle_tx_remove_input(&self, _their_node_id: &PublicKey, msg: &msgs::TxRemoveInput) {
+               self.received_msg(wire::Message::TxRemoveInput(msg.clone()));
+       }
+
+       fn handle_tx_remove_output(&self, _their_node_id: &PublicKey, msg: &msgs::TxRemoveOutput) {
+               self.received_msg(wire::Message::TxRemoveOutput(msg.clone()));
+       }
+
+       fn handle_tx_complete(&self, _their_node_id: &PublicKey, msg: &msgs::TxComplete) {
+               self.received_msg(wire::Message::TxComplete(msg.clone()));
+       }
+
+       fn handle_tx_signatures(&self, _their_node_id: &PublicKey, msg: &msgs::TxSignatures) {
+               self.received_msg(wire::Message::TxSignatures(msg.clone()));
+       }
+
+       fn handle_tx_init_rbf(&self, _their_node_id: &PublicKey, msg: &msgs::TxInitRbf) {
+               self.received_msg(wire::Message::TxInitRbf(msg.clone()));
+       }
+
+       fn handle_tx_ack_rbf(&self, _their_node_id: &PublicKey, msg: &msgs::TxAckRbf) {
+               self.received_msg(wire::Message::TxAckRbf(msg.clone()));
+       }
+
+       fn handle_tx_abort(&self, _their_node_id: &PublicKey, msg: &msgs::TxAbort) {
+               self.received_msg(wire::Message::TxAbort(msg.clone()));
+       }
 }
 
 impl events::MessageSendEventsProvider for TestChannelMessageHandler {
        fn get_and_clear_pending_msg_events(&self) -> Vec<events::MessageSendEvent> {
+               self.message_fetch_counter.fetch_add(1, Ordering::AcqRel);
                let mut pending_events = self.pending_events.lock().unwrap();
                let mut ret = Vec::new();
                mem::swap(&mut ret, &mut *pending_events);
@@ -665,6 +742,7 @@ impl TestLogger {
        /// 1. belong to the specified module and
        /// 2. match the given regex pattern.
        /// Assert that the number of occurrences equals the given `count`
+       #[cfg(any(test, feature = "_test_utils"))]
        pub fn assert_log_regex(&self, module: &str, pattern: regex::Regex, count: usize) {
                let log_entries = self.lines.lock().unwrap();
                let l: usize = log_entries.iter().filter(|&(&(ref m, ref l), _c)| {
@@ -678,7 +756,7 @@ impl Logger for TestLogger {
        fn log(&self, record: &Record) {
                *self.lines.lock().unwrap().entry((record.module_path.to_string(), format!("{}", record.args))).or_insert(0) += 1;
                if record.level >= self.level {
-                       #[cfg(feature = "std")]
+                       #[cfg(all(not(ldk_bench), feature = "std"))]
                        println!("{:<5} {} [{} : {}, {}] {}", record.level.to_string(), self.id, record.module_path, record.file, record.line, record.args);
                }
        }
@@ -695,7 +773,7 @@ impl TestNodeSigner {
 }
 
 impl NodeSigner for TestNodeSigner {
-       fn get_inbound_payment_key_material(&self) -> crate::chain::keysinterface::KeyMaterial {
+       fn get_inbound_payment_key_material(&self) -> crate::sign::KeyMaterial {
                unreachable!()
        }
 
@@ -728,7 +806,7 @@ impl NodeSigner for TestNodeSigner {
 }
 
 pub struct TestKeysInterface {
-       pub backing: keysinterface::PhantomKeysManager,
+       pub backing: sign::PhantomKeysManager,
        pub override_random_bytes: Mutex<Option<[u8; 32]>>,
        pub disable_revocation_policy_check: bool,
        enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
@@ -754,7 +832,7 @@ impl NodeSigner for TestKeysInterface {
                self.backing.ecdh(recipient, other_key, tweak)
        }
 
-       fn get_inbound_payment_key_material(&self) -> keysinterface::KeyMaterial {
+       fn get_inbound_payment_key_material(&self) -> sign::KeyMaterial {
                self.backing.get_inbound_payment_key_material()
        }
 
@@ -783,7 +861,7 @@ impl SignerProvider for TestKeysInterface {
        fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
                let mut reader = io::Cursor::new(buffer);
 
-               let inner: InMemorySigner = Readable::read(&mut reader)?;
+               let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?;
                let state = self.make_enforcement_state_cell(inner.commitment_seed);
 
                Ok(EnforcingSigner::new_with_revoked(
@@ -793,14 +871,14 @@ impl SignerProvider for TestKeysInterface {
                ))
        }
 
-       fn get_destination_script(&self) -> Script { self.backing.get_destination_script() }
+       fn get_destination_script(&self) -> Result<Script, ()> { self.backing.get_destination_script() }
 
-       fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+       fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> {
                match &mut *self.expectations.lock().unwrap() {
                        None => self.backing.get_shutdown_scriptpubkey(),
                        Some(expectations) => match expectations.pop_front() {
                                None => panic!("Unexpected get_shutdown_scriptpubkey"),
-                               Some(expectation) => expectation.returns,
+                               Some(expectation) => Ok(expectation.returns),
                        },
                }
        }
@@ -810,7 +888,7 @@ impl TestKeysInterface {
        pub fn new(seed: &[u8; 32], network: Network) -> Self {
                let now = Duration::from_secs(genesis_block(network).header.time as u64);
                Self {
-                       backing: keysinterface::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed),
+                       backing: sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed),
                        override_random_bytes: Mutex::new(None),
                        disable_revocation_policy_check: false,
                        enforcement_states: Mutex::new(HashMap::new()),
@@ -818,7 +896,7 @@ impl TestKeysInterface {
                }
        }
 
-       /// Sets an expectation that [`keysinterface::SignerProvider::get_shutdown_scriptpubkey`] is
+       /// Sets an expectation that [`sign::SignerProvider::get_shutdown_scriptpubkey`] is
        /// called.
        pub fn expect(&self, expectation: OnGetShutdownScriptpubkey) -> &Self {
                self.expectations.lock().unwrap()
@@ -866,7 +944,7 @@ impl Drop for TestKeysInterface {
        }
 }
 
-/// An expectation that [`keysinterface::SignerProvider::get_shutdown_scriptpubkey`] was called and
+/// An expectation that [`sign::SignerProvider::get_shutdown_scriptpubkey`] was called and
 /// returns a [`ShutdownScript`].
 pub struct OnGetShutdownScriptpubkey {
        /// A shutdown script used to close a channel.
@@ -952,8 +1030,9 @@ impl crate::util::ser::Writeable for TestScorer {
 }
 
 impl Score for TestScorer {
+       type ScoreParams = ();
        fn channel_penalty_msat(
-               &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage
+               &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams
        ) -> u64 {
                if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
                        match scorer_expectations.pop_front() {
@@ -991,3 +1070,65 @@ impl Drop for TestScorer {
                }
        }
 }
+
+pub struct TestWalletSource {
+       secret_key: SecretKey,
+       utxos: RefCell<Vec<Utxo>>,
+       secp: Secp256k1<bitcoin::secp256k1::All>,
+}
+
+impl TestWalletSource {
+       pub fn new(secret_key: SecretKey) -> Self {
+               Self {
+                       secret_key,
+                       utxos: RefCell::new(Vec::new()),
+                       secp: Secp256k1::new(),
+               }
+       }
+
+       pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: u64) -> TxOut {
+               let public_key = bitcoin::PublicKey::new(self.secret_key.public_key(&self.secp));
+               let utxo = Utxo::new_p2pkh(outpoint, value, &public_key.pubkey_hash());
+               self.utxos.borrow_mut().push(utxo.clone());
+               utxo.output
+       }
+
+       pub fn add_custom_utxo(&self, utxo: Utxo) -> TxOut {
+               let output = utxo.output.clone();
+               self.utxos.borrow_mut().push(utxo);
+               output
+       }
+
+       pub fn remove_utxo(&self, outpoint: bitcoin::OutPoint) {
+               self.utxos.borrow_mut().retain(|utxo| utxo.outpoint != outpoint);
+       }
+}
+
+impl WalletSource for TestWalletSource {
+       fn list_confirmed_utxos(&self) -> Result<Vec<Utxo>, ()> {
+               Ok(self.utxos.borrow().clone())
+       }
+
+       fn get_change_script(&self) -> Result<Script, ()> {
+               let public_key = bitcoin::PublicKey::new(self.secret_key.public_key(&self.secp));
+               Ok(Script::new_p2pkh(&public_key.pubkey_hash()))
+       }
+
+       fn sign_tx(&self, mut tx: Transaction) -> Result<Transaction, ()> {
+               let utxos = self.utxos.borrow();
+               for i in 0..tx.input.len() {
+                       if let Some(utxo) = utxos.iter().find(|utxo| utxo.outpoint == tx.input[i].previous_output) {
+                               let sighash = SighashCache::new(&tx)
+                                       .legacy_signature_hash(i, &utxo.output.script_pubkey, EcdsaSighashType::All as u32)
+                                       .map_err(|_| ())?;
+                               let sig = self.secp.sign_ecdsa(&sighash.as_hash().into(), &self.secret_key);
+                               let bitcoin_sig = bitcoin::EcdsaSig { sig, hash_ty: EcdsaSighashType::All }.to_vec();
+                               tx.input[i].script_sig = Builder::new()
+                                       .push_slice(&bitcoin_sig)
+                                       .push_slice(&self.secret_key.public_key(&self.secp).serialize())
+                                       .into_script();
+                       }
+               }
+               Ok(tx)
+       }
+}