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::ln::channelmanager;
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::ln::{msgs, wire};
use crate::ln::script::ShutdownScript;
use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
-use crate::routing::router::{find_route, InFlightHtlcs, Route, RouteHop, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
+use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
use crate::routing::scoring::{ChannelUsage, Score};
use crate::util::config::UserConfig;
use crate::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
-use crate::util::events;
use crate::util::logger::{Logger, Level, Record};
use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
+use bitcoin::blockdata::constants::ChainHash;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::blockdata::script::{Builder, Script};
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> {
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.iter().rev().enumerate() {
+ for (idx, hop) in path.hops.iter().rev().enumerate() {
aggregate_msat += hop.fee_msat;
let usage = ChannelUsage {
amount_msat: aggregate_msat,
// Since the path is reversed, the last element in our iteration is the first
// hop.
- if idx == path.len() - 1 {
- scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage);
+ if idx == path.hops.len() - 1 {
+ 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.len() - 1 - idx;
- scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage);
+ 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, &());
}
}
}
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]
)
}
}
-#[cfg(feature = "std")] // If we put this on the `if`, we get "attributes are not yet allowed on `if` expressions" on 1.41.1
impl<'a> Drop for TestRouter<'a> {
fn drop(&mut self) {
- if std::thread::panicking() {
- return;
+ #[cfg(feature = "std")] {
+ if std::thread::panicking() {
+ return;
+ }
}
assert!(self.next_routes.lock().unwrap().is_empty());
}
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(
))
}
- 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> {
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
}
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> {
+ self.txn_broadcasted.lock().unwrap().split_off(0)
+ }
+
+ pub fn unique_txn_broadcast(&self) -> Vec<Transaction> {
+ let mut txn = self.txn_broadcasted.lock().unwrap().split_off(0);
+ let mut seen = HashSet::new();
+ txn.retain(|tx| seen.insert(tx.txid()));
+ txn
}
}
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);
}
}
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,
}
}
fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, msg: &msgs::ChannelReestablish) {
self.received_msg(wire::Message::ChannelReestablish(msg.clone()));
}
- fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
- fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) -> Result<(), ()> {
+ fn peer_disconnected(&self, their_node_id: &PublicKey) {
+ assert!(self.connected_peers.lock().unwrap().remove(their_node_id));
+ }
+ fn peer_connected(&self, their_node_id: &PublicKey, _msg: &msgs::Init, _inbound: bool) -> Result<(), ()> {
+ assert!(self.connected_peers.lock().unwrap().insert(their_node_id.clone()));
// Don't bother with `received_msg` for Init as its auto-generated and we don't want to
// bother re-generating the expected Init message in all tests.
Ok(())
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);
None
}
- fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init) -> Result<(), ()> {
+ fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init, _inbound: bool) -> Result<(), ()> {
if !init_msg.features.supports_gossip_queries() {
return Ok(());
}
/// 1. belongs to the specified module and
/// 2. contains `line` in it.
/// And asserts if the number of occurrences is the same with the given `count`
- pub fn assert_log_contains(&self, module: String, line: String, count: usize) {
+ 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.as_str())
+ m == module && l.contains(line)
}).map(|(_, c) | { c }).sum();
assert_eq!(l, count)
}
/// 1. belong to the specified module and
/// 2. match the given regex pattern.
/// Assert that the number of occurrences equals the given `count`
- pub fn assert_log_regex(&self, module: String, pattern: regex::Regex, count: usize) {
+ #[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)| {
- m == &module && pattern.is_match(&l)
+ m == module && pattern.is_match(&l)
}).map(|(_, c) | { c }).sum();
assert_eq!(l, count)
}
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);
}
}
}
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!()
}
}
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>>>>,
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()
}
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(
))
}
- 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),
},
}
}
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()),
}
}
- /// 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()
}
}
-/// 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.
}
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() {
0
}
- fn payment_path_failed(&mut self, _actual_path: &[&RouteHop], _actual_short_channel_id: u64) {}
+ fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64) {}
- fn payment_path_successful(&mut self, _actual_path: &[&RouteHop]) {}
+ fn payment_path_successful(&mut self, _actual_path: &Path) {}
- fn probe_failed(&mut self, _actual_path: &[&RouteHop], _: u64) {}
+ fn probe_failed(&mut self, _actual_path: &Path, _: u64) {}
- fn probe_successful(&mut self, _actual_path: &[&RouteHop]) {}
+ fn probe_successful(&mut self, _actual_path: &Path) {}
}
impl Drop for TestScorer {