Skip to content

Commit f151c02

Browse files
authored
Merge pull request #764 from lightning-signer/revoke-enforcement
Revocation enforcement
2 parents 25c9a37 + 142b0d6 commit f151c02

File tree

9 files changed

+231
-111
lines changed

9 files changed

+231
-111
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use lightning::chain::keysinterface::{KeysInterface, InMemoryChannelKeys};
3838
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
3939
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4040
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init};
41-
use lightning::util::enforcing_trait_impls::EnforcingChannelKeys;
41+
use lightning::util::enforcing_trait_impls::{EnforcingChannelKeys, INITIAL_REVOKED_COMMITMENT_NUMBER};
4242
use lightning::util::errors::APIError;
4343
use lightning::util::events;
4444
use lightning::util::logger::Logger;
@@ -146,6 +146,7 @@ impl chain::Watch for TestChainMonitor {
146146
struct KeyProvider {
147147
node_id: u8,
148148
rand_bytes_id: atomic::AtomicU8,
149+
revoked_commitments: Mutex<HashMap<[u8;32], Arc<Mutex<u64>>>>,
149150
}
150151
impl KeysInterface for KeyProvider {
151152
type ChanKeySigner = EnforcingChannelKeys;
@@ -168,26 +169,52 @@ impl KeysInterface for KeyProvider {
168169

169170
fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys {
170171
let secp_ctx = Secp256k1::signing_only();
171-
EnforcingChannelKeys::new(InMemoryChannelKeys::new(
172+
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
173+
let keys = InMemoryChannelKeys::new(
172174
&secp_ctx,
173175
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, self.node_id]).unwrap(),
174176
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, self.node_id]).unwrap(),
175177
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, 6, self.node_id]).unwrap(),
176178
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, self.node_id]).unwrap(),
177179
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, self.node_id]).unwrap(),
178-
[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, self.node_id],
180+
[id, 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, self.node_id],
179181
channel_value_satoshis,
180182
(0, 0),
181-
))
183+
);
184+
let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
185+
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment, false)
182186
}
183187

184188
fn get_secure_random_bytes(&self) -> [u8; 32] {
185189
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
186190
[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, id, 11, self.node_id]
187191
}
188192

189-
fn read_chan_signer(&self, data: &[u8]) -> Result<EnforcingChannelKeys, DecodeError> {
190-
EnforcingChannelKeys::read(&mut std::io::Cursor::new(data))
193+
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::ChanKeySigner, DecodeError> {
194+
let mut reader = std::io::Cursor::new(buffer);
195+
196+
let inner: InMemoryChannelKeys = Readable::read(&mut reader)?;
197+
let revoked_commitment = self.make_revoked_commitment_cell(inner.commitment_seed);
198+
199+
let last_commitment_number = Readable::read(&mut reader)?;
200+
201+
Ok(EnforcingChannelKeys {
202+
inner,
203+
last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
204+
revoked_commitment,
205+
disable_revocation_policy_check: false,
206+
})
207+
}
208+
}
209+
210+
impl KeyProvider {
211+
fn make_revoked_commitment_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<u64>> {
212+
let mut revoked_commitments = self.revoked_commitments.lock().unwrap();
213+
if !revoked_commitments.contains_key(&commitment_seed) {
214+
revoked_commitments.insert(commitment_seed, Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER)));
215+
}
216+
let cell = revoked_commitments.get(&commitment_seed).unwrap();
217+
Arc::clone(cell)
191218
}
192219
}
193220

@@ -288,22 +315,22 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
288315
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
289316
let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone(), Arc::new(TestPersister{})));
290317

291-
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU8::new(0) });
318+
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU8::new(0), revoked_commitments: Mutex::new(HashMap::new()) });
292319
let mut config = UserConfig::default();
293320
config.channel_options.fee_proportional_millionths = 0;
294321
config.channel_options.announced_channel = true;
295322
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
296323
(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0),
297-
monitor)
324+
monitor, keys_manager)
298325
} }
299326
}
300327

301328
macro_rules! reload_node {
302-
($ser: expr, $node_id: expr, $old_monitors: expr) => { {
329+
($ser: expr, $node_id: expr, $old_monitors: expr, $keys_manager: expr) => { {
330+
let keys_manager = Arc::clone(& $keys_manager);
303331
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
304332
let chain_monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone(), Arc::new(TestPersister{})));
305333

306-
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU8::new(0) });
307334
let mut config = UserConfig::default();
308335
config.channel_options.fee_proportional_millionths = 0;
309336
config.channel_options.announced_channel = true;
@@ -440,9 +467,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
440467

441468
// 3 nodes is enough to hit all the possible cases, notably unknown-source-unknown-dest
442469
// forwarding.
443-
let (node_a, mut monitor_a) = make_node!(0);
444-
let (node_b, mut monitor_b) = make_node!(1);
445-
let (node_c, mut monitor_c) = make_node!(2);
470+
let (node_a, mut monitor_a, keys_manager_a) = make_node!(0);
471+
let (node_b, mut monitor_b, keys_manager_b) = make_node!(1);
472+
let (node_c, mut monitor_c, keys_manager_c) = make_node!(2);
446473

447474
let mut nodes = [node_a, node_b, node_c];
448475

@@ -793,7 +820,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
793820
chan_a_disconnected = true;
794821
drain_msg_events_on_disconnect!(0);
795822
}
796-
let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a);
823+
let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a, keys_manager_a);
797824
nodes[0] = new_node_a;
798825
monitor_a = new_monitor_a;
799826
},
@@ -810,7 +837,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
810837
nodes[2].get_and_clear_pending_msg_events();
811838
bc_events.clear();
812839
}
813-
let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b);
840+
let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b, keys_manager_b);
814841
nodes[1] = new_node_b;
815842
monitor_b = new_monitor_b;
816843
},
@@ -820,7 +847,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
820847
chan_b_disconnected = true;
821848
drain_msg_events_on_disconnect!(2);
822849
}
823-
let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c);
850+
let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c, keys_manager_c);
824851
nodes[2] = new_node_c;
825852
monitor_c = new_monitor_c;
826853
},

lightning-persister/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ mod tests {
198198
let persister_1 = FilesystemPersister::new("test_filesystem_persister_1".to_string());
199199
let chanmon_cfgs = create_chanmon_cfgs(2);
200200
let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
201-
let chain_mon_0 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &persister_0);
202-
let chain_mon_1 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[1].chain_source), &chanmon_cfgs[1].tx_broadcaster, &chanmon_cfgs[1].logger, &chanmon_cfgs[1].fee_estimator, &persister_1);
201+
let chain_mon_0 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &persister_0, &node_cfgs[0].keys_manager);
202+
let chain_mon_1 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[1].chain_source), &chanmon_cfgs[1].tx_broadcaster, &chanmon_cfgs[1].logger, &chanmon_cfgs[1].fee_estimator, &persister_1, &node_cfgs[1].keys_manager);
203203
node_cfgs[0].chain_monitor = chain_mon_0;
204204
node_cfgs[1].chain_monitor = chain_mon_1;
205205
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);

lightning/src/chain/keysinterface.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub trait ChannelKeys : Send+Clone + Writeable {
254254
/// state. Thus, needs its own method as sign_holder_commitment may enforce that we only ever
255255
/// get called once.
256256
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
257-
fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
257+
fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
258258

259259
/// Create a signature for the given input in a transaction spending an HTLC or commitment
260260
/// transaction output when our counterparty broadcasts an old state.
@@ -499,18 +499,22 @@ impl ChannelKeys for InMemoryChannelKeys {
499499
fn sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
500500
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
501501
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
502-
let sig = commitment_tx.trust().built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
503-
let channel_parameters = self.get_channel_parameters();
504502
let trusted_tx = commitment_tx.trust();
503+
let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
504+
let channel_parameters = self.get_channel_parameters();
505505
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
506506
Ok((sig, htlc_sigs))
507507
}
508508

509509
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
510-
fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
510+
fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
511511
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
512-
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
513-
Ok(commitment_tx.trust().built_transaction().sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
512+
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
513+
let trusted_tx = commitment_tx.trust();
514+
let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
515+
let channel_parameters = self.get_channel_parameters();
516+
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
517+
Ok((sig, htlc_sigs))
514518
}
515519

516520
fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ fn test_monitor_and_persister_update_fail() {
109109
let new_monitor = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
110110
&mut ::std::io::Cursor::new(&w.0), &test_utils::OnlyReadsKeysInterface {}).unwrap().1;
111111
assert!(new_monitor == *monitor);
112-
let chain_mon = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister);
112+
let chain_mon = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister, &node_cfgs[0].keys_manager);
113113
assert!(chain_mon.watch_channel(outpoint, new_monitor).is_ok());
114114
chain_mon
115115
};

lightning/src/ln/functional_test_utils.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use ln::msgs;
2121
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
2222
use util::enforcing_trait_impls::EnforcingChannelKeys;
2323
use util::test_utils;
24-
use util::test_utils::{TestChainMonitor, OnlyReadsKeysInterface};
24+
use util::test_utils::TestChainMonitor;
2525
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
2626
use util::errors::APIError;
2727
use util::config::UserConfig;
@@ -96,14 +96,15 @@ pub struct TestChanMonCfg {
9696
pub chain_source: test_utils::TestChainSource,
9797
pub persister: test_utils::TestPersister,
9898
pub logger: test_utils::TestLogger,
99+
pub keys_manager: test_utils::TestKeysInterface,
99100
}
100101

101102
pub struct NodeCfg<'a> {
102103
pub chain_source: &'a test_utils::TestChainSource,
103104
pub tx_broadcaster: &'a test_utils::TestBroadcaster,
104105
pub fee_estimator: &'a test_utils::TestFeeEstimator,
105106
pub chain_monitor: test_utils::TestChainMonitor<'a>,
106-
pub keys_manager: test_utils::TestKeysInterface,
107+
pub keys_manager: &'a test_utils::TestKeysInterface,
107108
pub logger: &'a test_utils::TestLogger,
108109
pub node_seed: [u8; 32],
109110
}
@@ -172,7 +173,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
172173
let mut w = test_utils::TestVecWriter(Vec::new());
173174
old_monitor.write(&mut w).unwrap();
174175
let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
175-
&mut ::std::io::Cursor::new(&w.0), &OnlyReadsKeysInterface {}).unwrap();
176+
&mut ::std::io::Cursor::new(&w.0), self.keys_manager).unwrap();
176177
deserialized_monitors.push(deserialized_monitor);
177178
}
178179
}
@@ -205,7 +206,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
205206
txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone())
206207
};
207208
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
208-
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister);
209+
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager);
209210
for deserialized_monitor in deserialized_monitors.drain(..) {
210211
if let Err(_) = chain_monitor.watch_channel(deserialized_monitor.get_funding_txo().0, deserialized_monitor) {
211212
panic!();
@@ -1132,7 +1133,10 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec<TestChanMonCfg> {
11321133
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
11331134
let logger = test_utils::TestLogger::with_id(format!("node {}", i));
11341135
let persister = test_utils::TestPersister::new();
1135-
chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_source, logger, persister });
1136+
let seed = [i as u8; 32];
1137+
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
1138+
1139+
chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager });
11361140
}
11371141

11381142
chan_mon_cfgs
@@ -1142,10 +1146,9 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec<TestChanMon
11421146
let mut nodes = Vec::new();
11431147

11441148
for i in 0..node_count {
1149+
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[i].chain_source), &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator, &chanmon_cfgs[i].persister, &chanmon_cfgs[i].keys_manager);
11451150
let seed = [i as u8; 32];
1146-
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
1147-
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[i].chain_source), &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator, &chanmon_cfgs[i].persister);
1148-
nodes.push(NodeCfg { chain_source: &chanmon_cfgs[i].chain_source, logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, chain_monitor, keys_manager, node_seed: seed });
1151+
nodes.push(NodeCfg { chain_source: &chanmon_cfgs[i].chain_source, logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, chain_monitor, keys_manager: &chanmon_cfgs[i].keys_manager, node_seed: seed });
11491152
}
11501153

11511154
nodes
@@ -1158,7 +1161,7 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
11581161
default_config.channel_options.announced_channel = true;
11591162
default_config.peer_channel_config_limits.force_announced_channel_preference = false;
11601163
default_config.own_channel_config.our_htlc_minimum_msat = 1000; // sanitization being done by the sender, to exerce receiver logic we need to lift of limit
1161-
let node = ChannelManager::new(Network::Testnet, cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, &cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0);
1164+
let node = ChannelManager::new(Network::Testnet, cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0);
11621165
chanmgrs.push(node);
11631166
}
11641167

0 commit comments

Comments
 (0)