diff --git a/Cargo.toml b/Cargo.toml index 8c088524416..49497e0b963 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "lightning-macros", "lightning-dns-resolver", "lightning-liquidity", + "lightning-tests", "possiblyrandom", ] diff --git a/ci/ci-tests.sh b/ci/ci-tests.sh index 8e3edfa43a8..acbacc5cd7e 100755 --- a/ci/ci-tests.sh +++ b/ci/ci-tests.sh @@ -32,7 +32,7 @@ cargo check --verbose --color always # When the workspace members change, make sure to update the list here as well # as in `Cargo.toml`. WORKSPACE_MEMBERS=( - lightning + lightning@0.2.0+git lightning-types lightning-block-sync lightning-invoice @@ -44,6 +44,7 @@ WORKSPACE_MEMBERS=( lightning-macros lightning-dns-resolver lightning-liquidity + lightning-tests possiblyrandom ) @@ -74,14 +75,14 @@ cargo test -p lightning-custom-message --verbose --color always [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean echo -e "\n\nTest backtrace-debug builds" -cargo test -p lightning --verbose --color always --features backtrace +cargo test -p lightning@0.2.0+git --verbose --color always --features backtrace echo -e "\n\nTesting no_std builds" for DIR in lightning-invoice lightning-rapid-gossip-sync lightning-liquidity; do cargo test -p $DIR --verbose --color always --no-default-features done -cargo test -p lightning --verbose --color always --no-default-features +cargo test -p lightning@0.2.0+git --verbose --color always --no-default-features echo -e "\n\nTesting c_bindings builds" # Note that because `$RUSTFLAGS` is not passed through to doctest builds we cannot selectively @@ -96,11 +97,11 @@ done # Note that because `$RUSTFLAGS` is not passed through to doctest builds we cannot selectively # disable doctests in `c_bindings` so we skip doctests entirely here. RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning-background-processor --verbose --color always --features futures --no-default-features --lib --bins --tests -RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning --verbose --color always --no-default-features --lib --bins --tests +RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning@0.2.0+git --verbose --color always --no-default-features --lib --bins --tests echo -e "\n\nTesting other crate-specific builds" # Note that outbound_commitment_test only runs in this mode because of hardcoded signature values -RUSTFLAGS="$RUSTFLAGS --cfg=ldk_test_vectors" cargo test -p lightning --verbose --color always --no-default-features --features=std +RUSTFLAGS="$RUSTFLAGS --cfg=ldk_test_vectors" cargo test -p lightning@0.2.0+git --verbose --color always --no-default-features --features=std # This one only works for lightning-invoice # check that compile with no_std and serde works in lightning-invoice cargo test -p lightning-invoice --verbose --color always --no-default-features --features serde @@ -127,12 +128,12 @@ if [ -f "$(which arm-none-eabi-gcc)" ]; then fi echo -e "\n\nTest cfg-flag builds" -RUSTFLAGS="--cfg=taproot" cargo test --verbose --color always -p lightning +RUSTFLAGS="--cfg=taproot" cargo test --verbose --color always -p lightning@0.2.0+git [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean -RUSTFLAGS="--cfg=splicing" cargo test --verbose --color always -p lightning +RUSTFLAGS="--cfg=splicing" cargo test --verbose --color always -p lightning@0.2.0+git [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean -RUSTFLAGS="--cfg=trampoline" cargo test --verbose --color always -p lightning +RUSTFLAGS="--cfg=trampoline" cargo test --verbose --color always -p lightning@0.2.0+git [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean -RUSTFLAGS="--cfg=async_payments" cargo test --verbose --color always -p lightning +RUSTFLAGS="--cfg=async_payments" cargo test --verbose --color always -p lightning@0.2.0+git [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean RUSTFLAGS="--cfg=lsps1_service" cargo test --verbose --color always -p lightning-liquidity diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index cf18fa83afa..82209ebe5f2 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -377,7 +377,7 @@ impl SignerProvider for KeyProvider { ); 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, false) } fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 6594f472516..638726f7488 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -435,85 +435,29 @@ impl SignerProvider for KeyProvider { [ctr; 32] } - fn derive_channel_signer(&self, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { + fn derive_channel_signer(&self, keys_id: [u8; 32]) -> Self::EcdsaSigner { let secp_ctx = Secp256k1::signing_only(); - let ctr = channel_keys_id[0]; + let ctr = keys_id[0]; let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone(); - TestChannelSigner::new_with_revoked( - DynSigner::new(if inbound { - InMemorySigner::new( - &secp_ctx, - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, ctr, - ]) - .unwrap(), - [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 6, ctr, - ], - channel_keys_id, - channel_keys_id, - ) - } else { - InMemorySigner::new( - &secp_ctx, - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 7, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 8, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, ctr, - ]) - .unwrap(), - SecretKey::from_slice(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 11, ctr, - ]) - .unwrap(), - [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 12, ctr, - ], - channel_keys_id, - channel_keys_id, - ) - }), - state, - false, - ) + + let (a, b, c, d, e, f); + let mut key = [0; 32]; + key[31] = ctr; + key[30] = 1 + if inbound { 0 } else { 6 }; + a = SecretKey::from_slice(&key).unwrap(); + key[30] = 2 + if inbound { 0 } else { 6 }; + b = SecretKey::from_slice(&key).unwrap(); + key[30] = 3 + if inbound { 0 } else { 6 }; + c = SecretKey::from_slice(&key).unwrap(); + key[30] = 4 + if inbound { 0 } else { 6 }; + d = SecretKey::from_slice(&key).unwrap(); + key[30] = 5 + if inbound { 0 } else { 6 }; + e = SecretKey::from_slice(&key).unwrap(); + key[30] = 6 + if inbound { 0 } else { 6 }; + f = key; + let signer = InMemorySigner::new(&secp_ctx, a, b, c, d, e, f, keys_id, keys_id); + + TestChannelSigner::new_with_revoked(DynSigner::new(signer), state, false, false) } fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { diff --git a/lightning-tests/Cargo.toml b/lightning-tests/Cargo.toml new file mode 100644 index 00000000000..8499bf04f12 --- /dev/null +++ b/lightning-tests/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "lightning-tests" +version = "0.0.1" +authors = ["Matt Corallo"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/lightningdevkit/rust-lightning/" +description = "Tests for LDK crates" +edition = "2021" + +[features] + +[dependencies] +lightning-types = { version = "0.3.0", path = "../lightning-types", features = ["_test_utils"] } +lightning-invoice = { version = "0.34.0", path = "../lightning-invoice", default-features = false } +lightning-macros = { version = "0.2", path = "../lightning-macros" } +lightning = { version = "0.2", path = "../lightning", features = ["_test_utils"] } +lightning_0_1 = { package = "lightning", version = "0.1.1", features = ["_test_utils"] } + +bitcoin = { version = "0.32.2", default-features = false } + +[dev-dependencies] + + +[lints] +workspace = true diff --git a/lightning-tests/src/lib.rs b/lightning-tests/src/lib.rs new file mode 100644 index 00000000000..c028193d692 --- /dev/null +++ b/lightning-tests/src/lib.rs @@ -0,0 +1,5 @@ +#[cfg_attr(test, macro_use)] +extern crate lightning; + +#[cfg(all(test, not(taproot)))] +pub mod upgrade_downgrade_tests; diff --git a/lightning-tests/src/upgrade_downgrade_tests.rs b/lightning-tests/src/upgrade_downgrade_tests.rs new file mode 100644 index 00000000000..c29f57ddf71 --- /dev/null +++ b/lightning-tests/src/upgrade_downgrade_tests.rs @@ -0,0 +1,64 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Tests which test upgrading from previous versions of LDK or downgrading to previous versions of +//! LDK. + +use lightning_0_1::ln::functional_test_utils as lightning_0_1_utils; +use lightning_0_1::get_monitor as get_monitor_0_1; +use lightning_0_1::util::ser::Writeable; + +use lightning::ln::functional_test_utils::*; + +use lightning_types::payment::PaymentPreimage; + +#[test] +fn simple_upgrade() { + // Tests a simple case of upgrading from LDK 0.1 with a pending payment + let (node_a, node_b, mon_a, mon_b, preimage); + { + let chanmon_cfgs = lightning_0_1_utils::create_chanmon_cfgs(2); + let node_cfgs = lightning_0_1_utils::create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = lightning_0_1_utils::create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = lightning_0_1_utils::create_network(2, &node_cfgs, &node_chanmgrs); + + let chan_id = lightning_0_1_utils::create_announced_chan_between_nodes(&nodes, 0, 1).2; + + let payment_preimage = + lightning_0_1_utils::route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + preimage = PaymentPreimage(payment_preimage.0 .0); + + node_a = nodes[0].node.encode(); + node_b = nodes[1].node.encode(); + mon_a = get_monitor_0_1!(nodes[0], chan_id).encode(); + mon_b = get_monitor_0_1!(nodes[1], chan_id).encode(); + } + + // Create a dummy node to reload over with the 0.1 state + + let mut chanmon_cfgs = create_chanmon_cfgs(2); + + // Our TestChannelSigner will fail as we're jumping ahead, so disable its state-based checks + chanmon_cfgs[0].keys_manager.disable_all_state_policy_checks = true; + chanmon_cfgs[1].keys_manager.disable_all_state_policy_checks = true; + + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let (persister_a, persister_b, chain_monitor_a, chain_monitor_b); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let (node_deser_a, node_deser_b); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let config = test_default_channel_config(); + reload_node!(nodes[0], config, &node_a, &[&mon_a], persister_a, chain_monitor_a, node_deser_a); + reload_node!(nodes[1], config, &node_b, &[&mon_b], persister_b, chain_monitor_b, node_deser_b); + + reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); + + claim_payment(&nodes[0], &[&nodes[1]], preimage); +} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index 5fc763f7e5f..72390795cf8 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -55,6 +55,9 @@ regex = "1.5.6" lightning-types = { version = "0.3.0", path = "../lightning-types", features = ["_test_utils"] } lightning-macros = { path = "../lightning-macros" } +[target.'cfg(not(taproot))'.dev-dependencies] +lightning_0_1 = { package = "lightning", version = "0.1.1", features = ["_test_utils"] } + [dev-dependencies.bitcoin] version = "0.32.2" default-features = false diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 3771e3fc959..629956944fa 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -13389,7 +13389,7 @@ where (13, htlc_onion_fields, optional_vec), (14, decode_update_add_htlcs_opt, option), (15, self.inbound_payment_id_secret, required), - (17, in_flight_monitor_updates, required), + (17, in_flight_monitor_updates, option), (19, peer_storage_dir, optional_vec), }); @@ -13935,7 +13935,7 @@ where (13, claimable_htlc_onion_fields, optional_vec), (14, decode_update_add_htlcs, option), (15, inbound_payment_id_secret, option), - (17, in_flight_monitor_updates, required), + (17, in_flight_monitor_updates, option), (19, peer_storage_dir, optional_vec), }); let mut decode_update_add_htlcs = decode_update_add_htlcs.unwrap_or_else(|| new_hash_map()); diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 67470b0ce45..3924775c916 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -1168,7 +1168,7 @@ pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: User node_deserialized } -#[cfg(any(test, feature = "_externalize_tests"))] +#[macro_export] macro_rules! reload_node { ($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; diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index ce5a37f1b31..9fef2772894 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -1293,8 +1293,8 @@ where } } - #[cfg(any(test, feature = "_externalize_tests"))] - pub(crate) fn set_offers_handler(&mut self, offers_handler: OMH) { + #[cfg(any(test, feature = "_test_utils"))] + pub fn set_offers_handler(&mut self, offers_handler: OMH) { self.offers_handler = offers_handler; } diff --git a/lightning/src/util/test_channel_signer.rs b/lightning/src/util/test_channel_signer.rs index c439ac66c95..1ec0d04579c 100644 --- a/lightning/src/util/test_channel_signer.rs +++ b/lightning/src/util/test_channel_signer.rs @@ -73,6 +73,7 @@ pub struct TestChannelSigner { /// Channel state used for policy enforcement pub state: Arc>, pub disable_revocation_policy_check: bool, + pub disable_all_state_policy_checks: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -122,7 +123,12 @@ impl TestChannelSigner { /// Construct an TestChannelSigner pub fn new(inner: DynSigner) -> Self { let state = Arc::new(Mutex::new(EnforcementState::new())); - Self { inner, state, disable_revocation_policy_check: false } + Self { + inner, + state, + disable_revocation_policy_check: false, + disable_all_state_policy_checks: false, + } } /// Construct an TestChannelSigner with externally managed storage @@ -132,9 +138,9 @@ impl TestChannelSigner { /// here, usually by an implementation of KeysInterface. pub fn new_with_revoked( inner: DynSigner, state: Arc>, - disable_revocation_policy_check: bool, + disable_revocation_policy_check: bool, disable_all_state_policy_checks: bool, ) -> Self { - Self { inner, state, disable_revocation_policy_check } + Self { inner, state, disable_revocation_policy_check, disable_all_state_policy_checks } } #[cfg(any(test, feature = "_test_utils"))] @@ -174,12 +180,12 @@ impl ChannelSigner for TestChannelSigner { if !self.is_signer_available(SignerOp::ReleaseCommitmentSecret) { return Err(()); } - { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock().unwrap(); + if !self.disable_all_state_policy_checks { assert!(idx == state.last_holder_revoked_commitment || idx == state.last_holder_revoked_commitment - 1, "can only revoke the current or next unrevoked commitment - trying {}, last revoked {}", idx, state.last_holder_revoked_commitment); assert!(idx > state.last_holder_commitment, "cannot revoke the last holder commitment - attempted to revoke {} last commitment {}", idx, state.last_holder_commitment); - state.last_holder_revoked_commitment = idx; } + state.last_holder_revoked_commitment = idx; self.inner.release_commitment_secret(idx) } @@ -189,12 +195,14 @@ impl ChannelSigner for TestChannelSigner { ) -> Result<(), ()> { let mut state = self.state.lock().unwrap(); let idx = holder_tx.commitment_number(); - assert!( - idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, - "expecting to validate the current or next holder commitment - trying {}, current {}", - idx, - state.last_holder_commitment - ); + if !self.disable_all_state_policy_checks { + assert!( + idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, + "expecting to validate the current or next holder commitment - trying {}, current {}", + idx, + state.last_holder_commitment + ); + } state.last_holder_commitment = idx; Ok(()) } @@ -205,7 +213,9 @@ impl ChannelSigner for TestChannelSigner { return Err(()); } let mut state = self.state.lock().unwrap(); - assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment); + if !self.disable_all_state_policy_checks { + assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment); + } state.last_counterparty_revoked_commitment = idx; Ok(()) } @@ -227,14 +237,14 @@ impl EcdsaChannelSigner for TestChannelSigner { ) -> Result<(Signature, Vec), ()> { self.verify_counterparty_commitment_tx(channel_parameters, commitment_tx, secp_ctx); - { - #[cfg(test)] - if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) { - return Err(()); - } - let mut state = self.state.lock().unwrap(); - let actual_commitment_number = commitment_tx.commitment_number(); - let last_commitment_number = state.last_counterparty_commitment; + #[cfg(test)] + if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) { + return Err(()); + } + let mut state = self.state.lock().unwrap(); + let actual_commitment_number = commitment_tx.commitment_number(); + let last_commitment_number = state.last_counterparty_commitment; + if !self.disable_all_state_policy_checks { // These commitment numbers are backwards counting. We expect either the same as the previously encountered, // or the next one. assert!( @@ -252,9 +262,9 @@ impl EcdsaChannelSigner for TestChannelSigner { actual_commitment_number, state.last_counterparty_revoked_commitment ); - state.last_counterparty_commitment = - cmp::min(last_commitment_number, actual_commitment_number) } + state.last_counterparty_commitment = + cmp::min(last_commitment_number, actual_commitment_number); Ok(self .inner @@ -278,14 +288,16 @@ impl EcdsaChannelSigner for TestChannelSigner { } let trusted_tx = self.verify_holder_commitment_tx(channel_parameters, commitment_tx, secp_ctx); - let state = self.state.lock().unwrap(); - let commitment_number = trusted_tx.commitment_number(); - if state.last_holder_revoked_commitment - 1 != commitment_number - && state.last_holder_revoked_commitment - 2 != commitment_number - { - if !self.disable_revocation_policy_check { - panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", - state.last_holder_revoked_commitment, commitment_number, self.inner.channel_keys_id()[0]) + if !self.disable_all_state_policy_checks { + let state = self.state.lock().unwrap(); + let commitment_number = trusted_tx.commitment_number(); + if state.last_holder_revoked_commitment - 1 != commitment_number + && state.last_holder_revoked_commitment - 2 != commitment_number + { + if !self.disable_revocation_policy_check { + panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", + state.last_holder_revoked_commitment, commitment_number, self.inner.channel_keys_id()[0]) + } } } Ok(self.inner.sign_holder_commitment(channel_parameters, commitment_tx, secp_ctx).unwrap()) @@ -353,13 +365,15 @@ impl EcdsaChannelSigner for TestChannelSigner { if !self.is_signer_available(SignerOp::SignHolderHtlcTransaction) { return Err(()); } - let state = self.state.lock().unwrap(); - if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number - && state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number - { - if !self.disable_revocation_policy_check { - panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", - state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.channel_keys_id()[0]) + if !self.disable_all_state_policy_checks { + let state = self.state.lock().unwrap(); + if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number + && state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number + { + if !self.disable_revocation_policy_check { + panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", + state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.channel_keys_id()[0]) + } } } assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input()); diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index cfe96666c15..df2ff4c636a 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -1492,6 +1492,7 @@ pub struct TestKeysInterface { pub backing: DynKeysInterface, pub override_random_bytes: Mutex>, pub disable_revocation_policy_check: bool, + pub disable_all_state_policy_checks: bool, enforcement_states: Mutex>>>, expectations: Mutex>>, pub unavailable_signers_ops: Mutex>>, @@ -1552,8 +1553,9 @@ impl SignerProvider for TestKeysInterface { fn derive_channel_signer(&self, channel_keys_id: [u8; 32]) -> TestChannelSigner { let keys = self.backing.derive_channel_signer(channel_keys_id); let state = self.make_enforcement_state_cell(keys.channel_keys_id()); - let signer = - TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check); + let rev_checks = self.disable_revocation_policy_check; + let state_checks = self.disable_all_state_policy_checks; + let signer = TestChannelSigner::new_with_revoked(keys, state, rev_checks, state_checks); #[cfg(test)] if let Some(ops) = self.unavailable_signers_ops.lock().unwrap().get(&channel_keys_id) { for &op in ops { @@ -1621,6 +1623,7 @@ impl TestKeysInterface { backing: DynKeysInterface::new(backing), override_random_bytes: Mutex::new(None), disable_revocation_policy_check: false, + disable_all_state_policy_checks: false, enforcement_states: Mutex::new(new_hash_map()), expectations: Mutex::new(None), unavailable_signers_ops: Mutex::new(new_hash_map()),