Skip to content

Commit 6468a8f

Browse files
committed
Allow toggling specific signing methods in test channel signer
1 parent 07f3380 commit 6468a8f

File tree

5 files changed

+148
-2
lines changed

5 files changed

+148
-2
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
19281928
let inner = self.inner.lock().unwrap();
19291929
f(&inner.onchain_tx_handler.signer);
19301930
}
1931+
1932+
#[cfg(test)]
1933+
pub fn do_mut_signer_call<F: FnMut(&mut Signer) -> ()>(&self, mut f: F) {
1934+
let mut inner = self.inner.lock().unwrap();
1935+
f(&mut inner.onchain_tx_handler.signer);
1936+
}
19311937
}
19321938

19331939
impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {

lightning/src/ln/channel.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,6 +2122,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
21222122
return &self.holder_signer
21232123
}
21242124

2125+
/// Returns the holder signer for this channel.
2126+
#[cfg(test)]
2127+
pub fn get_mut_signer(&mut self) -> &mut ChannelSignerType<SP> {
2128+
return &mut self.holder_signer
2129+
}
2130+
21252131
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
21262132
/// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases
21272133
/// or prior to any channel actions during `Channel` initialization.

lightning/src/ln/functional_test_utils.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ use crate::util::errors::APIError;
3131
use crate::util::logger::Logger;
3232
use crate::util::scid_utils;
3333
use crate::util::test_channel_signer::TestChannelSigner;
34+
#[cfg(test)]
35+
use crate::util::test_channel_signer::SignerOp;
3436
use crate::util::test_utils;
3537
use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface};
3638
use crate::util::ser::{ReadableArgs, Writeable};
@@ -523,6 +525,75 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
523525
.insert(channel_keys_id.unwrap());
524526
}
525527
}
528+
529+
/// Toggles this node's signer to be available for the given signer operation.
530+
/// This is useful for testing behavior for restoring an async signer that previously
531+
/// could not return a signature immediately.
532+
#[cfg(test)]
533+
pub fn enable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) {
534+
self.set_channel_signer_ops(peer_id, chan_id, signer_op, true);
535+
}
536+
537+
/// Toggles this node's signer to be unavailable, returning `Err` for the given signer operation.
538+
/// This is useful for testing behavior for an async signer that cannot return a signature
539+
/// immediately.
540+
#[cfg(test)]
541+
pub fn disable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) {
542+
self.set_channel_signer_ops(peer_id, chan_id, signer_op, false);
543+
}
544+
545+
/// Changes the channel signer's availability for the specified peer, channel, and signer
546+
/// operation.
547+
///
548+
/// For the specified signer operation, when `available` is set to `true`, the channel signer
549+
/// will behave normally, returning `Ok`. When set to `false`, and the channel signer will
550+
/// act like an off-line remote signer, returning `Err`. This applies to the signer in all
551+
/// relevant places, i.e. the channel manager, chain monitor, and the keys manager.
552+
#[cfg(test)]
553+
fn set_channel_signer_ops(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, available: bool) {
554+
use crate::sign::ChannelSigner;
555+
log_debug!(self.logger, "Setting channel signer for {} as available={}", chan_id, available);
556+
557+
let per_peer_state = self.node.per_peer_state.read().unwrap();
558+
let mut chan_lock = per_peer_state.get(peer_id).unwrap().lock().unwrap();
559+
560+
let mut channel_keys_id = None;
561+
if let Some(chan) = chan_lock.channel_by_id.get_mut(chan_id).map(|phase| phase.context_mut()) {
562+
let signer = chan.get_mut_signer().as_mut_ecdsa().unwrap();
563+
if available {
564+
signer.enable_op(signer_op);
565+
} else {
566+
signer.disable_op(signer_op);
567+
}
568+
channel_keys_id = Some(chan.channel_keys_id);
569+
}
570+
571+
let monitor = self.chain_monitor.chain_monitor.list_monitors().into_iter()
572+
.find(|(_, channel_id)| *channel_id == *chan_id)
573+
.and_then(|(funding_txo, _)| self.chain_monitor.chain_monitor.get_monitor(funding_txo).ok());
574+
if let Some(monitor) = monitor {
575+
monitor.do_mut_signer_call(|signer| {
576+
channel_keys_id = channel_keys_id.or(Some(signer.inner.channel_keys_id()));
577+
if available {
578+
signer.enable_op(signer_op);
579+
} else {
580+
signer.disable_op(signer_op);
581+
}
582+
});
583+
}
584+
585+
let channel_keys_id = channel_keys_id.unwrap();
586+
let mut unavailable_signers_ops = self.keys_manager.unavailable_signers_ops.lock().unwrap();
587+
let entry = unavailable_signers_ops.entry(channel_keys_id).or_insert(new_hash_set());
588+
if available {
589+
entry.remove(&signer_op);
590+
if entry.is_empty() {
591+
unavailable_signers_ops.remove(&channel_keys_id);
592+
}
593+
} else {
594+
entry.insert(signer_op);
595+
};
596+
}
526597
}
527598

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

lightning/src/util/test_channel_signer.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
1818
#[allow(unused_imports)]
1919
use crate::prelude::*;
2020

21-
use core::cmp;
21+
use core::{cmp, fmt};
2222
use crate::sync::{Mutex, Arc};
2323
#[cfg(test)] use crate::sync::MutexGuard;
2424

@@ -74,6 +74,46 @@ pub struct TestChannelSigner {
7474
/// When `true` (the default), the signer will respond immediately with signatures. When `false`,
7575
/// the signer will return an error indicating that it is unavailable.
7676
pub available: Arc<Mutex<bool>>,
77+
/// Set of signer operations that are disabled. If an operation is disabled,
78+
/// the signer will return `Err` when the corresponding method is called.
79+
pub disabled_signer_ops: HashSet<SignerOp>,
80+
}
81+
82+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83+
pub enum SignerOp {
84+
GetPerCommitmentPoint,
85+
ReleaseCommitmentSecret,
86+
ValidateHolderCommitment,
87+
SignCounterpartyCommitment,
88+
ValidateCounterpartyRevocation,
89+
SignHolderCommitment,
90+
SignJusticeRevokedOutput,
91+
SignJusticeRevokedHtlc,
92+
SignHolderHtlcTransaction,
93+
SignCounterpartyHtlcTransaction,
94+
SignClosingTransaction,
95+
SignHolderAnchorInput,
96+
SignChannelAnnouncementWithFundingKey,
97+
}
98+
99+
impl fmt::Display for SignerOp {
100+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101+
match self {
102+
SignerOp::GetPerCommitmentPoint => write!(f, "get_per_commitment_point"),
103+
SignerOp::ReleaseCommitmentSecret => write!(f, "release_commitment_secret"),
104+
SignerOp::ValidateHolderCommitment => write!(f, "validate_holder_commitment"),
105+
SignerOp::SignCounterpartyCommitment => write!(f, "sign_counterparty_commitment"),
106+
SignerOp::ValidateCounterpartyRevocation => write!(f, "validate_counterparty_revocation"),
107+
SignerOp::SignHolderCommitment => write!(f, "sign_holder_commitment"),
108+
SignerOp::SignJusticeRevokedOutput => write!(f, "sign_justice_revoked_output"),
109+
SignerOp::SignJusticeRevokedHtlc => write!(f, "sign_justice_revoked_htlc"),
110+
SignerOp::SignHolderHtlcTransaction => write!(f, "sign_holder_htlc_transaction"),
111+
SignerOp::SignCounterpartyHtlcTransaction => write!(f, "sign_counterparty_htlc_transaction"),
112+
SignerOp::SignClosingTransaction => write!(f, "sign_closing_transaction"),
113+
SignerOp::SignHolderAnchorInput => write!(f, "sign_holder_anchor_input"),
114+
SignerOp::SignChannelAnnouncementWithFundingKey => write!(f, "sign_channel_announcement_with_funding_key"),
115+
}
116+
}
77117
}
78118

79119
impl PartialEq for TestChannelSigner {
@@ -91,6 +131,7 @@ impl TestChannelSigner {
91131
state,
92132
disable_revocation_policy_check: false,
93133
available: Arc::new(Mutex::new(true)),
134+
disabled_signer_ops: new_hash_set(),
94135
}
95136
}
96137

@@ -105,6 +146,7 @@ impl TestChannelSigner {
105146
state,
106147
disable_revocation_policy_check,
107148
available: Arc::new(Mutex::new(true)),
149+
disabled_signer_ops: new_hash_set(),
108150
}
109151
}
110152

@@ -123,6 +165,18 @@ impl TestChannelSigner {
123165
pub fn set_available(&self, available: bool) {
124166
*self.available.lock().unwrap() = available;
125167
}
168+
169+
pub fn enable_op(&mut self, signer_op: SignerOp) {
170+
self.disabled_signer_ops.remove(&signer_op);
171+
}
172+
173+
pub fn disable_op(&mut self, signer_op: SignerOp) {
174+
self.disabled_signer_ops.insert(signer_op);
175+
}
176+
177+
fn is_signer_available(&self, signer_op: SignerOp) -> bool {
178+
!self.disabled_signer_ops.contains(&signer_op)
179+
}
126180
}
127181

128182
impl ChannelSigner for TestChannelSigner {

lightning/src/util/test_utils.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ use std::time::{SystemTime, UNIX_EPOCH};
7979
use bitcoin::psbt::Psbt;
8080
use bitcoin::Sequence;
8181

82+
use super::test_channel_signer::SignerOp;
83+
8284
pub fn pubkey(byte: u8) -> PublicKey {
8385
let secp_ctx = Secp256k1::new();
8486
PublicKey::from_secret_key(&secp_ctx, &privkey(byte))
@@ -1215,6 +1217,7 @@ pub struct TestKeysInterface {
12151217
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
12161218
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
12171219
pub unavailable_signers: Mutex<HashSet<[u8; 32]>>,
1220+
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
12181221
}
12191222

12201223
impl EntropySource for TestKeysInterface {
@@ -1273,10 +1276,15 @@ impl SignerProvider for TestKeysInterface {
12731276
fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> TestChannelSigner {
12741277
let keys = self.backing.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12751278
let state = self.make_enforcement_state_cell(keys.commitment_seed);
1276-
let signer = TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
1279+
let mut signer = TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
12771280
if self.unavailable_signers.lock().unwrap().contains(&channel_keys_id) {
12781281
signer.set_available(false);
12791282
}
1283+
if let Some(ops) = self.unavailable_signers_ops.lock().unwrap().get(&channel_keys_id) {
1284+
for &op in ops {
1285+
signer.disable_op(op);
1286+
}
1287+
}
12801288
signer
12811289
}
12821290

@@ -1316,6 +1324,7 @@ impl TestKeysInterface {
13161324
enforcement_states: Mutex::new(new_hash_map()),
13171325
expectations: Mutex::new(None),
13181326
unavailable_signers: Mutex::new(new_hash_set()),
1327+
unavailable_signers_ops: Mutex::new(new_hash_map()),
13191328
}
13201329
}
13211330

0 commit comments

Comments
 (0)