X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Ftest_utils.rs;h=805806dc34645f765ab9b616c283164a273eeb1e;hb=ee026d43574c49e41aa0355c6fda49c72b45523e;hp=0606e36e50e01d88496351e18dc7c019f94aae1e;hpb=6b43153861c4f8dd1f44da737ad0b06eab8659e7;p=rust-lightning diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 0606e36e..805806dc 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -17,6 +17,7 @@ use crate::chain::chainmonitor::{MonitorUpdateId, UpdateOrigin}; use crate::chain::channelmonitor; use crate::chain::channelmonitor::MonitorEvent; use crate::chain::transaction::OutPoint; +use crate::routing::router::CandidateRouteHop; use crate::sign; use crate::events; use crate::events::bump_transaction::{WalletSource, Utxo}; @@ -29,9 +30,9 @@ use crate::ln::msgs::LightningError; use crate::ln::script::ShutdownScript; use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::invoice_request::UnsignedInvoiceRequest; -use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; +use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult}; -use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, Router, ScorerAccountingForInFlightHtlcs}; +use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, RouteHintHop, Router, ScorerAccountingForInFlightHtlcs}; use crate::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp}; use crate::sync::RwLock; use crate::util::config::UserConfig; @@ -70,6 +71,7 @@ use crate::sign::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerPr #[cfg(feature = "std")] use std::time::{SystemTime, UNIX_EPOCH}; +use bitcoin::psbt::PartiallySignedTransaction; use bitcoin::Sequence; pub fn pubkey(byte: u8) -> PublicKey { @@ -128,6 +130,7 @@ impl<'a> Router for TestRouter<'a> { let scorer = ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs); for path in &route.paths { let mut aggregate_msat = 0u64; + let mut prev_hop_node = payer; for (idx, hop) in path.hops.iter().rev().enumerate() { aggregate_msat += hop.fee_msat; let usage = ChannelUsage { @@ -136,14 +139,44 @@ impl<'a> Router for TestRouter<'a> { effective_capacity: EffectiveCapacity::Unknown, }; - // 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, &Default::default()); + if let Some(first_hops) = first_hops { + if let Some(idx) = first_hops.iter().position(|h| h.get_outbound_payment_scid() == Some(hop.short_channel_id)) { + let node_id = NodeId::from_pubkey(payer); + let candidate = CandidateRouteHop::FirstHop { + details: first_hops[idx], + payer_node_id: &node_id, + }; + scorer.channel_penalty_msat(&candidate, usage, &()); + continue; + } + } + } + let network_graph = self.network_graph.read_only(); + if let Some(channel) = network_graph.channel(hop.short_channel_id) { + let (directed, _) = channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info: directed, + short_channel_id: hop.short_channel_id, + }; + scorer.channel_penalty_msat(&candidate, 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, &Default::default()); + let target_node_id = NodeId::from_pubkey(&hop.pubkey); + let route_hint = RouteHintHop { + src_node_id: *prev_hop_node, + short_channel_id: hop.short_channel_id, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, + cltv_expiry_delta: 0, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }; + let candidate = CandidateRouteHop::PrivateHop { + hint: &route_hint, + target_node_id: &target_node_id, + }; + scorer.channel_penalty_msat(&candidate, usage, &()); } + prev_hop_node = &hop.pubkey; } } } @@ -202,7 +235,7 @@ pub struct TestChainMonitor<'a> { 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 @@ -213,7 +246,7 @@ pub struct TestChainMonitor<'a> { pub expect_monitor_round_trip_fail: 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 dyn chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a dyn chainmonitor::Persist, keys_manager: &'a TestKeysInterface) -> Self { Self { added_monitors: Mutex::new(Vec::new()), monitor_updates: Mutex::new(HashMap::new()), @@ -930,8 +963,8 @@ impl events::MessageSendEventsProvider for TestRoutingMessageHandler { pub struct TestLogger { level: Level, pub(crate) id: String, - pub lines: Mutex>, - pub context: Mutex, Option), usize>>, + pub lines: Mutex>, + pub context: Mutex, Option), usize>>, } impl TestLogger { @@ -949,7 +982,7 @@ impl TestLogger { pub fn enable(&mut self, level: Level) { self.level = level; } - pub fn assert_log(&self, module: String, line: String, count: usize) { + pub fn assert_log(&self, module: &str, line: String, count: usize) { let log_entries = self.lines.lock().unwrap(); assert_eq!(log_entries.get(&(module, line)), Some(&count)); } @@ -961,7 +994,7 @@ impl TestLogger { pub fn assert_log_contains(&self, module: &str, line: &str, count: usize) { let log_entries = self.lines.lock().unwrap(); let l: usize = log_entries.iter().filter(|&(&(ref m, ref l), _c)| { - m == module && l.contains(line) + *m == module && l.contains(line) }).map(|(_, c) | { c }).sum(); assert_eq!(l, count) } @@ -974,7 +1007,7 @@ impl TestLogger { 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)| { - m == module && pattern.is_match(&l) + *m == module && pattern.is_match(&l) }).map(|(_, c) | { c }).sum(); assert_eq!(l, count) } @@ -983,18 +1016,15 @@ impl TestLogger { &self, module: &str, peer_id: Option, channel_id: Option, count: usize ) { let context_entries = self.context.lock().unwrap(); - let l: usize = context_entries.iter() - .filter(|&(&(ref m, ref p, ref c), _)| m == module && *p == peer_id && *c == channel_id) - .map(|(_, c) | c) - .sum(); - assert_eq!(l, count) + let l = context_entries.get(&(module, peer_id, channel_id)).unwrap(); + assert_eq!(*l, count) } } 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; - *self.context.lock().unwrap().entry((record.module_path.to_string(), record.peer_id, record.channel_id)).or_insert(0) += 1; + *self.lines.lock().unwrap().entry((record.module_path, format!("{}", record.args))).or_insert(0) += 1; + *self.context.lock().unwrap().entry((record.module_path, record.peer_id, record.channel_id)).or_insert(0) += 1; if record.level >= self.level { #[cfg(all(not(ldk_bench), feature = "std"))] { let pfx = format!("{} {} [{}:{}]", self.id, record.level.to_string(), record.module_path, record.line); @@ -1300,8 +1330,12 @@ impl crate::util::ser::Writeable for TestScorer { impl ScoreLookUp for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &Self::ScoreParams ) -> u64 { + let short_channel_id = match candidate.globally_unique_short_channel_id() { + Some(scid) => scid, + None => return 0, + }; if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() { match scorer_expectations.pop_front() { Some((scid, expectation)) => { @@ -1316,13 +1350,15 @@ impl ScoreLookUp for TestScorer { } impl ScoreUpdate for TestScorer { - fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64) {} + fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64, _duration_since_epoch: Duration) {} + + fn payment_path_successful(&mut self, _actual_path: &Path, _duration_since_epoch: Duration) {} - fn payment_path_successful(&mut self, _actual_path: &Path) {} + fn probe_failed(&mut self, _actual_path: &Path, _: u64, _duration_since_epoch: Duration) {} - fn probe_failed(&mut self, _actual_path: &Path, _: u64) {} + fn probe_successful(&mut self, _actual_path: &Path, _duration_since_epoch: Duration) {} - fn probe_successful(&mut self, _actual_path: &Path) {} + fn time_passed(&mut self, _duration_since_epoch: Duration) {} } impl Drop for TestScorer { @@ -1384,7 +1420,8 @@ impl WalletSource for TestWalletSource { Ok(ScriptBuf::new_p2pkh(&public_key.pubkey_hash())) } - fn sign_tx(&self, mut tx: Transaction) -> Result { + fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result { + let mut tx = psbt.extract_tx(); 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) {