Skip to content

Commit fd35254

Browse files
committed
expose functional tests under _test_utils feature flag
introduce DynSigner and TestSignerFactory
1 parent 7754bbb commit fd35254

32 files changed

+1140
-523
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ lightning/net_graph-*.bin
1212
lightning-rapid-gossip-sync/res/full_graph.lngossip
1313
lightning-custom-message/target
1414
lightning-transaction-sync/target
15+
ext-functional-test-demo/target
1516
no-std-check/target
1617
msrv-no-dev-deps-check/target

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ members = [
1919
]
2020

2121
exclude = [
22+
"ext-functional-test-demo",
2223
"no-std-check",
2324
"msrv-no-dev-deps-check",
2425
"bench",

ci/ci-tests.sh

+6
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ cargo check --verbose --color always --features lightning-transaction-sync
138138
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
139139
popd
140140

141+
echo -e "\n\Running functional tests from outside the workspace"
142+
pushd ext-functional-test-demo
143+
cargo test --color always
144+
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
145+
popd
146+
141147
# Test that we can build downstream code with only the "release pins".
142148
pushd msrv-no-dev-deps-check
143149
PIN_RELEASE_DEPS

ext-functional-test-demo/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "ext-functional-tester"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
lightning = { path = "../lightning", features = ["_test_utils"] }

ext-functional-test-demo/src/main.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
fn main() {
2+
println!("Hello, world!");
3+
}
4+
5+
#[cfg(test)]
6+
mod tests {
7+
use lightning::util::dyn_signer::{DynKeysInterfaceTrait, DynSigner};
8+
use lightning::util::test_utils::{TestSignerFactory, SIGNER_FACTORY};
9+
use std::panic::catch_unwind;
10+
use std::sync::Arc;
11+
use std::time::Duration;
12+
13+
struct BrokenSignerFactory();
14+
15+
impl TestSignerFactory for BrokenSignerFactory {
16+
fn make_signer(
17+
&self, _seed: &[u8; 32], _now: Duration,
18+
) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner = DynSigner>> {
19+
panic!()
20+
}
21+
}
22+
23+
#[test]
24+
fn test_functional() {
25+
lightning::ln::functional_tests::test_insane_channel_opens();
26+
lightning::ln::functional_tests::fake_network_test();
27+
28+
SIGNER_FACTORY.set(Arc::new(BrokenSignerFactory()));
29+
catch_unwind(|| lightning::ln::functional_tests::fake_network_test()).unwrap_err();
30+
}
31+
}

fuzz/src/chanmon_consistency.rs

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ use bitcoin::secp256k1::schnorr;
8181
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
8282

8383
use lightning::io::Cursor;
84+
use lightning::util::dyn_signer::DynSigner;
8485
use std::cmp::{self, Ordering};
8586
use std::mem;
8687
use std::sync::atomic;
@@ -391,6 +392,7 @@ impl SignerProvider for KeyProvider {
391392
channel_keys_id,
392393
);
393394
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
395+
let keys = DynSigner::new(keys);
394396
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
395397
}
396398

@@ -399,6 +401,7 @@ impl SignerProvider for KeyProvider {
399401

400402
let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?;
401403
let state = self.make_enforcement_state_cell(inner.commitment_seed);
404+
let inner = DynSigner::new(inner);
402405

403406
Ok(TestChannelSigner::new_with_revoked(inner, state, false))
404407
}

fuzz/src/full_stack.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
7777
use bitcoin::secp256k1::schnorr;
7878
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
7979

80+
use lightning::util::dyn_signer::DynSigner;
8081
use std::cell::RefCell;
8182
use std::cmp;
8283
use std::convert::TryInto;
@@ -455,7 +456,7 @@ impl SignerProvider for KeyProvider {
455456
let ctr = channel_keys_id[0];
456457
let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone();
457458
TestChannelSigner::new_with_revoked(
458-
if inbound {
459+
DynSigner::new(if inbound {
459460
InMemorySigner::new(
460461
&secp_ctx,
461462
SecretKey::from_slice(&[
@@ -527,7 +528,7 @@ impl SignerProvider for KeyProvider {
527528
channel_keys_id,
528529
channel_keys_id,
529530
)
530-
},
531+
}),
531532
state,
532533
false,
533534
)
@@ -536,6 +537,7 @@ impl SignerProvider for KeyProvider {
536537
fn read_chan_signer(&self, mut data: &[u8]) -> Result<TestChannelSigner, DecodeError> {
537538
let inner: InMemorySigner = ReadableArgs::read(&mut data, self)?;
538539
let state = Arc::new(Mutex::new(EnforcementState::new()));
540+
let inner = DynSigner::new(inner);
539541

540542
Ok(TestChannelSigner::new_with_revoked(inner, state, false))
541543
}

lightning-background-processor/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,8 @@ mod tests {
25572557
failure: PathFailure::OnPath { network_update: None },
25582558
path: path.clone(),
25592559
short_channel_id: Some(scored_scid),
2560+
error_code: None,
2561+
error_data: None,
25602562
});
25612563
let event = $receive.expect("PaymentPathFailed not handled within deadline");
25622564
match event {
@@ -2574,6 +2576,8 @@ mod tests {
25742576
failure: PathFailure::OnPath { network_update: None },
25752577
path: path.clone(),
25762578
short_channel_id: None,
2579+
error_code: None,
2580+
error_data: None,
25772581
});
25782582
let event = $receive.expect("PaymentPathFailed not handled within deadline");
25792583
match event {

lightning/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
1717

1818
[features]
1919
# Internal test utilities exposed to other repo crates
20-
_test_utils = ["regex", "bitcoin/bitcoinconsensus", "lightning-types/_test_utils"]
20+
_test_utils = ["regex", "bitcoin/bitcoinconsensus", "ext-test-macro", "lightning-types/_test_utils"]
2121
# Unlog messages superior at targeted level.
2222
max_level_off = []
2323
max_level_error = []
@@ -50,6 +50,7 @@ backtrace = { version = "0.3", optional = true }
5050

5151
libm = { version = "0.2", default-features = false }
5252
delegate = "0.12.0"
53+
ext-test-macro = { path = "../ext-test-macro", optional = true }
5354

5455
[dev-dependencies]
5556
regex = "1.5.6"

lightning/src/chain/chainmonitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ where C::Target: chain::Filter,
464464
}
465465

466466

467-
#[cfg(test)]
467+
#[cfg(any(test, feature = "_test_utils"))]
468468
pub fn remove_monitor(&self, funding_txo: &OutPoint) -> ChannelMonitor<ChannelSigner> {
469469
self.monitors.write().unwrap().remove(funding_txo).unwrap().monitor
470470
}

lightning/src/chain/channelmonitor.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -844,10 +844,7 @@ impl Readable for IrrevocablyResolvedHTLC {
844844
/// returned block hash and the the current chain and then reconnecting blocks to get to the
845845
/// best chain) upon deserializing the object!
846846
pub struct ChannelMonitor<Signer: EcdsaChannelSigner> {
847-
#[cfg(test)]
848847
pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
849-
#[cfg(not(test))]
850-
pub(super) inner: Mutex<ChannelMonitorImpl<Signer>>,
851848
}
852849

853850
impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone {
@@ -946,9 +943,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
946943
// Obviously Correct (tm) if we just keep track of them explicitly.
947944
outputs_to_watch: HashMap<Txid, Vec<(u32, ScriptBuf)>>,
948945

949-
#[cfg(test)]
946+
#[cfg(any(test, feature = "_test_utils"))]
950947
pub onchain_tx_handler: OnchainTxHandler<Signer>,
951-
#[cfg(not(test))]
948+
#[cfg(not(any(test, feature = "_test_utils")))]
952949
onchain_tx_handler: OnchainTxHandler<Signer>,
953950

954951
// This is set when the Channel[Manager] generated a ChannelMonitorUpdate which indicated the
@@ -1726,7 +1723,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17261723
/// Unsafe test-only version of `broadcast_latest_holder_commitment_txn` used by our test framework
17271724
/// to bypass HolderCommitmentTransaction state update lockdown after signature and generate
17281725
/// revoked commitment transaction.
1729-
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))]
1726+
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
17301727
pub fn unsafe_get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction>
17311728
where L::Target: Logger {
17321729
let mut inner = self.inner.lock().unwrap();
@@ -2026,7 +2023,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
20262023
self.inner.lock().unwrap().counterparty_payment_script = script;
20272024
}
20282025

2029-
#[cfg(test)]
2026+
#[cfg(any(test, feature = "_test_utils"))]
20302027
pub fn do_mut_signer_call<F: FnMut(&mut Signer) -> ()>(&self, mut f: F) {
20312028
let mut inner = self.inner.lock().unwrap();
20322029
f(&mut inner.onchain_tx_handler.signer);
@@ -2668,7 +2665,7 @@ macro_rules! fail_unbroadcast_htlcs {
26682665
// witness length match (ie is 136 bytes long). We generate one here which we also use in some
26692666
// in-line tests later.
26702667

2671-
#[cfg(test)]
2668+
#[cfg(any(test, feature = "_test_utils"))]
26722669
pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec<u8> {
26732670
use bitcoin::opcodes;
26742671
let mut ret = [opcodes::all::OP_NOP.to_u8(); 136];
@@ -2680,7 +2677,7 @@ pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec<u8> {
26802677
Vec::from(&ret[..])
26812678
}
26822679

2683-
#[cfg(test)]
2680+
#[cfg(any(test, feature = "_test_utils"))]
26842681
pub fn deliberately_bogus_accepted_htlc_witness() -> Vec<Vec<u8>> {
26852682
vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into()
26862683
}
@@ -3808,7 +3805,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38083805
}
38093806
}
38103807

3811-
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
3808+
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
38123809
/// Note that this includes possibly-locktimed-in-the-future transactions!
38133810
fn unsafe_get_latest_holder_commitment_txn<L: Deref>(
38143811
&mut self, logger: &WithChannelMonitor<L>
@@ -5066,7 +5063,7 @@ mod tests {
50665063
nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header,
50675064
&[(0, broadcast_tx)], conf_height);
50685065

5069-
let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<InMemorySigner>)>::read(
5066+
let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<_>)>::read(
50705067
&mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()),
50715068
(&nodes[1].keys_manager.backing, &nodes[1].keys_manager.backing)).unwrap();
50725069

lightning/src/chain/onchaintx.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,7 @@ pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
249249
// Key is identifier of the pending claim request, i.e the txid of the initial claiming transaction generated by
250250
// us and is immutable until all outpoint of the claimable set are post-anti-reorg-delay solved.
251251
// Entry is cache of elements need to generate a bumped claiming transaction (see ClaimTxBumpMaterial)
252-
#[cfg(test)] // Used in functional_test to verify sanitization
253252
pub(crate) pending_claim_requests: HashMap<ClaimId, PackageTemplate>,
254-
#[cfg(not(test))]
255-
pending_claim_requests: HashMap<ClaimId, PackageTemplate>,
256253

257254
// Used to track external events that need to be forwarded to the `ChainMonitor`. This `Vec`
258255
// essentially acts as an insertion-ordered `HashMap` – there should only ever be one occurrence
@@ -272,10 +269,7 @@ pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
272269
// block height, and are immutable until the outpoint has enough confirmations to meet our
273270
// [`ANTI_REORG_DELAY`]. The initial confirmation block height is used to remove the entry if
274271
// the block gets disconnected.
275-
#[cfg(test)] // Used in functional_test to verify sanitization
276-
pub claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>,
277-
#[cfg(not(test))]
278-
claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>,
272+
pub(crate) claimable_outpoints: HashMap<BitcoinOutPoint, (ClaimId, u32)>,
279273

280274
locktimed_packages: BTreeMap<u32, Vec<PackageTemplate>>,
281275

@@ -1176,7 +1170,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
11761170
MaybeSignedTransaction(tx)
11771171
}
11781172

1179-
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
1173+
#[cfg(any(test, feature="_test_utils", feature="unsafe_revoked_tx_signing"))]
11801174
pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {
11811175
let sig = self.signer.unsafe_sign_holder_commitment(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment");
11821176
self.holder_commitment.add_holder_sig(funding_redeemscript, sig)

lightning/src/events/mod.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -1009,9 +1009,9 @@ pub enum Event {
10091009
/// If this is `Some`, then the corresponding channel should be avoided when the payment is
10101010
/// retried. May be `None` for older [`Event`] serializations.
10111011
short_channel_id: Option<u64>,
1012-
#[cfg(test)]
1012+
#[cfg(any(test, feature = "_test_utils"))]
10131013
error_code: Option<u16>,
1014-
#[cfg(test)]
1014+
#[cfg(any(test, feature = "_test_utils"))]
10151015
error_data: Option<Vec<u8>>,
10161016
},
10171017
/// Indicates that a probe payment we sent returned successful, i.e., only failed at the destination.
@@ -1509,15 +1509,15 @@ impl Writeable for Event {
15091509
&Event::PaymentPathFailed {
15101510
ref payment_id, ref payment_hash, ref payment_failed_permanently, ref failure,
15111511
ref path, ref short_channel_id,
1512-
#[cfg(test)]
1512+
#[cfg(any(test, feature = "_test_utils"))]
15131513
ref error_code,
1514-
#[cfg(test)]
1514+
#[cfg(any(test, feature = "_test_utils"))]
15151515
ref error_data,
15161516
} => {
15171517
3u8.write(writer)?;
1518-
#[cfg(test)]
1518+
#[cfg(any(test, feature = "_test_utils"))]
15191519
error_code.write(writer)?;
1520-
#[cfg(test)]
1520+
#[cfg(any(test, feature = "_test_utils"))]
15211521
error_data.write(writer)?;
15221522
write_tlv_fields!(writer, {
15231523
(0, payment_hash, required),
@@ -1850,9 +1850,9 @@ impl MaybeReadable for Event {
18501850
},
18511851
3u8 => {
18521852
let mut f = || {
1853-
#[cfg(test)]
1853+
#[cfg(any(test, feature = "_test_utils"))]
18541854
let error_code = Readable::read(reader)?;
1855-
#[cfg(test)]
1855+
#[cfg(any(test, feature = "_test_utils"))]
18561856
let error_data = Readable::read(reader)?;
18571857
let mut payment_hash = PaymentHash([0; 32]);
18581858
let mut payment_failed_permanently = false;
@@ -1882,9 +1882,9 @@ impl MaybeReadable for Event {
18821882
failure,
18831883
path: Path { hops: path.unwrap(), blinded_tail },
18841884
short_channel_id,
1885-
#[cfg(test)]
1885+
#[cfg(any(test, feature = "_test_utils"))]
18861886
error_code,
1887-
#[cfg(test)]
1887+
#[cfg(any(test, feature = "_test_utils"))]
18881888
error_data,
18891889
}))
18901890
};

lightning/src/ln/bolt11_payment.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ mod tests {
8989
use super::*;
9090
use crate::ln::types::PaymentSecret;
9191
use crate::routing::router::Payee;
92+
use crate::sign::{NodeSigner, Recipient};
9293
use bitcoin::hashes::sha256::Hash as Sha256;
9394
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
9495
use lightning_invoice::{Currency, InvoiceBuilder};
@@ -178,8 +179,6 @@ mod tests {
178179
let (payment_hash, payment_secret) =
179180
nodes[1].node.create_inbound_payment(None, 7200, None).unwrap();
180181

181-
let secp_ctx = Secp256k1::new();
182-
let node_secret = nodes[1].keys_manager.backing.get_node_secret_key();
183182
let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
184183
let invoice = InvoiceBuilder::new(Currency::Bitcoin)
185184
.description("test".into())
@@ -189,8 +188,11 @@ mod tests {
189188
.min_final_cltv_expiry_delta(144)
190189
.amount_milli_satoshis(50_000)
191190
.payment_metadata(payment_metadata.clone())
192-
.build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &node_secret))
191+
.build_raw()
193192
.unwrap();
193+
let sig = nodes[1].keys_manager.backing.sign_invoice(&invoice, Recipient::Node).unwrap();
194+
let invoice = invoice.sign::<_, ()>(|_| Ok(sig)).unwrap();
195+
let invoice = Bolt11Invoice::from_signed(invoice).unwrap();
194196

195197
let (hash, onion, params) = payment_parameters_from_invoice(&invoice).unwrap();
196198
nodes[0]

lightning/src/ln/chan_utils.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,9 @@ impl HTLCClaim {
176176
}
177177
}
178178

179-
#[cfg(not(test))]
179+
#[cfg(not(any(test, feature = "_test_utils")))]
180180
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
181-
#[cfg(test)]
181+
#[cfg(any(test, feature = "_test_utils"))]
182182
pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
183183

184184
pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 {

0 commit comments

Comments
 (0)