X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Ftest_utils.rs;h=ba56edf3584f017ab0aa623e19aad6d2ec07f2e2;hb=2d6464cd71b658ebc41c686bc602667c9c0b9e53;hp=387f9df677e969def3eca8bde64186213854a3be;hpb=cc4bc1df5a1ab6c363fac3c1b7eddce362e167c0;p=rust-lightning diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 387f9df6..ba56edf3 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -7,6 +7,8 @@ // You may not use this file except in accordance with one or both of these // licenses. +use crate::blinded_path::BlindedPath; +use crate::blinded_path::payment::ReceiveTlvs; use crate::chain; use crate::chain::WatchedOutput; use crate::chain::chaininterface; @@ -22,17 +24,18 @@ use crate::sign; use crate::events; use crate::events::bump_transaction::{WalletSource, Utxo}; use crate::ln::ChannelId; -use crate::ln::channelmanager; +use crate::ln::channelmanager::{ChannelDetails, self}; use crate::ln::chan_utils::CommitmentTransaction; use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::{msgs, wire}; use crate::ln::msgs::LightningError; use crate::ln::script::ShutdownScript; -use crate::offers::invoice::UnsignedBolt12Invoice; +use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice}; use crate::offers::invoice_request::UnsignedInvoiceRequest; -use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; +use crate::onion_message::{Destination, MessageRouter, OnionMessagePath}; +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; @@ -51,7 +54,7 @@ use bitcoin::network::constants::Network; use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::sighash::{SighashCache, EcdsaSighashType}; -use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey}; +use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; @@ -71,6 +74,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 { @@ -118,7 +122,7 @@ impl<'a> TestRouter<'a> { impl<'a> Router for TestRouter<'a> { fn find_route( - &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&channelmanager::ChannelDetails]>, + &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs ) -> Result { if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() { @@ -129,6 +133,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 { @@ -137,39 +142,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 { - let first_hops = match first_hops { - Some(hops) => hops, - None => continue, - }; - if first_hops.len() == 0 { - continue; + 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 idx = if first_hops.len() > 1 { route.paths.iter().position(|p| p == path).unwrap_or(0) } else { 0 }; - let node_id = NodeId::from_pubkey(payer); - let candidate = CandidateRouteHop::FirstHop { - details: first_hops[idx], - payer_node_id: &node_id, + } + 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 network_graph = self.network_graph.read_only(); - let channel = match network_graph.channel(hop.short_channel_id) { - Some(channel) => channel, - None => continue, - }; - let channel = match channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)) { - Some(channel) => channel, - None => panic!("Channel directed to {} was not found", hop.pubkey), - }; - let candidate = CandidateRouteHop::PublicHop { - info: channel.0, + 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; } } } @@ -182,6 +192,32 @@ impl<'a> Router for TestRouter<'a> { &[42; 32] ) } + + fn create_blinded_payment_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, _recipient: PublicKey, _first_hops: Vec, _tlvs: ReceiveTlvs, + _amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1 + ) -> Result, ()> { + unreachable!() + } +} + +impl<'a> MessageRouter for TestRouter<'a> { + fn find_path( + &self, _sender: PublicKey, _peers: Vec, _destination: Destination + ) -> Result { + unreachable!() + } + + fn create_blinded_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, _recipient: PublicKey, _peers: Vec, _entropy_source: &ES, + _secp_ctx: &Secp256k1 + ) -> Result, ()> { + unreachable!() + } } impl<'a> Drop for TestRouter<'a> { @@ -228,7 +264,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 @@ -239,7 +275,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()), @@ -1343,13 +1379,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 { @@ -1411,7 +1449,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) {