Expose functional tests under _externalize_tests feature flag

Also, introduce TestSignerFactory, a factory for dynamic signers and ext-functional-test-demo crate for testing this machinery.
This commit is contained in:
Devrandom 2024-10-01 14:58:36 +02:00 committed by Devrandom
parent 17cd6e39fc
commit e41e7564ba
32 changed files with 559 additions and 490 deletions

1
.gitignore vendored
View file

@ -13,5 +13,6 @@ lightning-rapid-gossip-sync/res/full_graph.lngossip
lightning-custom-message/target lightning-custom-message/target
lightning-transaction-sync/target lightning-transaction-sync/target
lightning-dns-resolver/target lightning-dns-resolver/target
ext-functional-test-demo/target
no-std-check/target no-std-check/target
msrv-no-dev-deps-check/target msrv-no-dev-deps-check/target

View file

@ -21,6 +21,7 @@ members = [
exclude = [ exclude = [
"lightning-transaction-sync", "lightning-transaction-sync",
"ext-functional-test-demo",
"no-std-check", "no-std-check",
"msrv-no-dev-deps-check", "msrv-no-dev-deps-check",
"bench", "bench",

View file

@ -112,6 +112,13 @@ cargo check --verbose --color always
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
popd popd
echo -e "\n\Running functional tests from outside the workspace"
pushd ext-functional-test-demo
[ "$RUSTC_MINOR_VERSION" -lt 65 ] && cargo update -p regex --precise "1.9.6" --verbose
cargo test --color always
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
popd
# Test that we can build downstream code with only the "release pins". # Test that we can build downstream code with only the "release pins".
pushd msrv-no-dev-deps-check pushd msrv-no-dev-deps-check
PIN_RELEASE_DEPS PIN_RELEASE_DEPS

View file

@ -0,0 +1,7 @@
[package]
name = "ext-functional-tester"
version = "0.1.0"
edition = "2021"
[dependencies]
lightning = { path = "../lightning", features = ["_externalize_tests"] }

View file

@ -0,0 +1,31 @@
fn main() {
println!("{} tests were exported", lightning::get_xtests().len());
}
#[cfg(test)]
mod tests {
use lightning::util::dyn_signer::{DynKeysInterfaceTrait, DynSigner};
use lightning::util::test_utils::{TestSignerFactory, SIGNER_FACTORY};
use std::panic::catch_unwind;
use std::sync::Arc;
use std::time::Duration;
struct BrokenSignerFactory();
impl TestSignerFactory for BrokenSignerFactory {
fn make_signer(
&self, _seed: &[u8; 32], _now: Duration,
) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner = DynSigner>> {
panic!()
}
}
#[test]
fn test_functional() {
lightning::ln::functional_tests::test_insane_channel_opens();
lightning::ln::functional_tests::fake_network_test();
SIGNER_FACTORY.set(Arc::new(BrokenSignerFactory()));
catch_unwind(|| lightning::ln::functional_tests::fake_network_test()).unwrap_err();
}
}

View file

@ -79,6 +79,7 @@ use bitcoin::secp256k1::schnorr;
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey}; use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
use lightning::io::Cursor; use lightning::io::Cursor;
use lightning::util::dyn_signer::DynSigner;
use std::cmp::{self, Ordering}; use std::cmp::{self, Ordering};
use std::mem; use std::mem;
use std::sync::atomic; use std::sync::atomic;
@ -375,6 +376,7 @@ impl SignerProvider for KeyProvider {
channel_keys_id, channel_keys_id,
); );
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed); let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
let keys = DynSigner::new(keys);
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false) TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
} }

View file

@ -75,6 +75,7 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::schnorr; use bitcoin::secp256k1::schnorr;
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey}; use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
use lightning::util::dyn_signer::DynSigner;
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp; use std::cmp;
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
@ -439,7 +440,7 @@ impl SignerProvider for KeyProvider {
let ctr = channel_keys_id[0]; let ctr = channel_keys_id[0];
let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone(); let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone();
TestChannelSigner::new_with_revoked( TestChannelSigner::new_with_revoked(
if inbound { DynSigner::new(if inbound {
InMemorySigner::new( InMemorySigner::new(
&secp_ctx, &secp_ctx,
SecretKey::from_slice(&[ SecretKey::from_slice(&[
@ -509,7 +510,7 @@ impl SignerProvider for KeyProvider {
channel_keys_id, channel_keys_id,
channel_keys_id, channel_keys_id,
) )
}, }),
state, state,
false, false,
) )

View file

@ -2550,6 +2550,8 @@ mod tests {
failure: PathFailure::OnPath { network_update: None }, failure: PathFailure::OnPath { network_update: None },
path: path.clone(), path: path.clone(),
short_channel_id: Some(scored_scid), short_channel_id: Some(scored_scid),
error_code: None,
error_data: None,
}); });
let event = $receive.expect("PaymentPathFailed not handled within deadline"); let event = $receive.expect("PaymentPathFailed not handled within deadline");
match event { match event {
@ -2567,6 +2569,8 @@ mod tests {
failure: PathFailure::OnPath { network_update: None }, failure: PathFailure::OnPath { network_update: None },
path: path.clone(), path: path.clone(),
short_channel_id: None, short_channel_id: None,
error_code: None,
error_data: None,
}); });
let event = $receive.expect("PaymentPathFailed not handled within deadline"); let event = $receive.expect("PaymentPathFailed not handled within deadline");
match event { match event {

View file

@ -306,7 +306,7 @@ pub fn drop_legacy_field_definition(expr: TokenStream) -> TokenStream {
/// ///
/// fn f1() {} /// fn f1() {}
/// ///
/// #[xtest(feature = "_test_utils")] /// #[xtest(feature = "_externalize_tests")]
/// pub fn test_f1() { /// pub fn test_f1() {
/// f1(); /// f1();
/// } /// }

View file

@ -18,7 +18,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[features] [features]
# Internal test utilities exposed to other repo crates # Internal test utilities exposed to other repo crates
_test_utils = ["regex", "bitcoin/bitcoinconsensus", "lightning-types/_test_utils"] _test_utils = ["regex", "bitcoin/bitcoinconsensus", "lightning-types/_test_utils"]
_externalize_tests = ["inventory", "_test_utils"]
# Allow signing of local transactions that may have been revoked or will be revoked, for functional testing (e.g. justice tx handling). # Allow signing of local transactions that may have been revoked or will be revoked, for functional testing (e.g. justice tx handling).
# This is unsafe to use in production because it may result in the counterparty publishing taking our funds. # This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
unsafe_revoked_tx_signing = [] unsafe_revoked_tx_signing = []
@ -48,10 +48,12 @@ regex = { version = "1.5.6", optional = true }
backtrace = { version = "0.3", optional = true } backtrace = { version = "0.3", optional = true }
libm = { version = "0.2", default-features = false } libm = { version = "0.2", default-features = false }
inventory = { version = "0.3", optional = true }
[dev-dependencies] [dev-dependencies]
regex = "1.5.6" regex = "1.5.6"
lightning-types = { version = "0.3.0", path = "../lightning-types", features = ["_test_utils"] } lightning-types = { version = "0.3.0", path = "../lightning-types", features = ["_test_utils"] }
lightning-macros = { path = "../lightning-macros" }
[dev-dependencies.bitcoin] [dev-dependencies.bitcoin]
version = "0.32.2" version = "0.32.2"

View file

@ -469,7 +469,7 @@ where C::Target: chain::Filter,
} }
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub fn remove_monitor(&self, channel_id: &ChannelId) -> ChannelMonitor<ChannelSigner> { pub fn remove_monitor(&self, channel_id: &ChannelId) -> ChannelMonitor<ChannelSigner> {
self.monitors.write().unwrap().remove(channel_id).unwrap().monitor self.monitors.write().unwrap().remove(channel_id).unwrap().monitor
} }

View file

@ -854,10 +854,7 @@ impl Readable for IrrevocablyResolvedHTLC {
/// returned block hash and the the current chain and then reconnecting blocks to get to the /// returned block hash and the the current chain and then reconnecting blocks to get to the
/// best chain) upon deserializing the object! /// best chain) upon deserializing the object!
pub struct ChannelMonitor<Signer: EcdsaChannelSigner> { pub struct ChannelMonitor<Signer: EcdsaChannelSigner> {
#[cfg(test)]
pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>, pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
#[cfg(not(test))]
pub(super) inner: Mutex<ChannelMonitorImpl<Signer>>,
} }
impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone { impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone {
@ -965,9 +962,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
// Obviously Correct (tm) if we just keep track of them explicitly. // Obviously Correct (tm) if we just keep track of them explicitly.
outputs_to_watch: HashMap<Txid, Vec<(u32, ScriptBuf)>>, outputs_to_watch: HashMap<Txid, Vec<(u32, ScriptBuf)>>,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub onchain_tx_handler: OnchainTxHandler<Signer>, pub onchain_tx_handler: OnchainTxHandler<Signer>,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
onchain_tx_handler: OnchainTxHandler<Signer>, onchain_tx_handler: OnchainTxHandler<Signer>,
// This is set when the Channel[Manager] generated a ChannelMonitorUpdate which indicated the // This is set when the Channel[Manager] generated a ChannelMonitorUpdate which indicated the
@ -1818,7 +1815,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
/// Unsafe test-only version of `broadcast_latest_holder_commitment_txn` used by our test framework /// Unsafe test-only version of `broadcast_latest_holder_commitment_txn` used by our test framework
/// to bypass HolderCommitmentTransaction state update lockdown after signature and generate /// to bypass HolderCommitmentTransaction state update lockdown after signature and generate
/// revoked commitment transaction. /// revoked commitment transaction.
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] #[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
pub fn unsafe_get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction> pub fn unsafe_get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction>
where L::Target: Logger { where L::Target: Logger {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
@ -2132,7 +2129,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
self.inner.lock().unwrap().counterparty_payment_script = script; self.inner.lock().unwrap().counterparty_payment_script = script;
} }
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub fn do_mut_signer_call<F: FnMut(&mut Signer) -> ()>(&self, mut f: F) { pub fn do_mut_signer_call<F: FnMut(&mut Signer) -> ()>(&self, mut f: F) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
f(&mut inner.onchain_tx_handler.signer); f(&mut inner.onchain_tx_handler.signer);
@ -2773,7 +2770,7 @@ macro_rules! fail_unbroadcast_htlcs {
// witness length match (ie is 136 bytes long). We generate one here which we also use in some // witness length match (ie is 136 bytes long). We generate one here which we also use in some
// in-line tests later. // in-line tests later.
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec<u8> { pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec<u8> {
use bitcoin::opcodes; use bitcoin::opcodes;
let mut ret = [opcodes::all::OP_NOP.to_u8(); 136]; let mut ret = [opcodes::all::OP_NOP.to_u8(); 136];
@ -2785,7 +2782,7 @@ pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec<u8> {
Vec::from(&ret[..]) Vec::from(&ret[..])
} }
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub fn deliberately_bogus_accepted_htlc_witness() -> Vec<Vec<u8>> { pub fn deliberately_bogus_accepted_htlc_witness() -> Vec<Vec<u8>> {
vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into() vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into()
} }
@ -3947,7 +3944,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
} }
} }
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] #[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
/// Note that this includes possibly-locktimed-in-the-future transactions! /// Note that this includes possibly-locktimed-in-the-future transactions!
fn unsafe_get_latest_holder_commitment_txn<L: Deref>( fn unsafe_get_latest_holder_commitment_txn<L: Deref>(
&mut self, logger: &WithChannelMonitor<L> &mut self, logger: &WithChannelMonitor<L>
@ -5289,7 +5286,7 @@ mod tests {
nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header, nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header,
&[(0, broadcast_tx)], conf_height); &[(0, broadcast_tx)], conf_height);
let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<InMemorySigner>)>::read( let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<_>)>::read(
&mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()), &mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()),
(&nodes[1].keys_manager.backing, &nodes[1].keys_manager.backing)).unwrap(); (&nodes[1].keys_manager.backing, &nodes[1].keys_manager.backing)).unwrap();

View file

@ -250,9 +250,9 @@ pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
// Key is identifier of the pending claim request, i.e the txid of the initial claiming transaction generated by // Key is identifier of the pending claim request, i.e the txid of the initial claiming transaction generated by
// us and is immutable until all outpoint of the claimable set are post-anti-reorg-delay solved. // us and is immutable until all outpoint of the claimable set are post-anti-reorg-delay solved.
// Entry is cache of elements need to generate a bumped claiming transaction (see ClaimTxBumpMaterial) // Entry is cache of elements need to generate a bumped claiming transaction (see ClaimTxBumpMaterial)
#[cfg(test)] // Used in functional_test to verify sanitization #[cfg(any(test, feature = "_test_utils"))]
pub(crate) pending_claim_requests: HashMap<ClaimId, PackageTemplate>, pub(crate) pending_claim_requests: HashMap<ClaimId, PackageTemplate>,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
pending_claim_requests: HashMap<ClaimId, PackageTemplate>, pending_claim_requests: HashMap<ClaimId, PackageTemplate>,
// Used to track external events that need to be forwarded to the `ChainMonitor`. This `Vec` // Used to track external events that need to be forwarded to the `ChainMonitor`. This `Vec`
@ -273,9 +273,9 @@ pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
// block height, and are immutable until the outpoint has enough confirmations to meet our // block height, and are immutable until the outpoint has enough confirmations to meet our
// [`ANTI_REORG_DELAY`]. The initial confirmation block height is used to remove the entry if // [`ANTI_REORG_DELAY`]. The initial confirmation block height is used to remove the entry if
// the block gets disconnected. // the block gets disconnected.
#[cfg(test)] // Used in functional_test to verify sanitization #[cfg(any(test, feature = "_test_utils"))]
pub claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>, pub(crate) claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>, claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>,
locktimed_packages: BTreeMap<u32, Vec<PackageTemplate>>, locktimed_packages: BTreeMap<u32, Vec<PackageTemplate>>,
@ -1193,7 +1193,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
MaybeSignedTransaction(tx) MaybeSignedTransaction(tx)
} }
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))] #[cfg(any(test, feature="_test_utils", feature="unsafe_revoked_tx_signing"))]
pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction { pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {
let sig = self.signer.unsafe_sign_holder_commitment(&self.channel_transaction_parameters, &self.holder_commitment, &self.secp_ctx).expect("sign holder commitment"); let sig = self.signer.unsafe_sign_holder_commitment(&self.channel_transaction_parameters, &self.holder_commitment, &self.secp_ctx).expect("sign holder commitment");
self.holder_commitment.add_holder_sig(funding_redeemscript, sig) self.holder_commitment.add_holder_sig(funding_redeemscript, sig)

View file

@ -105,10 +105,10 @@ pub(crate) fn verify_channel_type_features(channel_type_features: &Option<Channe
// number_of_witness_elements + sig_length + revocation_sig + true_length + op_true + witness_script_length + witness_script // number_of_witness_elements + sig_length + revocation_sig + true_length + op_true + witness_script_length + witness_script
pub(crate) const WEIGHT_REVOKED_OUTPUT: u64 = 1 + 1 + 73 + 1 + 1 + 1 + 77; pub(crate) const WEIGHT_REVOKED_OUTPUT: u64 = 1 + 1 + 73 + 1 + 1 + 1 + 77;
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
/// Height delay at which transactions are fee-bumped/rebroadcasted with a low priority. /// Height delay at which transactions are fee-bumped/rebroadcasted with a low priority.
const LOW_FREQUENCY_BUMP_INTERVAL: u32 = 15; const LOW_FREQUENCY_BUMP_INTERVAL: u32 = 15;
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
/// Height delay at which transactions are fee-bumped/rebroadcasted with a low priority. /// Height delay at which transactions are fee-bumped/rebroadcasted with a low priority.
pub(crate) const LOW_FREQUENCY_BUMP_INTERVAL: u32 = 15; pub(crate) const LOW_FREQUENCY_BUMP_INTERVAL: u32 = 15;

View file

@ -1054,9 +1054,9 @@ pub enum Event {
/// If this is `Some`, then the corresponding channel should be avoided when the payment is /// If this is `Some`, then the corresponding channel should be avoided when the payment is
/// retried. May be `None` for older [`Event`] serializations. /// retried. May be `None` for older [`Event`] serializations.
short_channel_id: Option<u64>, short_channel_id: Option<u64>,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_code: Option<u16>, error_code: Option<u16>,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_data: Option<Vec<u8>>, error_data: Option<Vec<u8>>,
}, },
/// Indicates that a probe payment we sent returned successful, i.e., only failed at the destination. /// Indicates that a probe payment we sent returned successful, i.e., only failed at the destination.
@ -1569,15 +1569,15 @@ impl Writeable for Event {
&Event::PaymentPathFailed { &Event::PaymentPathFailed {
ref payment_id, ref payment_hash, ref payment_failed_permanently, ref failure, ref payment_id, ref payment_hash, ref payment_failed_permanently, ref failure,
ref path, ref short_channel_id, ref path, ref short_channel_id,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
ref error_code, ref error_code,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
ref error_data, ref error_data,
} => { } => {
3u8.write(writer)?; 3u8.write(writer)?;
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_code.write(writer)?; error_code.write(writer)?;
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_data.write(writer)?; error_data.write(writer)?;
write_tlv_fields!(writer, { write_tlv_fields!(writer, {
(0, payment_hash, required), (0, payment_hash, required),
@ -1920,9 +1920,9 @@ impl MaybeReadable for Event {
}, },
3u8 => { 3u8 => {
let mut f = || { let mut f = || {
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
let error_code = Readable::read(reader)?; let error_code = Readable::read(reader)?;
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
let error_data = Readable::read(reader)?; let error_data = Readable::read(reader)?;
let mut payment_hash = PaymentHash([0; 32]); let mut payment_hash = PaymentHash([0; 32]);
let mut payment_failed_permanently = false; let mut payment_failed_permanently = false;
@ -1952,9 +1952,9 @@ impl MaybeReadable for Event {
failure, failure,
path: Path { hops: path.unwrap(), blinded_tail }, path: Path { hops: path.unwrap(), blinded_tail },
short_channel_id, short_channel_id,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_code, error_code,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_data, error_data,
})) }))
}; };
@ -2364,7 +2364,7 @@ impl MaybeReadable for Event {
/// broadcast to most peers). /// broadcast to most peers).
/// These events are handled by PeerManager::process_events if you are using a PeerManager. /// These events are handled by PeerManager::process_events if you are using a PeerManager.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(any(test, feature = "_test_utils"), derive(PartialEq))]
pub enum MessageSendEvent { pub enum MessageSendEvent {
/// Used to indicate that we've accepted a channel open and should send the accept_channel /// Used to indicate that we've accepted a channel open and should send the accept_channel
/// message provided to the given peer. /// message provided to the given peer.

View file

@ -142,3 +142,6 @@ mod prelude {
extern crate backtrace; extern crate backtrace;
mod sync; mod sync;
#[cfg(feature = "_externalize_tests")]
lightning_macros::xtest_inventory!();

View file

@ -88,6 +88,7 @@ fn params_from_invoice(
mod tests { mod tests {
use super::*; use super::*;
use crate::routing::router::Payee; use crate::routing::router::Payee;
use crate::sign::{NodeSigner, Recipient};
use crate::types::payment::PaymentSecret; use crate::types::payment::PaymentSecret;
use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
@ -178,8 +179,6 @@ mod tests {
let (payment_hash, payment_secret) = let (payment_hash, payment_secret) =
nodes[1].node.create_inbound_payment(None, 7200, None).unwrap(); nodes[1].node.create_inbound_payment(None, 7200, None).unwrap();
let secp_ctx = Secp256k1::new();
let node_secret = nodes[1].keys_manager.backing.get_node_secret_key();
let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let invoice = InvoiceBuilder::new(Currency::Bitcoin) let invoice = InvoiceBuilder::new(Currency::Bitcoin)
.description("test".into()) .description("test".into())
@ -189,8 +188,11 @@ mod tests {
.min_final_cltv_expiry_delta(144) .min_final_cltv_expiry_delta(144)
.amount_milli_satoshis(50_000) .amount_milli_satoshis(50_000)
.payment_metadata(payment_metadata.clone()) .payment_metadata(payment_metadata.clone())
.build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &node_secret)) .build_raw()
.unwrap(); .unwrap();
let sig = nodes[1].keys_manager.backing.sign_invoice(&invoice, Recipient::Node).unwrap();
let invoice = invoice.sign::<_, ()>(|_| Ok(sig)).unwrap();
let invoice = Bolt11Invoice::from_signed(invoice).unwrap();
let (hash, onion, params) = payment_parameters_from_invoice(&invoice).unwrap(); let (hash, onion, params) = payment_parameters_from_invoice(&invoice).unwrap();
nodes[0] nodes[0]

View file

@ -176,9 +176,9 @@ impl HTLCClaim {
} }
} }
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 { pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 {

View file

@ -75,7 +75,8 @@ use crate::sign::type_resolver::ChannelSignerType;
use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint}; use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint};
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
#[allow(unused)]
pub struct ChannelValueStat { pub struct ChannelValueStat {
pub value_to_self_msat: u64, pub value_to_self_msat: u64,
pub channel_value_msat: u64, pub channel_value_msat: u64,
@ -1112,9 +1113,9 @@ impl HolderCommitmentPoint {
/// the channel. Sadly, there isn't really a good number for this - if we expect to have no new /// the channel. Sadly, there isn't really a good number for this - if we expect to have no new
/// HTLCs for days we may need this to suffice for feerate increases across days, but that may /// HTLCs for days we may need this to suffice for feerate increases across days, but that may
/// leave the channel less usable as we hold a bigger reserve. /// leave the channel less usable as we hold a bigger reserve.
#[cfg(any(fuzzing, test))] #[cfg(any(fuzzing, test, feature = "_test_utils"))]
pub const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2; pub const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2;
#[cfg(not(any(fuzzing, test)))] #[cfg(not(any(fuzzing, test, feature = "_test_utils")))]
const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2; const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2;
/// If we fail to see a funding transaction confirmed on-chain within this many blocks after the /// If we fail to see a funding transaction confirmed on-chain within this many blocks after the
@ -1220,7 +1221,7 @@ impl<SP: Deref> Channel<SP> where
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub fn funding_mut(&mut self) -> &mut FundingScope { pub fn funding_mut(&mut self) -> &mut FundingScope {
match &mut self.phase { match &mut self.phase {
ChannelPhase::Undefined => unreachable!(), ChannelPhase::Undefined => unreachable!(),
@ -1279,7 +1280,7 @@ impl<SP: Deref> Channel<SP> where
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub fn is_unfunded_v1(&self) -> bool { pub fn is_unfunded_v1(&self) -> bool {
matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_)) matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_))
} }
@ -1628,9 +1629,9 @@ pub(super) struct FundingScope {
/// minimum channel reserve for self to maintain - set by them. /// minimum channel reserve for self to maintain - set by them.
counterparty_selected_channel_reserve_satoshis: Option<u64>, counterparty_selected_channel_reserve_satoshis: Option<u64>,
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(super) holder_selected_channel_reserve_satoshis: u64, pub(super) holder_selected_channel_reserve_satoshis: u64,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_externalize_tests")))]
holder_selected_channel_reserve_satoshis: u64, holder_selected_channel_reserve_satoshis: u64,
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -1851,9 +1852,9 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
/// The minimum and maximum absolute fee, in satoshis, we are willing to place on the closing /// The minimum and maximum absolute fee, in satoshis, we are willing to place on the closing
/// transaction. These are set once we reach `closing_negotiation_ready`. /// transaction. These are set once we reach `closing_negotiation_ready`.
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(crate) closing_fee_limits: Option<(u64, u64)>, pub(crate) closing_fee_limits: Option<(u64, u64)>,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
closing_fee_limits: Option<(u64, u64)>, closing_fee_limits: Option<(u64, u64)>,
/// If we remove an HTLC (or fee update), commit, and receive our counterparty's /// If we remove an HTLC (or fee update), commit, and receive our counterparty's
@ -1880,26 +1881,26 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
counterparty_dust_limit_satoshis: u64, counterparty_dust_limit_satoshis: u64,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(super) holder_dust_limit_satoshis: u64, pub(crate) holder_dust_limit_satoshis: u64,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
holder_dust_limit_satoshis: u64, holder_dust_limit_satoshis: u64,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(super) counterparty_max_htlc_value_in_flight_msat: u64, pub(crate) counterparty_max_htlc_value_in_flight_msat: u64,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
counterparty_max_htlc_value_in_flight_msat: u64, counterparty_max_htlc_value_in_flight_msat: u64,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(super) holder_max_htlc_value_in_flight_msat: u64, pub(super) holder_max_htlc_value_in_flight_msat: u64,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
holder_max_htlc_value_in_flight_msat: u64, holder_max_htlc_value_in_flight_msat: u64,
counterparty_htlc_minimum_msat: u64, counterparty_htlc_minimum_msat: u64,
holder_htlc_minimum_msat: u64, holder_htlc_minimum_msat: u64,
#[cfg(test)] #[cfg(any(test, feature="_test_utils"))]
pub counterparty_max_accepted_htlcs: u16, pub counterparty_max_accepted_htlcs: u16,
#[cfg(not(test))] #[cfg(not(any(test, feature="_test_utils")))]
counterparty_max_accepted_htlcs: u16, counterparty_max_accepted_htlcs: u16,
holder_max_accepted_htlcs: u16, holder_max_accepted_htlcs: u16,
minimum_depth: Option<u32>, minimum_depth: Option<u32>,
@ -1987,9 +1988,9 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
/// The unique identifier used to re-derive the private key material for the channel through /// The unique identifier used to re-derive the private key material for the channel through
/// [`SignerProvider::derive_channel_signer`]. /// [`SignerProvider::derive_channel_signer`].
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
channel_keys_id: [u8; 32], channel_keys_id: [u8; 32],
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub channel_keys_id: [u8; 32], pub channel_keys_id: [u8; 32],
/// If we can't release a [`ChannelMonitorUpdate`] until some external action completes, we /// If we can't release a [`ChannelMonitorUpdate`] until some external action completes, we
@ -3130,7 +3131,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
} }
/// Returns the holder signer for this channel. /// Returns the holder signer for this channel.
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub fn get_mut_signer(&mut self) -> &mut ChannelSignerType<SP> { pub fn get_mut_signer(&mut self) -> &mut ChannelSignerType<SP> {
return &mut self.holder_signer return &mut self.holder_signer
} }
@ -7616,12 +7617,12 @@ impl<SP: Deref> FundedChannel<SP> where
self.context.cur_counterparty_commitment_transaction_number + 2 self.context.cur_counterparty_commitment_transaction_number + 2
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub fn get_signer(&self) -> &ChannelSignerType<SP> { pub fn get_signer(&self) -> &ChannelSignerType<SP> {
&self.context.holder_signer &self.context.holder_signer
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub fn get_value_stat(&self) -> ChannelValueStat { pub fn get_value_stat(&self) -> ChannelValueStat {
ChannelValueStat { ChannelValueStat {
value_to_self_msat: self.funding.value_to_self_msat, value_to_self_msat: self.funding.value_to_self_msat,

View file

@ -56,7 +56,9 @@ use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelType
use crate::types::features::Bolt11InvoiceFeatures; use crate::types::features::Bolt11InvoiceFeatures;
#[cfg(trampoline)] #[cfg(trampoline)]
use crate::routing::gossip::NodeId; use crate::routing::gossip::NodeId;
use crate::routing::router::{BlindedTail, FixedRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, RouteParametersConfig, Router}; use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, RouteParameters, RouteParametersConfig, Router};
#[cfg(any(feature = "_test_utils", test))]
use crate::routing::router::{FixedRouter, Route};
use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundHTLCErr, NextPacketDetails}; use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundHTLCErr, NextPacketDetails};
use crate::ln::msgs; use crate::ln::msgs;
use crate::ln::onion_utils; use crate::ln::onion_utils;
@ -128,7 +130,7 @@ use core::ops::Deref;
use bitcoin::hex::impl_fmt_traits; use bitcoin::hex::impl_fmt_traits;
// Re-export this for use in the public API. // Re-export this for use in the public API.
pub use crate::ln::outbound_payment::{Bolt12PaymentError, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; pub use crate::ln::outbound_payment::{Bolt12PaymentError, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) use crate::ln::outbound_payment::PaymentSendFailure; pub(crate) use crate::ln::outbound_payment::PaymentSendFailure;
use crate::ln::script::ShutdownScript; use crate::ln::script::ShutdownScript;
@ -2458,9 +2460,10 @@ where
message_router: MR, message_router: MR,
/// See `ChannelManager` struct-level documentation for lock order requirements. /// See `ChannelManager` struct-level documentation for lock order requirements.
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(super) best_block: RwLock<BestBlock>, pub(super) best_block: RwLock<BestBlock>,
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
/// See `ChannelManager` struct-level documentation for lock order requirements.
best_block: RwLock<BestBlock>, best_block: RwLock<BestBlock>,
secp_ctx: Secp256k1<secp256k1::All>, secp_ctx: Secp256k1<secp256k1::All>,
@ -2542,10 +2545,10 @@ where
/// required to access the channel with the `counterparty_node_id`. /// required to access the channel with the `counterparty_node_id`.
/// ///
/// See `ChannelManager` struct-level documentation for lock order requirements. /// See `ChannelManager` struct-level documentation for lock order requirements.
#[cfg(not(test))] #[cfg(any(test, feature = "_test_utils"))]
outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>,
#[cfg(test)]
pub(crate) outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>, pub(crate) outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>,
#[cfg(not(any(test, feature = "_test_utils")))]
outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>,
/// SCIDs (and outbound SCID aliases) -> `counterparty_node_id`s and `channel_id`s. /// SCIDs (and outbound SCID aliases) -> `counterparty_node_id`s and `channel_id`s.
/// ///
@ -4563,7 +4566,7 @@ where
}) })
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) fn test_send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { pub(crate) fn test_send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
let _lck = self.total_consistency_lock.read().unwrap(); let _lck = self.total_consistency_lock.read().unwrap();
self.send_payment_along_path(SendAlongPathArgs { self.send_payment_along_path(SendAlongPathArgs {
@ -4667,6 +4670,7 @@ where
/// ///
/// LDK will not automatically retry this payment, though it may be manually re-sent after an /// LDK will not automatically retry this payment, though it may be manually re-sent after an
/// [`Event::PaymentFailed`] is generated. /// [`Event::PaymentFailed`] is generated.
#[cfg(any(test, feature = "_test_utils"))]
pub fn send_payment_with_route( pub fn send_payment_with_route(
&self, mut route: Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, &self, mut route: Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
payment_id: PaymentId payment_id: PaymentId
@ -4737,7 +4741,7 @@ where
&self.pending_events, |args| self.send_payment_along_path(args)) &self.pending_events, |args| self.send_payment_along_path(args))
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(super) fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> { pub(super) fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> {
let best_block_height = self.best_block.read().unwrap().height; let best_block_height = self.best_block.read().unwrap().height;
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
@ -4746,7 +4750,7 @@ where
best_block_height, |args| self.send_payment_along_path(args)) best_block_height, |args| self.send_payment_along_path(args))
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route) -> Result<Vec<[u8; 32]>, PaymentSendFailure> { pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route) -> Result<Vec<[u8; 32]>, PaymentSendFailure> {
let best_block_height = self.best_block.read().unwrap().height; let best_block_height = self.best_block.read().unwrap().height;
self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, recipient_onion, payment_id, route, None, &self.entropy_source, best_block_height) self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, recipient_onion, payment_id, route, None, &self.entropy_source, best_block_height)
@ -5204,7 +5208,7 @@ where
Ok(()) Ok(())
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> { pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> {
let txid = funding_transaction.compute_txid(); let txid = funding_transaction.compute_txid();
self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, false, |_| { self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, false, |_| {
@ -11406,7 +11410,7 @@ where
// Most of our tests were written when we only broadcasted // Most of our tests were written when we only broadcasted
// `channel_announcement`s once and then never re-broadcasted // `channel_announcement`s once and then never re-broadcasted
// them again, so disable the re-broadcasting entirely in tests // them again, so disable the re-broadcasting entirely in tests
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
{ {
should_announce = announcement_sigs.is_some(); should_announce = announcement_sigs.is_some();
} }

View file

@ -28,11 +28,9 @@ use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
use crate::routing::router::{self, PaymentParameters, Route, RouteParameters}; use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
use crate::sign::{EntropySource, RandomBytes}; use crate::sign::{EntropySource, RandomBytes};
use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::config::{MaxDustHTLCExposure, UserConfig};
#[cfg(test)]
use crate::util::logger::Logger; use crate::util::logger::Logger;
use crate::util::scid_utils; use crate::util::scid_utils;
use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_channel_signer::TestChannelSigner;
#[cfg(test)]
use crate::util::test_channel_signer::SignerOp; use crate::util::test_channel_signer::SignerOp;
use crate::util::test_utils; use crate::util::test_utils;
use crate::util::test_utils::{TestChainMonitor, TestScorer, TestKeysInterface}; use crate::util::test_utils::{TestChainMonitor, TestScorer, TestKeysInterface};
@ -515,8 +513,7 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
/// Toggles this node's signer to be available for the given signer operation. /// Toggles this node's signer to be available for the given signer operation.
/// This is useful for testing behavior for restoring an async signer that previously /// This is useful for testing behavior for restoring an async signer that previously
/// could not return a signature immediately. /// could not return a signature immediately.
#[cfg(test)] pub fn enable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) {
pub fn enable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) {
self.set_channel_signer_ops(peer_id, chan_id, signer_op, true); self.set_channel_signer_ops(peer_id, chan_id, signer_op, true);
} }
@ -535,8 +532,7 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
/// will behave normally, returning `Ok`. When set to `false`, and the channel signer will /// will behave normally, returning `Ok`. When set to `false`, and the channel signer will
/// act like an off-line remote signer, returning `Err`. This applies to the signer in all /// act like an off-line remote signer, returning `Err`. This applies to the signer in all
/// relevant places, i.e. the channel manager, chain monitor, and the keys manager. /// relevant places, i.e. the channel manager, chain monitor, and the keys manager.
#[cfg(test)] fn set_channel_signer_ops(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, available: bool) {
fn set_channel_signer_ops(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, available: bool) {
use crate::sign::ChannelSigner; use crate::sign::ChannelSigner;
log_debug!(self.logger, "Setting channel signer for {} as available={}", chan_id, available); log_debug!(self.logger, "Setting channel signer for {} as available={}", chan_id, available);
@ -1002,7 +998,7 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! get_channel_ref { macro_rules! get_channel_ref {
($node: expr, $counterparty_node: expr, $per_peer_state_lock: ident, $peer_state_lock: ident, $channel_id: expr) => { ($node: expr, $counterparty_node: expr, $per_peer_state_lock: ident, $peer_state_lock: ident, $channel_id: expr) => {
{ {
@ -1013,7 +1009,7 @@ macro_rules! get_channel_ref {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! get_feerate { macro_rules! get_feerate {
($node: expr, $counterparty_node: expr, $channel_id: expr) => { ($node: expr, $counterparty_node: expr, $channel_id: expr) => {
{ {
@ -1025,7 +1021,7 @@ macro_rules! get_feerate {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! get_channel_type_features { macro_rules! get_channel_type_features {
($node: expr, $counterparty_node: expr, $channel_id: expr) => { ($node: expr, $counterparty_node: expr, $channel_id: expr) => {
{ {
@ -1172,7 +1168,7 @@ pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: User
node_deserialized node_deserialized
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! reload_node { macro_rules! reload_node {
($node: expr, $new_config: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => { ($node: expr, $new_config: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => {
let chanman_encoded = $chanman_encoded; let chanman_encoded = $chanman_encoded;
@ -2011,7 +2007,7 @@ macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed {
}} }}
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! expect_pending_htlcs_forwardable_from_events { macro_rules! expect_pending_htlcs_forwardable_from_events {
($node: expr, $events: expr, $ignore: expr) => {{ ($node: expr, $events: expr, $ignore: expr) => {{
assert_eq!($events.len(), 1); assert_eq!($events.len(), 1);
@ -2209,7 +2205,6 @@ macro_rules! get_route {
}} }}
} }
#[cfg(test)]
#[macro_export] #[macro_export]
macro_rules! get_route_and_payment_hash { macro_rules! get_route_and_payment_hash {
($send_node: expr, $recv_node: expr, $recv_value: expr) => {{ ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
@ -2345,7 +2340,6 @@ macro_rules! expect_payment_sent {
} }
} }
#[cfg(test)]
#[macro_export] #[macro_export]
macro_rules! expect_payment_path_successful { macro_rules! expect_payment_path_successful {
($node: expr) => { ($node: expr) => {
@ -2433,7 +2427,6 @@ macro_rules! expect_payment_forwarded {
} }
} }
#[cfg(test)]
#[macro_export] #[macro_export]
macro_rules! expect_channel_shutdown_state { macro_rules! expect_channel_shutdown_state {
($node: expr, $chan_id: expr, $state: path) => { ($node: expr, $chan_id: expr, $state: path) => {
@ -2468,7 +2461,6 @@ pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, ex
} }
} }
#[cfg(any(test, feature = "_test_utils"))]
pub fn expect_probe_successful_events(node: &Node, mut probe_results: Vec<(PaymentHash, PaymentId)>) { pub fn expect_probe_successful_events(node: &Node, mut probe_results: Vec<(PaymentHash, PaymentId)>) {
let mut events = node.node.get_and_clear_pending_events(); let mut events = node.node.get_and_clear_pending_events();
@ -2528,7 +2520,7 @@ impl<'a> PaymentFailedConditions<'a> {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! expect_payment_failed_with_update { macro_rules! expect_payment_failed_with_update {
($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr, $scid: expr, $chan_closed: expr) => { ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr, $scid: expr, $chan_closed: expr) => {
$crate::ln::functional_test_utils::expect_payment_failed_conditions( $crate::ln::functional_test_utils::expect_payment_failed_conditions(
@ -2538,7 +2530,7 @@ macro_rules! expect_payment_failed_with_update {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! expect_payment_failed { macro_rules! expect_payment_failed {
($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => { ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => {
#[allow(unused_mut)] #[allow(unused_mut)]
@ -2557,14 +2549,11 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); } if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); }
let expected_payment_id = match &payment_failed_events[0] { let expected_payment_id = match &payment_failed_events[0] {
Event::PaymentPathFailed { payment_hash, payment_failed_permanently, payment_id, failure, Event::PaymentPathFailed { payment_hash, payment_failed_permanently, payment_id, failure,
#[cfg(test)] error_code,
error_code, error_data, .. } => {
#[cfg(test)]
error_data, .. } => {
assert_eq!(*payment_hash, expected_payment_hash, "unexpected payment_hash"); assert_eq!(*payment_hash, expected_payment_hash, "unexpected payment_hash");
assert_eq!(*payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value"); assert_eq!(*payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value");
#[cfg(test)] {
{
assert!(error_code.is_some(), "expected error_code.is_some() = true"); assert!(error_code.is_some(), "expected error_code.is_some() = true");
assert!(error_data.is_some(), "expected error_data.is_some() = true"); assert!(error_data.is_some(), "expected error_data.is_some() = true");
if let Some((code, data)) = conditions.expected_htlc_error_data { if let Some((code, data)) = conditions.expected_htlc_error_data {
@ -3627,7 +3616,7 @@ pub fn get_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec<Node<'a, 'b,
handle_announce_close_broadcast_events(nodes, a, b, false, "Channel closed because commitment or closing transaction was confirmed on chain."); handle_announce_close_broadcast_events(nodes, a, b, false, "Channel closed because commitment or closing transaction was confirmed on chain.");
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
macro_rules! get_channel_value_stat { macro_rules! get_channel_value_stat {
($node: expr, $counterparty_node: expr, $channel_id: expr) => {{ ($node: expr, $counterparty_node: expr, $channel_id: expr) => {{
let peer_state_lock = $node.node.per_peer_state.read().unwrap(); let peer_state_lock = $node.node.per_peer_state.read().unwrap();

File diff suppressed because it is too large Load diff

View file

@ -720,6 +720,7 @@ mod test {
use crate::util::test_utils; use crate::util::test_utils;
use crate::util::config::UserConfig; use crate::util::config::UserConfig;
use std::collections::HashSet; use std::collections::HashSet;
use crate::util::dyn_signer::{DynKeysInterface, DynPhantomKeysInterface};
#[test] #[test]
fn test_prefer_current_channel() { fn test_prefer_current_channel() {
@ -1239,6 +1240,13 @@ mod test {
do_test_multi_node_receive(false); do_test_multi_node_receive(false);
} }
fn make_dyn_keys_interface(seed: &[u8; 32]) -> DynKeysInterface {
let cross_node_seed = [44u8; 32];
let inner = PhantomKeysManager::new(&seed, 43, 44, &cross_node_seed);
let dyn_inner = DynPhantomKeysInterface::new(inner);
DynKeysInterface::new(Box::new(dyn_inner))
}
fn do_test_multi_node_receive(user_generated_pmt_hash: bool) { fn do_test_multi_node_receive(user_generated_pmt_hash: bool) {
use crate::events::{Event, EventsProvider}; use crate::events::{Event, EventsProvider};
use core::cell::RefCell; use core::cell::RefCell;
@ -1246,9 +1254,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(3); let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
@ -1350,9 +1357,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(3); let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
@ -1441,9 +1447,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(3); let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
@ -1469,9 +1474,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(4); let mut chanmon_cfgs = create_chanmon_cfgs(4);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[3].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs); let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
@ -1499,9 +1503,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(4); let mut chanmon_cfgs = create_chanmon_cfgs(4);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[3].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs); let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
@ -1556,9 +1559,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(3); let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
@ -1588,9 +1590,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(4); let mut chanmon_cfgs = create_chanmon_cfgs(4);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs); let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
@ -1621,9 +1622,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(3); let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
@ -1651,9 +1651,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(4); let mut chanmon_cfgs = create_chanmon_cfgs(4);
let seed_1 = [42u8; 32]; let seed_1 = [42u8; 32];
let seed_2 = [43u8; 32]; let seed_2 = [43u8; 32];
let cross_node_seed = [44u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs); let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
@ -1726,11 +1725,10 @@ mod test {
let seed_2 = [43 as u8; 32]; let seed_2 = [43 as u8; 32];
let seed_3 = [44 as u8; 32]; let seed_3 = [44 as u8; 32];
let seed_4 = [45 as u8; 32]; let seed_4 = [45 as u8; 32];
let cross_node_seed = [44 as u8; 32]; chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[3].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); chanmon_cfgs[4].keys_manager.backing = make_dyn_keys_interface(&seed_3);
chanmon_cfgs[4].keys_manager.backing = PhantomKeysManager::new(&seed_3, 43, 44, &cross_node_seed); chanmon_cfgs[4].keys_manager.backing = make_dyn_keys_interface(&seed_4);
chanmon_cfgs[5].keys_manager.backing = PhantomKeysManager::new(&seed_4, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(6, &chanmon_cfgs); let node_cfgs = create_node_cfgs(6, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(6, &node_cfgs, &[None, None, None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(6, &node_cfgs, &[None, None, None, None, None, None]);
let nodes = create_network(6, &node_cfgs, &node_chanmgrs); let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
@ -1783,9 +1781,8 @@ mod test {
let mut chanmon_cfgs = create_chanmon_cfgs(5); let mut chanmon_cfgs = create_chanmon_cfgs(5);
let seed_1 = [42 as u8; 32]; let seed_1 = [42 as u8; 32];
let seed_2 = [43 as u8; 32]; let seed_2 = [43 as u8; 32];
let cross_node_seed = [44 as u8; 32]; chanmon_cfgs[1].keys_manager.backing = make_dyn_keys_interface(&seed_1);
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); chanmon_cfgs[2].keys_manager.backing = make_dyn_keys_interface(&seed_2);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, None]); let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, None]);
let nodes = create_network(5, &node_cfgs, &node_chanmgrs); let nodes = create_network(5, &node_cfgs, &node_chanmgrs);

View file

@ -58,9 +58,9 @@ mod blinded_payment_tests;
#[cfg(all(test, async_payments))] #[cfg(all(test, async_payments))]
#[allow(unused_mut)] #[allow(unused_mut)]
mod async_payments_tests; mod async_payments_tests;
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
#[allow(unused_mut)] #[allow(unused_mut)]
mod functional_tests; pub mod functional_tests;
#[cfg(test)] #[cfg(test)]
#[allow(unused_mut)] #[allow(unused_mut)]
mod max_payment_path_len_tests; mod max_payment_path_len_tests;

View file

@ -2324,8 +2324,8 @@ fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Reset our RNG counters to mirror the RNG output from when this test was written. // Reset our RNG counters to mirror the RNG output from when this test was written.
nodes[0].keys_manager.backing.inner.entropy_source.set_counter(0x1_0000_0004); nodes[0].keys_manager.backing.inner.set_counter(0x1_0000_0004);
nodes[1].keys_manager.backing.inner.entropy_source.set_counter(0x1_0000_0004); nodes[1].keys_manager.backing.inner.set_counter(0x1_0000_0004);
// Open a channel, lock in an HTLC, and immediately broadcast the commitment transaction. This // Open a channel, lock in an HTLC, and immediately broadcast the commitment transaction. This
// ensures that the HTLC timeout package is held until we reach its expiration height. // ensures that the HTLC timeout package is held until we reach its expiration height.

View file

@ -925,9 +925,9 @@ pub(crate) struct DecodedOnionFailure {
pub(crate) short_channel_id: Option<u64>, pub(crate) short_channel_id: Option<u64>,
pub(crate) payment_failed_permanently: bool, pub(crate) payment_failed_permanently: bool,
pub(crate) failed_within_blinded_path: bool, pub(crate) failed_within_blinded_path: bool,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(crate) onion_error_code: Option<u16>, pub(crate) onion_error_code: Option<u16>,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
pub(crate) onion_error_data: Option<Vec<u8>>, pub(crate) onion_error_data: Option<Vec<u8>>,
} }
@ -1211,9 +1211,9 @@ where
short_channel_id, short_channel_id,
payment_failed_permanently, payment_failed_permanently,
failed_within_blinded_path, failed_within_blinded_path,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_code: error_code_ret, onion_error_code: error_code_ret,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_data: error_packet_ret, onion_error_data: error_packet_ret,
} }
} else { } else {
@ -1224,9 +1224,9 @@ where
short_channel_id: None, short_channel_id: None,
payment_failed_permanently: is_from_final_node, payment_failed_permanently: is_from_final_node,
failed_within_blinded_path: false, failed_within_blinded_path: false,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_code: None, onion_error_code: None,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_data: None, onion_error_data: None,
} }
} }
@ -1382,9 +1382,9 @@ impl HTLCFailReason {
payment_failed_permanently: false, payment_failed_permanently: false,
short_channel_id: Some(path.hops[0].short_channel_id), short_channel_id: Some(path.hops[0].short_channel_id),
failed_within_blinded_path: false, failed_within_blinded_path: false,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_code: Some(*failure_code), onion_error_code: Some(*failure_code),
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
onion_error_data: Some(data.clone()), onion_error_data: Some(data.clone()),
} }
} else { } else {

View file

@ -1546,9 +1546,9 @@ impl OutboundPayments {
failure: events::PathFailure::InitialSend { err: e }, failure: events::PathFailure::InitialSend { err: e },
path, path,
short_channel_id: failed_scid, short_channel_id: failed_scid,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_code: None, error_code: None,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_data: None, error_data: None,
}, None)); }, None));
} }
@ -1643,7 +1643,7 @@ impl OutboundPayments {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(super) fn test_add_new_pending_payment<ES: Deref>( pub(super) fn test_add_new_pending_payment<ES: Deref>(
&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId,
route: &Route, retry_strategy: Option<Retry>, entropy_source: &ES, best_block_height: u32 route: &Route, retry_strategy: Option<Retry>, entropy_source: &ES, best_block_height: u32
@ -1901,7 +1901,7 @@ impl OutboundPayments {
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(super) fn test_send_payment_internal<NS: Deref, F>( pub(super) fn test_send_payment_internal<NS: Deref, F>(
&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>, keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>,
@ -2099,12 +2099,12 @@ impl OutboundPayments {
probing_cookie_secret: [u8; 32], secp_ctx: &Secp256k1<secp256k1::All>, probing_cookie_secret: [u8; 32], secp_ctx: &Secp256k1<secp256k1::All>,
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, logger: &L, pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, logger: &L,
) -> bool where L::Target: Logger { ) -> bool where L::Target: Logger {
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
let DecodedOnionFailure { let DecodedOnionFailure {
network_update, short_channel_id, payment_failed_permanently, onion_error_code, network_update, short_channel_id, payment_failed_permanently, onion_error_code,
onion_error_data, failed_within_blinded_path onion_error_data, failed_within_blinded_path
} = onion_error.decode_onion_failure(secp_ctx, logger, &source); } = onion_error.decode_onion_failure(secp_ctx, logger, &source);
#[cfg(not(test))] #[cfg(not(any(test, feature = "_test_utils")))]
let DecodedOnionFailure { let DecodedOnionFailure {
network_update, short_channel_id, payment_failed_permanently, failed_within_blinded_path network_update, short_channel_id, payment_failed_permanently, failed_within_blinded_path
} = onion_error.decode_onion_failure(secp_ctx, logger, &source); } = onion_error.decode_onion_failure(secp_ctx, logger, &source);
@ -2212,9 +2212,9 @@ impl OutboundPayments {
failure: events::PathFailure::OnPath { network_update }, failure: events::PathFailure::OnPath { network_update },
path: path.clone(), path: path.clone(),
short_channel_id, short_channel_id,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_code: onion_error_code, error_code: onion_error_code,
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
error_data: onion_error_data error_data: onion_error_data
} }
} }

View file

@ -47,7 +47,7 @@ impl<T> TestEq for T {}
/// variant contains a message from [`msgs`] or otherwise the message type if unknown. /// variant contains a message from [`msgs`] or otherwise the message type if unknown.
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(any(test, feature = "_test_utils"), derive(PartialEq))]
pub(crate) enum Message<T: core::fmt::Debug + Type + TestEq> { pub(crate) enum Message<T: core::fmt::Debug + Type + TestEq> {
Init(msgs::Init), Init(msgs::Init),
Error(msgs::ErrorMessage), Error(msgs::ErrorMessage),

View file

@ -1293,7 +1293,7 @@ where
} }
} }
#[cfg(test)] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) fn set_offers_handler(&mut self, offers_handler: OMH) { pub(crate) fn set_offers_handler(&mut self, offers_handler: OMH) {
self.offers_handler = offers_handler; self.offers_handler = offers_handler;
} }

View file

@ -25,6 +25,7 @@ use crate::offers::invoice::Bolt12Invoice;
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId}; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId};
use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
use crate::sign::EntropySource; use crate::sign::EntropySource;
#[cfg(any(test, feature = "_test_utils"))]
use crate::sync::Mutex; use crate::sync::Mutex;
use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer};
use crate::util::logger::Logger; use crate::util::logger::Logger;
@ -189,17 +190,20 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref, SP: Size
/// A `Router` that returns a fixed route one time, erroring otherwise. Useful for /// A `Router` that returns a fixed route one time, erroring otherwise. Useful for
/// `ChannelManager::send_payment_with_route` to support sending to specific routes without /// `ChannelManager::send_payment_with_route` to support sending to specific routes without
/// requiring a custom `Router` implementation. /// requiring a custom `Router` implementation.
#[cfg(any(test, feature = "_test_utils"))]
pub(crate) struct FixedRouter { pub(crate) struct FixedRouter {
// Use an `Option` to avoid needing to clone the route when `find_route` is called. // Use an `Option` to avoid needing to clone the route when `find_route` is called.
route: Mutex<Option<Route>>, route: Mutex<Option<Route>>,
} }
#[cfg(any(test, feature = "_test_utils"))]
impl FixedRouter { impl FixedRouter {
pub(crate) fn new(route: Route) -> Self { pub(crate) fn new(route: Route) -> Self {
Self { route: Mutex::new(Some(route)) } Self { route: Mutex::new(Some(route)) }
} }
} }
#[cfg(any(test, feature = "_test_utils"))]
impl Router for FixedRouter { impl Router for FixedRouter {
fn find_route( fn find_route(
&self, _payer: &PublicKey, _route_params: &RouteParameters, &self, _payer: &PublicKey, _route_params: &RouteParameters,

View file

@ -15,7 +15,7 @@ use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSH
use crate::ln::channel_keys::HtlcKey; use crate::ln::channel_keys::HtlcKey;
use crate::ln::msgs; use crate::ln::msgs;
use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sign::ecdsa::EcdsaChannelSigner;
use crate::sign::{ChannelSigner, InMemorySigner}; use crate::sign::ChannelSigner;
use crate::types::payment::PaymentPreimage; use crate::types::payment::PaymentPreimage;
#[allow(unused_imports)] #[allow(unused_imports)]
@ -36,6 +36,7 @@ use crate::ln::msgs::PartialSignatureWithNonce;
#[cfg(taproot)] #[cfg(taproot)]
use crate::sign::taproot::TaprootChannelSigner; use crate::sign::taproot::TaprootChannelSigner;
use crate::sign::HTLCDescriptor; use crate::sign::HTLCDescriptor;
use crate::util::dyn_signer::DynSigner;
use bitcoin::secp256k1; use bitcoin::secp256k1;
#[cfg(taproot)] #[cfg(taproot)]
use bitcoin::secp256k1::All; use bitcoin::secp256k1::All;
@ -68,7 +69,7 @@ pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48;
/// forwards-compatibility prefix/suffixes! /// forwards-compatibility prefix/suffixes!
#[derive(Clone)] #[derive(Clone)]
pub struct TestChannelSigner { pub struct TestChannelSigner {
pub inner: InMemorySigner, pub inner: DynSigner,
/// Channel state used for policy enforcement /// Channel state used for policy enforcement
pub state: Arc<Mutex<EnforcementState>>, pub state: Arc<Mutex<EnforcementState>>,
pub disable_revocation_policy_check: bool, pub disable_revocation_policy_check: bool,
@ -119,7 +120,7 @@ impl PartialEq for TestChannelSigner {
impl TestChannelSigner { impl TestChannelSigner {
/// Construct an TestChannelSigner /// Construct an TestChannelSigner
pub fn new(inner: InMemorySigner) -> Self { pub fn new(inner: DynSigner) -> Self {
let state = Arc::new(Mutex::new(EnforcementState::new())); let state = Arc::new(Mutex::new(EnforcementState::new()));
Self { inner, state, disable_revocation_policy_check: false } Self { inner, state, disable_revocation_policy_check: false }
} }
@ -130,7 +131,7 @@ impl TestChannelSigner {
/// so that all copies are aware of enforcement state. A pointer to this state is provided /// so that all copies are aware of enforcement state. A pointer to this state is provided
/// here, usually by an implementation of KeysInterface. /// here, usually by an implementation of KeysInterface.
pub fn new_with_revoked( pub fn new_with_revoked(
inner: InMemorySigner, state: Arc<Mutex<EnforcementState>>, inner: DynSigner, state: Arc<Mutex<EnforcementState>>,
disable_revocation_policy_check: bool, disable_revocation_policy_check: bool,
) -> Self { ) -> Self {
Self { inner, state, disable_revocation_policy_check } Self { inner, state, disable_revocation_policy_check }

View file

@ -13,7 +13,7 @@ use crate::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
use crate::chain; use crate::chain;
use crate::chain::chaininterface; use crate::chain::chaininterface;
use crate::chain::chaininterface::ConfirmationTarget; use crate::chain::chaininterface::ConfirmationTarget;
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW; use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
use crate::chain::chainmonitor::{ChainMonitor, Persist}; use crate::chain::chainmonitor::{ChainMonitor, Persist};
use crate::chain::channelmonitor::{ use crate::chain::channelmonitor::{
@ -23,7 +23,7 @@ use crate::chain::transaction::OutPoint;
use crate::chain::WatchedOutput; use crate::chain::WatchedOutput;
use crate::events; use crate::events;
use crate::events::bump_transaction::{Utxo, WalletSource}; use crate::events::bump_transaction::{Utxo, WalletSource};
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
use crate::ln::chan_utils::CommitmentTransaction; use crate::ln::chan_utils::CommitmentTransaction;
use crate::ln::channel_state::ChannelDetails; use crate::ln::channel_state::ChannelDetails;
use crate::ln::channelmanager; use crate::ln::channelmanager;
@ -50,13 +50,15 @@ use crate::sign::ChannelSigner;
use crate::sync::RwLock; use crate::sync::RwLock;
use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::util::config::UserConfig; use crate::util::config::UserConfig;
use crate::util::dyn_signer::{
DynKeysInterface, DynKeysInterfaceTrait, DynPhantomKeysInterface, DynSigner,
};
use crate::util::logger::{Logger, Record}; use crate::util::logger::{Logger, Record};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::util::mut_global::MutGlobal; use crate::util::mut_global::MutGlobal;
use crate::util::persist::{KVStore, MonitorName}; use crate::util::persist::{KVStore, MonitorName};
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use crate::util::test_channel_signer::{EnforcementState, TestChannelSigner}; use crate::util::test_channel_signer::{EnforcementState, TestChannelSigner};
use crate::util::dyn_signer::{DynPhantomKeysInterface, DynSigner, DynKeysInterfaceTrait};
use bitcoin::amount::Amount; use bitcoin::amount::Amount;
use bitcoin::block::Block; use bitcoin::block::Block;
@ -509,14 +511,14 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
} }
} }
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
struct JusticeTxData { struct JusticeTxData {
justice_tx: Transaction, justice_tx: Transaction,
value: Amount, value: Amount,
commitment_number: u64, commitment_number: u64,
} }
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
pub(crate) struct WatchtowerPersister { pub(crate) struct WatchtowerPersister {
persister: TestPersister, persister: TestPersister,
/// Upon a new commitment_signed, we'll get a /// Upon a new commitment_signed, we'll get a
@ -530,7 +532,7 @@ pub(crate) struct WatchtowerPersister {
destination_script: ScriptBuf, destination_script: ScriptBuf,
} }
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
impl WatchtowerPersister { impl WatchtowerPersister {
pub(crate) fn new(destination_script: ScriptBuf) -> Self { pub(crate) fn new(destination_script: ScriptBuf) -> Self {
let unsigned_justice_tx_data = Mutex::new(new_hash_map()); let unsigned_justice_tx_data = Mutex::new(new_hash_map());
@ -573,7 +575,7 @@ impl WatchtowerPersister {
} }
} }
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_externalize_tests"))]
impl<Signer: sign::ecdsa::EcdsaChannelSigner> Persist<Signer> for WatchtowerPersister { impl<Signer: sign::ecdsa::EcdsaChannelSigner> Persist<Signer> for WatchtowerPersister {
fn persist_new_channel( fn persist_new_channel(
&self, monitor_name: MonitorName, data: &ChannelMonitor<Signer>, &self, monitor_name: MonitorName, data: &ChannelMonitor<Signer>,
@ -951,7 +953,7 @@ impl TestChannelMessageHandler {
!msgs.as_ref().unwrap().is_empty(), !msgs.as_ref().unwrap().is_empty(),
"Received message when we weren't expecting one" "Received message when we weren't expecting one"
); );
#[cfg(test)] #[cfg(any(test, feature = "_test_utils"))]
assert_eq!(msgs.as_ref().unwrap()[0], _ev); assert_eq!(msgs.as_ref().unwrap()[0], _ev);
msgs.as_mut().unwrap().remove(0); msgs.as_mut().unwrap().remove(0);
} }
@ -1487,7 +1489,7 @@ impl NodeSigner for TestNodeSigner {
} }
pub struct TestKeysInterface { pub struct TestKeysInterface {
pub backing: sign::PhantomKeysManager, pub backing: DynKeysInterface,
pub override_random_bytes: Mutex<Option<[u8; 32]>>, pub override_random_bytes: Mutex<Option<[u8; 32]>>,
pub disable_revocation_policy_check: bool, pub disable_revocation_policy_check: bool,
enforcement_states: Mutex<HashMap<[u8; 32], Arc<Mutex<EnforcementState>>>>, enforcement_states: Mutex<HashMap<[u8; 32], Arc<Mutex<EnforcementState>>>>,
@ -1581,30 +1583,42 @@ impl SignerProvider for TestKeysInterface {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub static SIGNER_FACTORY: MutGlobal<Arc<dyn TestSignerFactory>> = MutGlobal::new(|| { Arc::new(DefaultSignerFactory()) }); pub static SIGNER_FACTORY: MutGlobal<Arc<dyn TestSignerFactory>> =
MutGlobal::new(|| Arc::new(DefaultSignerFactory()));
pub trait TestSignerFactory: Send + Sync { pub trait TestSignerFactory: Send + Sync {
/// Make a dynamic signer /// Make a dynamic signer
fn make_signer(&self, seed: &[u8; 32], now: Duration) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>>; fn make_signer(
&self, seed: &[u8; 32], now: Duration,
) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner = DynSigner>>;
} }
#[derive(Clone)] #[derive(Clone)]
struct DefaultSignerFactory(); struct DefaultSignerFactory();
impl TestSignerFactory for DefaultSignerFactory { impl TestSignerFactory for DefaultSignerFactory {
fn make_signer(&self, seed: &[u8; 32], now: Duration) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>> { fn make_signer(
&self, seed: &[u8; 32], now: Duration,
) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner = DynSigner>> {
let phantom = sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed); let phantom = sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed);
let dphantom = DynPhantomKeysInterface::new(phantom); let dphantom = DynPhantomKeysInterface::new(phantom);
let backing = Box::new(dphantom) as Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>>; let backing = Box::new(dphantom) as Box<dyn DynKeysInterfaceTrait<EcdsaSigner = DynSigner>>;
backing backing
} }
} }
impl TestKeysInterface { impl TestKeysInterface {
pub fn new(seed: &[u8; 32], network: Network) -> Self { pub fn new(seed: &[u8; 32], network: Network) -> Self {
#[cfg(feature = "std")]
let factory = SIGNER_FACTORY.get();
#[cfg(not(feature = "std"))]
let factory = DefaultSignerFactory();
let now = Duration::from_secs(genesis_block(network).header.time as u64); let now = Duration::from_secs(genesis_block(network).header.time as u64);
let backing = factory.make_signer(seed, now);
Self { Self {
backing: sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed), backing: DynKeysInterface::new(backing),
override_random_bytes: Mutex::new(None), override_random_bytes: Mutex::new(None),
disable_revocation_policy_check: false, disable_revocation_policy_check: false,
enforcement_states: Mutex::new(new_hash_map()), enforcement_states: Mutex::new(new_hash_map()),