Skip to content

Commit 3cc98e3

Browse files
committed
Add support for retrieving and suspending the channel signer
This adds a `get_signer` method to the context so that a test can get ahold of the channel signer. Adds a `set_available` method on the `TestChannelSigner` to allow a test to enable and disable the signer: when disabled some of the signer's methods will return `Err` which will typically activate the error handling case. Adds a `set_channel_signer_available` function on the test `Node` class to make it easy to enable and disable a specific signer.
1 parent dbe9840 commit 3cc98e3

File tree

4 files changed

+60
-3
lines changed

4 files changed

+60
-3
lines changed

lightning/src/ln/channel.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
10251025
self.outbound_scid_alias
10261026
}
10271027

1028+
/// Returns the holder signer for this channel.
1029+
#[cfg(test)]
1030+
pub fn get_signer(&self) -> &ChannelSignerType<<SP::Target as SignerProvider>::Signer> {
1031+
return &self.holder_signer
1032+
}
1033+
10281034
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
10291035
/// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases
10301036
/// or prior to any channel actions during `Channel` initialization.

lightning/src/ln/functional_test_utils.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysI
3030
use crate::util::errors::APIError;
3131
use crate::util::config::{UserConfig, MaxDustHTLCExposure};
3232
use crate::util::ser::{ReadableArgs, Writeable};
33+
#[cfg(test)]
34+
use crate::util::logger::Logger;
3335

3436
use bitcoin::blockdata::block::{Block, BlockHeader};
3537
use bitcoin::blockdata::transaction::{Transaction, TxOut};
@@ -414,6 +416,31 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
414416
pub fn get_block_header(&self, height: u32) -> BlockHeader {
415417
self.blocks.lock().unwrap()[height as usize].0.header
416418
}
419+
/// Changes the channel signer's availability for the specified peer and channel.
420+
///
421+
/// When `available` is set to `true`, the channel signer will behave normally. When set to
422+
/// `false`, the channel signer will act like an off-line remote signer and will return `Err` for
423+
/// several of the signing methods. Currently, only `get_per_commitment_point` and
424+
/// `release_commitment_secret` are affected by this setting.
425+
#[cfg(test)]
426+
pub fn set_channel_signer_available(&self, peer_id: &PublicKey, chan_id: &ChannelId, available: bool) {
427+
let per_peer_state = self.node.per_peer_state.read().unwrap();
428+
let chan_lock = per_peer_state.get(peer_id).unwrap().lock().unwrap();
429+
let signer = (|| {
430+
if let Some(local_chan) = chan_lock.channel_by_id.get(chan_id) {
431+
return local_chan.get_signer();
432+
}
433+
if let Some(local_chan) = chan_lock.inbound_v1_channel_by_id.get(chan_id) {
434+
return local_chan.context.get_signer();
435+
}
436+
if let Some(local_chan) = chan_lock.outbound_v1_channel_by_id.get(chan_id) {
437+
return local_chan.context.get_signer();
438+
}
439+
panic!("Couldn't find a channel with id {}", chan_id);
440+
})();
441+
log_debug!(self.logger, "Setting channel signer for {} as available={}", chan_id, available);
442+
signer.as_ecdsa().unwrap().set_available(available);
443+
}
417444
}
418445

419446
/// If we need an unsafe pointer to a `Node` (ie to reference it in a thread

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1717
use crate::chain::channelmonitor;
1818
use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
1919
use crate::chain::transaction::OutPoint;
20-
use crate::sign::{ChannelSigner, EcdsaChannelSigner, EntropySource, SignerProvider};
20+
use crate::sign::{EcdsaChannelSigner, EntropySource, SignerProvider};
2121
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
2222
use crate::ln::{ChannelId, PaymentPreimage, PaymentSecret, PaymentHash};
2323
use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY};

lightning/src/util/test_channel_signer.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ pub struct TestChannelSigner {
5656
/// Channel state used for policy enforcement
5757
pub state: Arc<Mutex<EnforcementState>>,
5858
pub disable_revocation_policy_check: bool,
59+
/// When `true` (the default), the signer will respond immediately with signatures. When `false`,
60+
/// the signer will return an error indicating that it is unavailable.
61+
available: Arc<Mutex<bool>>,
5962
}
6063

6164
impl PartialEq for TestChannelSigner {
@@ -71,7 +74,8 @@ impl TestChannelSigner {
7174
Self {
7275
inner,
7376
state,
74-
disable_revocation_policy_check: false
77+
disable_revocation_policy_check: false,
78+
available: Arc::new(Mutex::new(true)),
7579
}
7680
}
7781

@@ -84,7 +88,8 @@ impl TestChannelSigner {
8488
Self {
8589
inner,
8690
state,
87-
disable_revocation_policy_check
91+
disable_revocation_policy_check,
92+
available: Arc::new(Mutex::new(true)),
8893
}
8994
}
9095

@@ -94,6 +99,16 @@ impl TestChannelSigner {
9499
pub fn get_enforcement_state(&self) -> MutexGuard<EnforcementState> {
95100
self.state.lock().unwrap()
96101
}
102+
103+
/// Marks the signer's availability.
104+
///
105+
/// When `true`, methods are forwarded to the underlying signer as normal. When `false`, some
106+
/// methods will return `Err` indicating that the signer is unavailable. Intended to be used for
107+
/// testing asynchronous signing.
108+
#[cfg(test)]
109+
pub fn set_available(&self, available: bool) {
110+
*self.available.lock().unwrap() = available;
111+
}
97112
}
98113

99114
impl ChannelSigner for TestChannelSigner {
@@ -133,6 +148,9 @@ impl EcdsaChannelSigner for TestChannelSigner {
133148
self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx);
134149

135150
{
151+
if !*self.available.lock().unwrap() {
152+
return Err(());
153+
}
136154
let mut state = self.state.lock().unwrap();
137155
let actual_commitment_number = commitment_tx.commitment_number();
138156
let last_commitment_number = state.last_counterparty_commitment;
@@ -149,13 +167,19 @@ impl EcdsaChannelSigner for TestChannelSigner {
149167
}
150168

151169
fn validate_counterparty_revocation(&self, idx: u64, _secret: &SecretKey) -> Result<(), ()> {
170+
if !*self.available.lock().unwrap() {
171+
return Err(());
172+
}
152173
let mut state = self.state.lock().unwrap();
153174
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);
154175
state.last_counterparty_revoked_commitment = idx;
155176
Ok(())
156177
}
157178

158179
fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
180+
if !*self.available.lock().unwrap() {
181+
return Err(());
182+
}
159183
let trusted_tx = self.verify_holder_commitment_tx(commitment_tx, secp_ctx);
160184
let commitment_txid = trusted_tx.txid();
161185
let holder_csv = self.inner.counterparty_selected_contest_delay();

0 commit comments

Comments
 (0)