Skip to content

Commit c71956b

Browse files
author
Yuko Roodt
committed
Added tests to check the bolt 2 specs for Sending Node Channel
1 parent 4a4cdc1 commit c71956b

File tree

5 files changed

+105
-3
lines changed

5 files changed

+105
-3
lines changed

fuzz/fuzz_targets/full_stack_target.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@ impl KeysInterface for KeyProvider {
281281
fill_bytes(&mut session_key);
282282
SecretKey::from_slice(&session_key).unwrap()
283283
}
284+
285+
fn get_channel_id(&self) -> [u8; 32] {
286+
let mut channel_id = [0; 32];
287+
fill_bytes(&mut channel_id);
288+
channel_id
289+
}
284290
}
285291

286292
#[inline]

src/chain/keysinterface.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ pub trait KeysInterface: Send + Sync {
8080
fn get_channel_keys(&self, inbound: bool) -> ChannelKeys;
8181
/// Get a secret for construting an onion packet
8282
fn get_session_key(&self) -> SecretKey;
83+
/// Get a unique channel id
84+
fn get_channel_id(&self) -> [u8; 32];
8385
}
8486

8587
/// Set of lightning keys needed to operate a channel as described in BOLT 3
@@ -124,6 +126,8 @@ pub struct KeysManager {
124126
channel_child_index: AtomicUsize,
125127
session_master_key: ExtendedPrivKey,
126128
session_child_index: AtomicUsize,
129+
channel_id_master_key: ExtendedPrivKey,
130+
channel_id_child_index: AtomicUsize,
127131

128132
logger: Arc<Logger>,
129133
}
@@ -151,6 +155,7 @@ impl KeysManager {
151155
};
152156
let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3)).expect("Your RNG is busted");
153157
let session_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4)).expect("Your RNG is busted");
158+
let channel_id_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5)).expect("Your RNG is busted");
154159
KeysManager {
155160
secp_ctx,
156161
node_secret,
@@ -160,6 +165,8 @@ impl KeysManager {
160165
channel_child_index: AtomicUsize::new(0),
161166
session_master_key,
162167
session_child_index: AtomicUsize::new(0),
168+
channel_id_master_key,
169+
channel_id_child_index: AtomicUsize::new(0),
163170

164171
logger,
165172
}
@@ -246,4 +253,18 @@ impl KeysInterface for KeysManager {
246253
sha.input(&child_privkey.secret_key[..]);
247254
SecretKey::from_slice(&Sha256::from_engine(sha).into_inner()).expect("Your RNG is busted")
248255
}
256+
257+
fn get_channel_id(&self) -> [u8; 32] {
258+
let mut sha = Sha256::engine();
259+
260+
let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
261+
sha.input(&byte_utils::be32_to_array(now.subsec_nanos()));
262+
sha.input(&byte_utils::be64_to_array(now.as_secs()));
263+
264+
let child_ix = self.channel_id_child_index.fetch_add(1, Ordering::AcqRel);
265+
let child_privkey = self.channel_id_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32)).expect("Your RNG is busted");
266+
sha.input(&child_privkey.secret_key[..]);
267+
268+
(Sha256::from_engine(sha).into_inner())
269+
}
249270
}

src/ln/channel.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use ln::chan_utils;
2323
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
2424
use chain::transaction::OutPoint;
2525
use chain::keysinterface::{ChannelKeys, KeysInterface};
26-
use util::{transaction_utils,rng};
26+
use util::transaction_utils;
2727
use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor};
2828
use util::logger::Logger;
2929
use util::errors::APIError;
@@ -350,7 +350,10 @@ pub const OUR_MAX_HTLCS: u16 = 50; //TODO
350350
const UNCONF_THRESHOLD: u32 = 6;
351351
/// The amount of time we require our counterparty wait to claim their money (ie time between when
352352
/// we, or our watchtower, must check for them having broadcast a theft transaction).
353+
#[cfg(not(test))]
353354
const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO?
355+
#[cfg(test)]
356+
pub const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO?
354357
/// The amount of time we're willing to wait to claim money back to us
355358
const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 14;
356359
/// Exposing these two constants for use in test in ChannelMonitor
@@ -444,7 +447,7 @@ impl Channel {
444447
user_id: user_id,
445448
config: config.channel_options.clone(),
446449

447-
channel_id: rng::rand_u832(),
450+
channel_id: keys_provider.get_channel_id(),
448451
channel_state: ChannelState::OurInitSent as u32,
449452
channel_outbound: true,
450453
secp_ctx: secp_ctx,
@@ -3958,6 +3961,7 @@ mod tests {
39583961

39593962
fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { self.chan_keys.clone() }
39603963
fn get_session_key(&self) -> SecretKey { panic!(); }
3964+
fn get_channel_id(&self) -> [u8; 32] { [0; 32] }
39613965
}
39623966

39633967
#[test]

src/ln/functional_tests.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use chain::transaction::OutPoint;
77
use chain::chaininterface::{ChainListener, ChainWatchInterface};
88
use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor};
99
use chain::keysinterface;
10-
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
10+
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC, BREAKDOWN_TIMEOUT};
1111
use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash};
1212
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS, ManyChannelMonitor};
1313
use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
@@ -6716,6 +6716,68 @@ fn test_onion_failure() {
67166716
}, ||{}, true, Some(21), None);
67176717
}
67186718

6719+
#[test]
6720+
#[should_panic]
6721+
fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be on its own as we are catching a panic
6722+
let nodes = create_network(2);
6723+
//Force duplicate channel ids
6724+
for node in nodes.iter() {
6725+
*node.keys_manager.override_channel_id_priv.lock().unwrap() = Some([0; 32]);
6726+
}
6727+
6728+
// BOLT #2 spec: Sending node must ensure temporary_channel_id is unique from any other channel ID with the same peer.
6729+
let channel_value_satoshis=10000;
6730+
let push_msat=10001;
6731+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42).unwrap();
6732+
let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
6733+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel).unwrap();
6734+
6735+
//Create a second channel with a channel_id collision
6736+
assert!(nodes[0].node.create_channel(nodes[0].node.get_our_node_id(), channel_value_satoshis, push_msat, 42).is_err());
6737+
}
6738+
6739+
#[test]
6740+
fn bolt2_open_channel_sending_node_checks_part2() {
6741+
let nodes = create_network(2);
6742+
6743+
// BOLT #2 spec: Sending node must set funding_satoshis to less than 2^24 satoshis
6744+
let channel_value_satoshis=2^24;
6745+
let push_msat=10001;
6746+
assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42).is_err());
6747+
6748+
// BOLT #2 spec: Sending node must set push_msat to equal or less than 1000 * funding_satoshis
6749+
let channel_value_satoshis=10000;
6750+
// Test when push_msat is equal to 1000 * funding_satoshis.
6751+
let push_msat=1000*channel_value_satoshis+1;
6752+
assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42).is_err());
6753+
6754+
// BOLT #2 spec: Sending node must set set channel_reserve_satoshis greater than or equal to dust_limit_satoshis
6755+
let channel_value_satoshis=10000;
6756+
let push_msat=10001;
6757+
assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42).is_ok()); //Create a valid channel
6758+
let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
6759+
assert!(node0_to_1_send_open_channel.channel_reserve_satoshis>=node0_to_1_send_open_channel.dust_limit_satoshis);
6760+
6761+
// BOLT #2 spec: Sending node must set undefined bits in channel_flags to 0
6762+
// Only the least-significant bit of channel_flags is currently defined resulting in channel_flags only having one of two possible states 0 or 1
6763+
assert!(node0_to_1_send_open_channel.channel_flags<=1);
6764+
6765+
// BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver.
6766+
assert!(BREAKDOWN_TIMEOUT>0);
6767+
assert!(node0_to_1_send_open_channel.to_self_delay==BREAKDOWN_TIMEOUT);
6768+
6769+
// BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within.
6770+
let chain_hash=genesis_block(Network::Testnet).header.bitcoin_hash();
6771+
assert_eq!(node0_to_1_send_open_channel.chain_hash,chain_hash);
6772+
6773+
// BOLT #2 spec: Sending node must set funding_pubkey, revocation_basepoint, htlc_basepoint, payment_basepoint, and delayed_payment_basepoint to valid DER-encoded, compressed, secp256k1 pubkeys.
6774+
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.funding_pubkey.serialize()).is_ok());
6775+
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.revocation_basepoint.serialize()).is_ok());
6776+
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.htlc_basepoint.serialize()).is_ok());
6777+
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.payment_basepoint.serialize()).is_ok());
6778+
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.delayed_payment_basepoint.serialize()).is_ok());
6779+
}
6780+
67196781
// BOLT 2 Requirements for the Sender when constructing and sending an update_add_htlc message.
67206782
// BOLT 2 Requirement: MUST NOT offer amount_msat it cannot pay for in the remote commitment transaction at the current feerate_per_kw (see "Updating Fees") while maintaining its channel reserve.
67216783
//TODO: I don't believe this is explicitly enforced when sending an HTLC but as the Fee aspect of the BOLT specs is in flux leaving this as a TODO.

src/util/test_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ impl Logger for TestLogger {
215215
pub struct TestKeysInterface {
216216
backing: keysinterface::KeysManager,
217217
pub override_session_priv: Mutex<Option<SecretKey>>,
218+
pub override_channel_id_priv: Mutex<Option<[u8; 32]>>,
218219
}
219220

220221
impl keysinterface::KeysInterface for TestKeysInterface {
@@ -229,13 +230,21 @@ impl keysinterface::KeysInterface for TestKeysInterface {
229230
None => self.backing.get_session_key()
230231
}
231232
}
233+
234+
fn get_channel_id(&self) -> [u8; 32] {
235+
match *self.override_channel_id_priv.lock().unwrap() {
236+
Some(key) => key.clone(),
237+
None => self.backing.get_channel_id()
238+
}
239+
}
232240
}
233241

234242
impl TestKeysInterface {
235243
pub fn new(seed: &[u8; 32], network: Network, logger: Arc<Logger>) -> Self {
236244
Self {
237245
backing: keysinterface::KeysManager::new(seed, network, logger),
238246
override_session_priv: Mutex::new(None),
247+
override_channel_id_priv: Mutex::new(None),
239248
}
240249
}
241250
}

0 commit comments

Comments
 (0)