X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Ftest_utils.rs;h=3c36cdf066a5048bbb1b6fe112c2906ac824e6cc;hb=e49f738630559ce2eaa97689f1b4d37546fc7020;hp=6dd5836c4809ec4d9691f1d926457ab2aa985836;hpb=bb9df69d0d91cf5ea4cef6b81ab2edd9baddb6be;p=rust-lightning diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 6dd5836c..3c36cdf0 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -12,6 +12,7 @@ use chain::WatchedOutput; use chain::chaininterface; use chain::chaininterface::ConfirmationTarget; use chain::chainmonitor; +use chain::chainmonitor::MonitorUpdateId; use chain::channelmonitor; use chain::channelmonitor::MonitorEvent; use chain::transaction::OutPoint; @@ -20,6 +21,7 @@ use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::OptionalField; use ln::script::ShutdownScript; +use routing::scoring::FixedPenaltyScorer; use util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; use util::events; use util::logger::{Logger, Level, Record}; @@ -44,7 +46,8 @@ use core::time::Duration; use sync::{Mutex, Arc}; use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use core::{cmp, mem}; -use chain::keysinterface::InMemorySigner; +use bitcoin::bech32::u5; +use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial}; pub struct TestVecWriter(pub Vec); impl Writer for TestVecWriter { @@ -52,9 +55,6 @@ impl Writer for TestVecWriter { self.0.extend_from_slice(buf); Ok(()) } - fn size_hint(&mut self, size: usize) { - self.0.reserve_exact(size); - } } pub struct TestFeeEstimator { @@ -70,14 +70,16 @@ pub struct OnlyReadsKeysInterface {} impl keysinterface::KeysInterface for OnlyReadsKeysInterface { type Signer = EnforcingSigner; - fn get_node_secret(&self) -> SecretKey { unreachable!(); } + fn get_node_secret(&self, _recipient: Recipient) -> Result { unreachable!(); } + fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!(); } fn get_destination_script(&self) -> Script { unreachable!(); } fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!(); } fn get_channel_signer(&self, _inbound: bool, _channel_value_satoshis: u64) -> EnforcingSigner { unreachable!(); } fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } fn read_chan_signer(&self, mut reader: &[u8]) -> Result { - let inner: InMemorySigner = Readable::read(&mut reader)?; + let dummy_sk = SecretKey::from_slice(&[42; 32]).unwrap(); + let inner: InMemorySigner = ReadableArgs::read(&mut reader, dummy_sk)?; let state = Arc::new(Mutex::new(EnforcementState::new())); Ok(EnforcingSigner::new_with_revoked( @@ -86,38 +88,34 @@ impl keysinterface::KeysInterface for OnlyReadsKeysInterface { false )) } - fn sign_invoice(&self, _invoice_preimage: Vec) -> Result { unreachable!(); } + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!(); } } pub struct TestChainMonitor<'a> { pub added_monitors: Mutex)>>, - pub latest_monitor_update_id: Mutex>, - pub chain_monitor: chainmonitor::ChainMonitor>, + pub monitor_updates: Mutex>>, + pub latest_monitor_update_id: Mutex>, + pub chain_monitor: chainmonitor::ChainMonitor>, pub keys_manager: &'a TestKeysInterface, - pub update_ret: Mutex>>, - /// If this is set to Some(), after the next return, we'll always return this until update_ret - /// is changed: - pub next_update_ret: Mutex>>, /// 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 /// boolean. 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 channelmonitor::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()), latest_monitor_update_id: Mutex::new(HashMap::new()), chain_monitor: chainmonitor::ChainMonitor::new(chain_source, broadcaster, logger, fee_estimator, persister), keys_manager, - update_ret: Mutex::new(None), - next_update_ret: Mutex::new(None), expect_channel_force_closed: Mutex::new(None), } } } impl<'a> chain::Watch for TestChainMonitor<'a> { - fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { + fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), chain::ChannelMonitorUpdateErr> { // 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()); @@ -125,28 +123,21 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut io::Cursor::new(&w.0), self.keys_manager).unwrap().1; assert!(new_monitor == monitor); - self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), (funding_txo, monitor.get_latest_update_id())); + self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), + (funding_txo, monitor.get_latest_update_id(), MonitorUpdateId::from_new_monitor(&monitor))); self.added_monitors.lock().unwrap().push((funding_txo, monitor)); - let watch_res = self.chain_monitor.watch_channel(funding_txo, new_monitor); - - let ret = self.update_ret.lock().unwrap().clone(); - if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() { - *self.update_ret.lock().unwrap() = Some(next_ret); - } - if ret.is_some() { - assert!(watch_res.is_ok()); - return ret.unwrap(); - } - watch_res + self.chain_monitor.watch_channel(funding_txo, new_monitor) } - fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { + fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), chain::ChannelMonitorUpdateErr> { // Every monitor update should survive roundtrip let mut w = TestVecWriter(Vec::new()); update.write(&mut w).unwrap(); assert!(channelmonitor::ChannelMonitorUpdate::read( &mut io::Cursor::new(&w.0)).unwrap() == update); + self.monitor_updates.lock().unwrap().entry(funding_txo.to_channel_id()).or_insert(Vec::new()).push(update.clone()); + if let Some(exp) = self.expect_channel_force_closed.lock().unwrap().take() { assert_eq!(funding_txo.to_channel_id(), exp.0); assert_eq!(update.updates.len(), 1); @@ -155,27 +146,18 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { } else { panic!(); } } - self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), (funding_txo, update.update_id)); + self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), + (funding_txo, update.update_id, MonitorUpdateId::from_monitor_update(&update))); let update_res = self.chain_monitor.update_channel(funding_txo, update); // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... - let monitors = self.chain_monitor.monitors.read().unwrap(); - let monitor = monitors.get(&funding_txo).unwrap(); + 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( &mut io::Cursor::new(&w.0), self.keys_manager).unwrap().1; assert!(new_monitor == *monitor); self.added_monitors.lock().unwrap().push((funding_txo, new_monitor)); - - let ret = self.update_ret.lock().unwrap().clone(); - if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() { - *self.update_ret.lock().unwrap() = Some(next_ret); - } - if ret.is_some() { - assert!(update_res.is_ok()); - return ret.unwrap(); - } update_res } @@ -185,26 +167,55 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { } pub struct TestPersister { - pub update_ret: Mutex> + pub update_ret: Mutex>, + /// If this is set to Some(), after the next return, we'll always return this until update_ret + /// is changed: + pub next_update_ret: Mutex>>, + /// When we get an update_persisted_channel call with no ChannelMonitorUpdate, we insert the + /// MonitorUpdateId here. + pub chain_sync_monitor_persistences: Mutex>>, + /// When we get an update_persisted_channel call *with* a ChannelMonitorUpdate, we insert the + /// MonitorUpdateId here. + pub offchain_monitor_updates: Mutex>>, } impl TestPersister { pub fn new() -> Self { Self { - update_ret: Mutex::new(Ok(())) + update_ret: Mutex::new(Ok(())), + next_update_ret: Mutex::new(None), + chain_sync_monitor_persistences: Mutex::new(HashMap::new()), + offchain_monitor_updates: Mutex::new(HashMap::new()), } } - pub fn set_update_ret(&self, ret: Result<(), channelmonitor::ChannelMonitorUpdateErr>) { + pub fn set_update_ret(&self, ret: Result<(), chain::ChannelMonitorUpdateErr>) { *self.update_ret.lock().unwrap() = ret; } + + pub fn set_next_update_ret(&self, next_ret: Option>) { + *self.next_update_ret.lock().unwrap() = next_ret; + } } -impl channelmonitor::Persist for TestPersister { - fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { - self.update_ret.lock().unwrap().clone() +impl chainmonitor::Persist for TestPersister { + fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor, _id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> { + let ret = self.update_ret.lock().unwrap().clone(); + if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() { + *self.update_ret.lock().unwrap() = next_ret; + } + ret } - fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &channelmonitor::ChannelMonitorUpdate, _data: &channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { - self.update_ret.lock().unwrap().clone() + fn update_persisted_channel(&self, funding_txo: OutPoint, update: &Option, _data: &channelmonitor::ChannelMonitor, update_id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> { + let ret = self.update_ret.lock().unwrap().clone(); + if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() { + *self.update_ret.lock().unwrap() = next_ret; + } + if update.is_none() { + self.chain_sync_monitor_persistences.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id); + } else { + self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id); + } + ret } } @@ -212,6 +223,13 @@ pub struct TestBroadcaster { pub txn_broadcasted: Mutex>, pub blocks: Arc>>, } + +impl TestBroadcaster { + pub fn new(blocks: Arc>>) -> TestBroadcaster { + TestBroadcaster { txn_broadcasted: Mutex::new(Vec::new()), blocks } + } +} + impl chaininterface::BroadcasterInterface for TestBroadcaster { fn broadcast_transaction(&self, tx: &Transaction) { assert!(tx.lock_time < 1_500_000_000); @@ -323,7 +341,6 @@ fn get_dummy_channel_update(short_chan_id: u64) -> msgs::ChannelUpdate { pub struct TestRoutingMessageHandler { pub chan_upds_recvd: AtomicUsize, pub chan_anns_recvd: AtomicUsize, - pub chan_anns_sent: AtomicUsize, pub request_full_sync: AtomicBool, } @@ -332,7 +349,6 @@ impl TestRoutingMessageHandler { TestRoutingMessageHandler { chan_upds_recvd: AtomicUsize::new(0), chan_anns_recvd: AtomicUsize::new(0), - chan_anns_sent: AtomicUsize::new(0), request_full_sync: AtomicBool::new(false), } } @@ -351,8 +367,8 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { } fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(msgs::ChannelAnnouncement, Option, Option)> { let mut chan_anns = Vec::new(); - const TOTAL_UPDS: u64 = 100; - let end: u64 = cmp::min(starting_point + batch_amount as u64, TOTAL_UPDS - self.chan_anns_sent.load(Ordering::Acquire) as u64); + const TOTAL_UPDS: u64 = 50; + let end: u64 = cmp::min(starting_point + batch_amount as u64, TOTAL_UPDS); for i in starting_point..end { let chan_upd_1 = get_dummy_channel_update(i); let chan_upd_2 = get_dummy_channel_update(i); @@ -361,7 +377,6 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { chan_anns.push((chan_ann, Some(chan_upd_1), Some(chan_upd_2))); } - self.chan_anns_sent.fetch_add(chan_anns.len(), Ordering::AcqRel); chan_anns } @@ -369,7 +384,7 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { Vec::new() } - fn sync_routing_table(&self, _their_node_id: &PublicKey, _init_msg: &msgs::Init) {} + fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &msgs::Init) {} fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), msgs::LightningError> { Ok(()) @@ -396,7 +411,10 @@ impl events::MessageSendEventsProvider for TestRoutingMessageHandler { pub struct TestLogger { level: Level, + #[cfg(feature = "std")] id: String, + #[cfg(not(feature = "std"))] + _id: String, pub lines: Mutex>, } @@ -407,7 +425,10 @@ impl TestLogger { pub fn with_id(id: String) -> TestLogger { TestLogger { level: Level::Trace, + #[cfg(feature = "std")] id, + #[cfg(not(feature = "std"))] + _id: id, lines: Mutex::new(HashMap::new()) } } @@ -448,15 +469,15 @@ 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")] println!("{:<5} {} [{} : {}, {}] {}", record.level.to_string(), self.id, record.module_path, record.file, record.line, record.args); } } } pub struct TestKeysInterface { - pub backing: keysinterface::KeysManager, - pub override_session_priv: Mutex>, - pub override_channel_id_priv: Mutex>, + pub backing: keysinterface::PhantomKeysManager, + pub override_random_bytes: Mutex>, pub disable_revocation_policy_check: bool, enforcement_states: Mutex>>>, expectations: Mutex>>, @@ -465,7 +486,12 @@ pub struct TestKeysInterface { impl keysinterface::KeysInterface for TestKeysInterface { type Signer = EnforcingSigner; - fn get_node_secret(&self) -> SecretKey { self.backing.get_node_secret() } + fn get_node_secret(&self, recipient: Recipient) -> Result { + self.backing.get_node_secret(recipient) + } + fn get_inbound_payment_key_material(&self) -> keysinterface::KeyMaterial { + self.backing.get_inbound_payment_key_material() + } fn get_destination_script(&self) -> Script { self.backing.get_destination_script() } fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { @@ -485,16 +511,9 @@ impl keysinterface::KeysInterface for TestKeysInterface { } fn get_secure_random_bytes(&self) -> [u8; 32] { - let override_channel_id = self.override_channel_id_priv.lock().unwrap(); - let override_session_key = self.override_session_priv.lock().unwrap(); - if override_channel_id.is_some() && override_session_key.is_some() { - panic!("We don't know which override key to use!"); - } - if let Some(key) = &*override_channel_id { - return *key; - } - if let Some(key) = &*override_session_key { - return *key; + let override_random_bytes = self.override_random_bytes.lock().unwrap(); + if let Some(bytes) = &*override_random_bytes { + return *bytes; } self.backing.get_secure_random_bytes() } @@ -502,7 +521,7 @@ impl keysinterface::KeysInterface for TestKeysInterface { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = io::Cursor::new(buffer); - let inner: InMemorySigner = Readable::read(&mut reader)?; + let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner::new_with_revoked( @@ -512,8 +531,8 @@ impl keysinterface::KeysInterface for TestKeysInterface { )) } - fn sign_invoice(&self, invoice_preimage: Vec) -> Result { - self.backing.sign_invoice(invoice_preimage) + fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { + self.backing.sign_invoice(hrp_bytes, invoice_data, recipient) } } @@ -521,9 +540,8 @@ 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::KeysManager::new(seed, now.as_secs(), now.subsec_nanos()), - override_session_priv: Mutex::new(None), - override_channel_id_priv: Mutex::new(None), + backing: keysinterface::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()), expectations: Mutex::new(None), @@ -556,9 +574,17 @@ impl TestKeysInterface { } } +pub(crate) fn panicking() -> bool { + #[cfg(feature = "std")] + let panicking = ::std::thread::panicking(); + #[cfg(not(feature = "std"))] + let panicking = false; + return panicking; +} + impl Drop for TestKeysInterface { fn drop(&mut self) { - if std::thread::panicking() { + if panicking() { return; } @@ -650,7 +676,7 @@ impl chain::Filter for TestChainSource { impl Drop for TestChainSource { fn drop(&mut self) { - if std::thread::panicking() { + if panicking() { return; } @@ -696,3 +722,6 @@ impl core::fmt::Debug for OnRegisterOutput { .finish() } } + +/// A scorer useful in testing, when the passage of time isn't a concern. +pub type TestScorer = FixedPenaltyScorer;