Skip to content

Commit c336da6

Browse files
committed
Temp changes for open channel test
1 parent 5590bc5 commit c336da6

File tree

3 files changed

+173
-1
lines changed

3 files changed

+173
-1
lines changed

lightning/src/ln/async_signer_tests.rs

+52
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,58 @@ use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureR
2020
use crate::ln::functional_test_utils::*;
2121
use crate::ln::msgs::ChannelMessageHandler;
2222
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
23+
use crate::util::test_channel_signer::{EnforcementState, ops};
24+
25+
26+
#[cfg(feature = "std")]
27+
#[test]
28+
fn test_open_channel() {
29+
// Simulate acquiring the signature for `funding_created` asynchronously.
30+
let chanmon_cfgs = create_chanmon_cfgs(2);
31+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
32+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
33+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
34+
35+
// Open an outbound channel simulating an async signer.
36+
let channel_id_0 = EnforcementState::with_default_unavailable(
37+
ops::GET_PER_COMMITMENT_POINT,
38+
|| nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None)
39+
).expect("Failed to create channel");
40+
41+
{
42+
let msgs = nodes[0].node.get_and_clear_pending_msg_events();
43+
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
44+
}
45+
46+
nodes[0].set_channel_signer_ops_available(&nodes[1].node.get_our_node_id(), &channel_id_0, ops::GET_PER_COMMITMENT_POINT, true);
47+
nodes[0].node.signer_unblocked(None);
48+
49+
// nodes[0] --- open_channel --> nodes[1]
50+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
51+
52+
// Handle an inbound channel simulating an async signer.
53+
EnforcementState::with_default_unavailable(
54+
ops::GET_PER_COMMITMENT_POINT,
55+
|| nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg)
56+
);
57+
58+
{
59+
let msgs = nodes[1].node.get_and_clear_pending_msg_events();
60+
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
61+
}
62+
63+
let channel_id_1 = {
64+
let channels = nodes[1].node.list_channels();
65+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
66+
channels[0].channel_id
67+
};
68+
69+
nodes[1].set_channel_signer_ops_available(&nodes[0].node.get_our_node_id(), &channel_id_1, ops::GET_PER_COMMITMENT_POINT, true);
70+
nodes[1].node.signer_unblocked(None);
71+
72+
// nodes[0] <-- accept_channel --- nodes[1]
73+
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
74+
}
2375

2476
#[test]
2577
fn test_async_commitment_signature_for_funding_created() {

lightning/src/ln/functional_test_utils.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::util::errors::APIError;
3030
#[cfg(test)]
3131
use crate::util::logger::Logger;
3232
use crate::util::scid_utils;
33-
use crate::util::test_channel_signer::TestChannelSigner;
33+
use crate::util::test_channel_signer::{TestChannelSigner, ops};
3434
use crate::util::test_utils;
3535
use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface};
3636
use crate::util::ser::{ReadableArgs, Writeable};
@@ -523,6 +523,28 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
523523
.insert(channel_keys_id.unwrap());
524524
}
525525
}
526+
527+
/// Changes the channel signer's availability for the specified peer and channel.
528+
///
529+
/// When `available` is set to `true`, the channel signer will behave normally. When set to
530+
/// `false`, the channel signer will act like an off-line remote signer and will return `Err` for
531+
/// several of the signing methods. Currently, only `get_per_commitment_point` and
532+
/// `release_commitment_secret` are affected by this setting.
533+
/// several of the signing methods.
534+
#[cfg(test)]
535+
pub fn set_channel_signer_ops_available(&self, peer_id: &PublicKey, chan_id: &ChannelId, mask: u32, available: bool) {
536+
let per_peer_state = self.node.per_peer_state.read().unwrap();
537+
let chan_lock = per_peer_state.get(peer_id).unwrap().lock().unwrap();
538+
let signer = (|| {
539+
match chan_lock.channel_by_id.get(chan_id) {
540+
Some(phase) => phase.context().get_signer(),
541+
None => panic!("Couldn't find a channel with id {}", chan_id),
542+
}
543+
})();
544+
log_debug!(self.logger, "Setting channel signer for {} as {}available for {} (mask={})",
545+
chan_id, if available { "" } else { "un" }, ops::string_from(mask), mask);
546+
signer.as_ecdsa().unwrap().set_ops_available(mask, available);
547+
}
526548
}
527549

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

lightning/src/util/test_channel_signer.rs

+98
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
1818
#[allow(unused_imports)]
1919
use crate::prelude::*;
2020

21+
use core::cell::RefCell;
2122
use core::cmp;
2223
use crate::sync::{Mutex, Arc};
2324
#[cfg(test)] use crate::sync::MutexGuard;
@@ -76,6 +77,51 @@ pub struct TestChannelSigner {
7677
pub available: Arc<Mutex<bool>>,
7778
}
7879

80+
/// Channel signer operations that can be individually enabled and disabled. If a particular value
81+
/// is set in the `TestChannelSigner::unavailable` bitmask, then that operation will return an
82+
/// error.
83+
pub mod ops {
84+
pub const GET_PER_COMMITMENT_POINT: u32 = 1 << 0;
85+
pub const RELEASE_COMMITMENT_SECRET: u32 = 1 << 1;
86+
pub const VALIDATE_HOLDER_COMMITMENT: u32 = 1 << 2;
87+
pub const SIGN_COUNTERPARTY_COMMITMENT: u32 = 1 << 3;
88+
pub const VALIDATE_COUNTERPARTY_REVOCATION: u32 = 1 << 4;
89+
pub const SIGN_HOLDER_COMMITMENT_AND_HTLCS: u32 = 1 << 5;
90+
pub const SIGN_JUSTICE_REVOKED_OUTPUT: u32 = 1 << 6;
91+
pub const SIGN_JUSTICE_REVOKED_HTLC: u32 = 1 << 7;
92+
pub const SIGN_HOLDER_HTLC_TRANSACTION: u32 = 1 << 8;
93+
pub const SIGN_COUNTERPARTY_HTLC_TRANSATION: u32 = 1 << 9;
94+
pub const SIGN_CLOSING_TRANSACTION: u32 = 1 << 10;
95+
pub const SIGN_HOLDER_ANCHOR_INPUT: u32 = 1 << 11;
96+
pub const SIGN_CHANNEL_ANNOUNCMENT_WITH_FUNDING_KEY: u32 = 1 << 12;
97+
98+
#[cfg(test)]
99+
pub fn string_from(mask: u32) -> String {
100+
if mask == 0 {
101+
return "nothing".to_owned();
102+
}
103+
if mask == !(0 as u32) {
104+
return "everything".to_owned();
105+
}
106+
107+
vec![
108+
if (mask & GET_PER_COMMITMENT_POINT) != 0 { Some("get_per_commitment_point") } else { None },
109+
if (mask & RELEASE_COMMITMENT_SECRET) != 0 { Some("release_commitment_secret") } else { None },
110+
if (mask & VALIDATE_HOLDER_COMMITMENT) != 0 { Some("validate_holder_commitment") } else { None },
111+
if (mask & SIGN_COUNTERPARTY_COMMITMENT) != 0 { Some("sign_counterparty_commitment") } else { None },
112+
if (mask & VALIDATE_COUNTERPARTY_REVOCATION) != 0 { Some("validate_counterparty_revocation") } else { None },
113+
if (mask & SIGN_HOLDER_COMMITMENT_AND_HTLCS) != 0 { Some("sign_holder_commitment_and_htlcs") } else { None },
114+
if (mask & SIGN_JUSTICE_REVOKED_OUTPUT) != 0 { Some("sign_justice_revoked_output") } else { None },
115+
if (mask & SIGN_JUSTICE_REVOKED_HTLC) != 0 { Some("sign_justice_revoked_htlc") } else { None },
116+
if (mask & SIGN_HOLDER_HTLC_TRANSACTION) != 0 { Some("sign_holder_htlc_transaction") } else { None },
117+
if (mask & SIGN_COUNTERPARTY_HTLC_TRANSATION) != 0 { Some("sign_counterparty_htlc_transation") } else { None },
118+
if (mask & SIGN_CLOSING_TRANSACTION) != 0 { Some("sign_closing_transaction") } else { None },
119+
if (mask & SIGN_HOLDER_ANCHOR_INPUT) != 0 { Some("sign_holder_anchor_input") } else { None },
120+
if (mask & SIGN_CHANNEL_ANNOUNCMENT_WITH_FUNDING_KEY) != 0 { Some("sign_channel_announcment_with_funding_key") } else { None },
121+
].iter().flatten().map(|s| s.to_string()).collect::<Vec<_>>().join(", ")
122+
}
123+
}
124+
79125
impl PartialEq for TestChannelSigner {
80126
fn eq(&self, o: &Self) -> bool {
81127
Arc::ptr_eq(&self.state, &o.state)
@@ -123,12 +169,29 @@ impl TestChannelSigner {
123169
pub fn set_available(&self, available: bool) {
124170
*self.available.lock().unwrap() = available;
125171
}
172+
173+
#[cfg(test)]
174+
pub fn set_ops_available(&self, mask: u32, available: bool) {
175+
let mut state = self.get_enforcement_state();
176+
if available {
177+
state.unavailable_signer_ops &= !mask; // clear the bits that are now available
178+
} else {
179+
state.unavailable_signer_ops |= mask; // set the bits that are now unavailable
180+
}
181+
}
182+
183+
fn is_signer_available(&self, ops_mask: u32) -> bool {
184+
self.state.lock().unwrap().is_signer_available(ops_mask)
185+
}
126186
}
127187

128188
impl ChannelSigner for TestChannelSigner {
129189
fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<PublicKey, ()> {
130190
// TODO: implement a mask in EnforcementState to let you test signatures being
131191
// unavailable
192+
if !self.is_signer_available(ops::GET_PER_COMMITMENT_POINT) {
193+
return Err(());
194+
}
132195
self.inner.get_per_commitment_point(idx, secp_ctx)
133196
}
134197

@@ -379,16 +442,51 @@ pub struct EnforcementState {
379442
pub last_holder_revoked_commitment: u64,
380443
/// The last validated holder commitment number, backwards counting
381444
pub last_holder_commitment: u64,
445+
/// A flag array that indicates which signing operations are currently *not* available in the
446+
/// channel. When a method's bit is set, then the signer will act as if the signature is
447+
/// unavailable and return an error result.
448+
pub unavailable_signer_ops: u32,
382449
}
383450

384451
impl EnforcementState {
452+
#[cfg(feature = "std")]
453+
thread_local! {
454+
static DEFAULT_UNAVAILABLE_SIGNER_OPS: RefCell<u32> = RefCell::new(0);
455+
}
456+
385457
/// Enforcement state for a new channel
386458
pub fn new() -> Self {
387459
EnforcementState {
388460
last_counterparty_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER,
389461
last_counterparty_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER,
390462
last_holder_revoked_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER,
391463
last_holder_commitment: INITIAL_REVOKED_COMMITMENT_NUMBER,
464+
unavailable_signer_ops: {
465+
#[cfg(feature = "std")]
466+
{
467+
EnforcementState::DEFAULT_UNAVAILABLE_SIGNER_OPS.with(|ops| *ops.borrow())
468+
}
469+
#[cfg(not(feature = "std"))]
470+
{
471+
0
472+
}
473+
}
392474
}
393475
}
476+
477+
pub fn is_signer_available(&self, ops_mask: u32) -> bool {
478+
(self.unavailable_signer_ops & ops_mask) == 0
479+
}
480+
481+
#[cfg(feature = "std")]
482+
pub fn with_default_unavailable<F, R>(ops: u32, f: F) -> R
483+
where F: FnOnce() -> R
484+
{
485+
EnforcementState::DEFAULT_UNAVAILABLE_SIGNER_OPS.with(|unavailable_ops| {
486+
unavailable_ops.replace(ops);
487+
let res = f();
488+
unavailable_ops.replace(0);
489+
res
490+
})
491+
}
394492
}

0 commit comments

Comments
 (0)