Skip to content

Commit 5610ca1

Browse files
committed
Combine ChannelManager's block hash and height
There is a possible race condition when both the latest block hash and height are needed. Combine these in one struct and place them behind a single lock.
1 parent 24351f5 commit 5610ca1

File tree

6 files changed

+85
-73
lines changed

6 files changed

+85
-73
lines changed

background-processor/src/lib.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ mod tests {
131131
use lightning::chain::keysinterface::{Sign, InMemorySigner, KeysInterface, KeysManager};
132132
use lightning::chain::transaction::OutPoint;
133133
use lightning::get_event_msg;
134-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, SimpleArcChannelManager};
134+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, SimpleArcChannelManager};
135135
use lightning::ln::features::InitFeatures;
136136
use lightning::ln::msgs::ChannelMessageHandler;
137137
use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor};
@@ -192,14 +192,12 @@ mod tests {
192192
let persister = Arc::new(FilesystemPersister::new(format!("{}_persister_{}", persist_dir, i)));
193193
let seed = [i as u8; 32];
194194
let network = Network::Testnet;
195-
let genesis_block = genesis_block(network);
196-
let now = Duration::from_secs(genesis_block.header.time as u64);
195+
let now = Duration::from_secs(genesis_block(network).header.time as u64);
197196
let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
198197
let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new(Some(chain_source.clone()), tx_broadcaster.clone(), logger.clone(), fee_estimator.clone(), persister.clone()));
199198
let params = ChainParameters {
200199
network,
201-
latest_hash: genesis_block.block_hash(),
202-
latest_height: 0,
200+
best_block: BestBlock::from_genesis(network),
203201
};
204202
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster, logger.clone(), keys_manager.clone(), UserConfig::default(), params));
205203
let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new() )};

fuzz/src/chanmon_consistency.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr,
3636
use lightning::chain::transaction::OutPoint;
3737
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3838
use lightning::chain::keysinterface::{KeysInterface, InMemorySigner};
39-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
39+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
4040
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4141
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init};
4242
use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER};
@@ -322,8 +322,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
322322
let network = Network::Bitcoin;
323323
let params = ChainParameters {
324324
network,
325-
latest_hash: genesis_block(network).block_hash(),
326-
latest_height: 0,
325+
best_block: BestBlock::from_genesis(network),
327326
};
328327
(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params),
329328
monitor, keys_manager)

fuzz/src/full_stack.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget,
3232
use lightning::chain::chainmonitor;
3333
use lightning::chain::transaction::OutPoint;
3434
use lightning::chain::keysinterface::{InMemorySigner, KeysInterface};
35-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
35+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
3636
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
3737
use lightning::ln::msgs::DecodeError;
3838
use lightning::routing::router::get_route;
@@ -355,15 +355,13 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
355355
config.channel_options.announced_channel = get_slice!(1)[0] != 0;
356356
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
357357
let network = Network::Bitcoin;
358-
let genesis_hash = genesis_block(network).block_hash();
359358
let params = ChainParameters {
360359
network,
361-
latest_hash: genesis_hash,
362-
latest_height: 0,
360+
best_block: BestBlock::from_genesis(network),
363361
};
364362
let channelmanager = Arc::new(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params));
365363
let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret());
366-
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_hash, None, Arc::clone(&logger)));
364+
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_block(network).block_hash(), None, Arc::clone(&logger)));
367365

368366
let peers = RefCell::new([false; 256]);
369367
let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler {

lightning/src/ln/channelmanager.rs

+70-51
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,6 @@ struct PeerState {
352352
latest_features: InitFeatures,
353353
}
354354

355-
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
356-
const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assume they're the same) for ChannelManager::latest_block_height";
357-
358355
/// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
359356
/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
360357
/// lifetimes). Other times you can afford a reference, which is more efficient, in which case
@@ -424,10 +421,9 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
424421
tx_broadcaster: T,
425422

426423
#[cfg(test)]
427-
pub(super) latest_block_height: AtomicUsize,
424+
pub(super) best_block: RwLock<BestBlock>,
428425
#[cfg(not(test))]
429-
latest_block_height: AtomicUsize,
430-
last_block_hash: RwLock<BlockHash>,
426+
best_block: RwLock<BestBlock>,
431427
secp_ctx: Secp256k1<secp256k1::All>,
432428

433429
#[cfg(any(test, feature = "_test_utils"))]
@@ -475,13 +471,37 @@ pub struct ChainParameters {
475471
/// The network for determining the `chain_hash` in Lightning messages.
476472
pub network: Network,
477473

478-
/// The hash of the latest block successfully connected.
479-
pub latest_hash: BlockHash,
480-
481-
/// The height of the latest block successfully connected.
474+
/// The hash and height of the latest block successfully connected.
482475
///
483476
/// Used to track on-chain channel funding outputs and send payments with reliable timelocks.
484-
pub latest_height: usize,
477+
pub best_block: BestBlock,
478+
}
479+
480+
/// The best known block as identified by its hash and height.
481+
pub struct BestBlock {
482+
block_hash: BlockHash,
483+
height: u32,
484+
}
485+
486+
impl BestBlock {
487+
/// Returns the best block from the genesis of the given network.
488+
pub fn from_genesis(network: Network) -> Self {
489+
BestBlock {
490+
block_hash: genesis_block(network).header.block_hash(),
491+
height: 0,
492+
}
493+
}
494+
495+
/// Returns the best block as identified by the given block hash and height.
496+
pub fn new(block_hash: BlockHash, height: u32) -> Self {
497+
BestBlock { block_hash, height }
498+
}
499+
500+
/// Returns the best block hash.
501+
pub fn block_hash(&self) -> BlockHash { self.block_hash }
502+
503+
/// Returns the best block height.
504+
pub fn height(&self) -> u32 { self.height }
485505
}
486506

487507
/// Whenever we release the `ChannelManager`'s `total_consistency_lock`, from read mode, it is
@@ -822,8 +842,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
822842
chain_monitor,
823843
tx_broadcaster,
824844

825-
latest_block_height: AtomicUsize::new(params.latest_height),
826-
last_block_hash: RwLock::new(params.latest_hash),
845+
best_block: RwLock::new(params.best_block),
827846

828847
channel_state: Mutex::new(ChannelHolder{
829848
by_id: HashMap::new(),
@@ -1176,7 +1195,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
11761195
// HTLC_FAIL_BACK_BUFFER blocks to go.
11771196
// Also, ensure that, in the case of an unknown payment hash, our payment logic has enough time to fail the HTLC backward
11781197
// before our onchain logic triggers a channel closure (see HTLC_FAIL_BACK_BUFFER rational).
1179-
if (msg.cltv_expiry as u64) <= self.latest_block_height.load(Ordering::Acquire) as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
1198+
if (msg.cltv_expiry as u64) <= self.best_block.read().unwrap().height() as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
11801199
return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]);
11811200
}
11821201
// final_incorrect_htlc_amount
@@ -1299,7 +1318,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
12991318
if (msg.cltv_expiry as u64) < (*outgoing_cltv_value) as u64 + chan.get_cltv_expiry_delta() as u64 { // incorrect_cltv_expiry
13001319
break Some(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", 0x1000 | 13, Some(self.get_channel_update(chan).unwrap())));
13011320
}
1302-
let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
1321+
let cur_height = self.best_block.read().unwrap().height() + 1;
13031322
// Theoretically, channel counterparty shouldn't send us a HTLC expiring now, but we want to be robust wrt to counterparty
13041323
// packet sanitization (see HTLC_FAIL_BACK_BUFFER rational)
13051324
if msg.cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { // expiry_too_soon
@@ -1516,7 +1535,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15161535
return Err(PaymentSendFailure::PathParameterError(path_errs));
15171536
}
15181537

1519-
let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
1538+
let cur_height = self.best_block.read().unwrap().height() + 1;
15201539
let mut results = Vec::new();
15211540
for path in route.paths.iter() {
15221541
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height));
@@ -1910,10 +1929,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
19101929
for htlc in htlcs.iter() {
19111930
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
19121931
htlc_msat_height_data.extend_from_slice(
1913-
&byte_utils::be32_to_array(
1914-
self.latest_block_height.load(Ordering::Acquire)
1915-
as u32,
1916-
),
1932+
&byte_utils::be32_to_array(self.best_block.read().unwrap().height()),
19171933
);
19181934
failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
19191935
short_channel_id: htlc.prev_hop.short_channel_id,
@@ -2033,8 +2049,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20332049
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
20342050
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
20352051
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(
2036-
self.latest_block_height.load(Ordering::Acquire) as u32,
2037-
));
2052+
self.best_block.read().unwrap().height()));
20382053
self.fail_htlc_backwards_internal(channel_state.take().unwrap(),
20392054
HTLCSource::PreviousHopData(htlc.prev_hop), payment_hash,
20402055
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data });
@@ -2248,8 +2263,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
22482263
if (is_mpp && !valid_mpp) || (!is_mpp && (htlc.value < expected_amount || htlc.value > expected_amount * 2)) {
22492264
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
22502265
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(
2251-
self.latest_block_height.load(Ordering::Acquire) as u32,
2252-
));
2266+
self.best_block.read().unwrap().height()));
22532267
self.fail_htlc_backwards_internal(channel_state.take().unwrap(),
22542268
HTLCSource::PreviousHopData(htlc.prev_hop), &payment_hash,
22552269
HTLCFailReason::Reason { failure_code: 0x4000|15, data: htlc_msat_height_data });
@@ -2534,7 +2548,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25342548

25352549
fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
25362550
let ((funding_msg, monitor), mut chan) = {
2537-
let last_block_hash = *self.last_block_hash.read().unwrap();
2551+
let last_block_hash = self.best_block.read().unwrap().block_hash();
25382552
let mut channel_lock = self.channel_state.lock().unwrap();
25392553
let channel_state = &mut *channel_lock;
25402554
match channel_state.by_id.entry(msg.temporary_channel_id.clone()) {
@@ -2591,7 +2605,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25912605

25922606
fn internal_funding_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> {
25932607
let funding_tx = {
2594-
let last_block_hash = *self.last_block_hash.read().unwrap();
2608+
let last_block_hash = self.best_block.read().unwrap().block_hash();
25952609
let mut channel_lock = self.channel_state.lock().unwrap();
25962610
let channel_state = &mut *channel_lock;
25972611
match channel_state.by_id.entry(msg.channel_id) {
@@ -3339,24 +3353,30 @@ where
33393353
L::Target: Logger,
33403354
{
33413355
fn block_connected(&self, block: &Block, height: u32) {
3342-
assert_eq!(*self.last_block_hash.read().unwrap(), block.header.prev_blockhash,
3343-
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3344-
assert_eq!(self.latest_block_height.load(Ordering::Acquire) as u64, height as u64 - 1,
3345-
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height");
3356+
{
3357+
let best_block = self.best_block.read().unwrap();
3358+
assert_eq!(best_block.block_hash(), block.header.prev_blockhash,
3359+
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3360+
assert_eq!(best_block.height(), height - 1,
3361+
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height");
3362+
}
3363+
33463364
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
33473365
self.transactions_confirmed(&block.header, height, &txdata);
33483366
self.update_best_block(&block.header, height);
33493367
}
33503368

33513369
fn block_disconnected(&self, header: &BlockHeader, height: u32) {
3352-
assert_eq!(*self.last_block_hash.read().unwrap(), header.block_hash(),
3353-
"Blocks must be disconnected in chain-order - the disconnected header must be the last connected header");
3354-
33553370
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3356-
let new_height = self.latest_block_height.fetch_sub(1, Ordering::AcqRel) as u32 - 1;
3357-
assert_eq!(new_height, height - 1,
3358-
"Blocks must be disconnected in chain-order - the disconnected block must have the correct height");
3359-
*self.last_block_hash.write().unwrap() = header.prev_blockhash;
3371+
let new_height = height - 1;
3372+
{
3373+
let mut best_block = self.best_block.write().unwrap();
3374+
assert_eq!(best_block.block_hash(), header.block_hash(),
3375+
"Blocks must be disconnected in chain-order - the disconnected header must be the last connected header");
3376+
assert_eq!(best_block.height(), height,
3377+
"Blocks must be disconnected in chain-order - the disconnected block must have the correct height");
3378+
*best_block = BestBlock::new(header.prev_blockhash, new_height)
3379+
}
33603380

33613381
self.do_chain_event(Some(new_height), |channel| channel.update_best_block(new_height, header.time));
33623382
}
@@ -3513,8 +3533,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
35133533

35143534
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
35153535

3516-
self.latest_block_height.store(height as usize, Ordering::Release);
3517-
*self.last_block_hash.write().unwrap() = block_hash;
3536+
*self.best_block.write().unwrap() = BestBlock::new(block_hash, height);
35183537

35193538
self.do_chain_event(Some(height), |channel| channel.update_best_block(height, header.time));
35203539

@@ -4147,8 +4166,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
41474166
writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
41484167

41494168
self.genesis_hash.write(writer)?;
4150-
(self.latest_block_height.load(Ordering::Acquire) as u32).write(writer)?;
4151-
self.last_block_hash.read().unwrap().write(writer)?;
4169+
{
4170+
let best_block = self.best_block.read().unwrap();
4171+
best_block.height().write(writer)?;
4172+
best_block.block_hash().write(writer)?;
4173+
}
41524174

41534175
let channel_state = self.channel_state.lock().unwrap();
41544176
let mut unfunded_channels = 0;
@@ -4340,8 +4362,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
43404362
}
43414363

43424364
let genesis_hash: BlockHash = Readable::read(reader)?;
4343-
let latest_block_height: u32 = Readable::read(reader)?;
4344-
let last_block_hash: BlockHash = Readable::read(reader)?;
4365+
let best_block_height: u32 = Readable::read(reader)?;
4366+
let best_block_hash: BlockHash = Readable::read(reader)?;
43454367

43464368
let mut failed_htlcs = Vec::new();
43474369

@@ -4449,8 +4471,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
44494471
chain_monitor: args.chain_monitor,
44504472
tx_broadcaster: args.tx_broadcaster,
44514473

4452-
latest_block_height: AtomicUsize::new(latest_block_height as usize),
4453-
last_block_hash: RwLock::new(last_block_hash),
4474+
best_block: RwLock::new(BestBlock::new(best_block_hash, best_block_height)),
44544475

44554476
channel_state: Mutex::new(ChannelHolder {
44564477
by_id,
@@ -4484,7 +4505,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
44844505
//TODO: Broadcast channel update for closed channels, but only after we've made a
44854506
//connection or two.
44864507

4487-
Ok((last_block_hash.clone(), channel_manager))
4508+
Ok((best_block_hash.clone(), channel_manager))
44884509
}
44894510
}
44904511

@@ -4545,7 +4566,7 @@ pub mod bench {
45454566
use chain::chainmonitor::ChainMonitor;
45464567
use chain::channelmonitor::Persist;
45474568
use chain::keysinterface::{KeysManager, InMemorySigner};
4548-
use ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
4569+
use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
45494570
use ln::features::InitFeatures;
45504571
use ln::functional_test_utils::*;
45514572
use ln::msgs::ChannelMessageHandler;
@@ -4597,8 +4618,7 @@ pub mod bench {
45974618
let keys_manager_a = KeysManager::new(&seed_a, 42, 42);
45984619
let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &logger_a, &keys_manager_a, config.clone(), ChainParameters {
45994620
network,
4600-
latest_hash: genesis_hash,
4601-
latest_height: 0,
4621+
best_block: BestBlock::from_genesis(network),
46024622
});
46034623
let node_a_holder = NodeHolder { node: &node_a };
46044624

@@ -4608,8 +4628,7 @@ pub mod bench {
46084628
let keys_manager_b = KeysManager::new(&seed_b, 42, 42);
46094629
let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &logger_b, &keys_manager_b, config.clone(), ChainParameters {
46104630
network,
4611-
latest_hash: genesis_hash,
4612-
latest_height: 0,
4631+
best_block: BestBlock::from_genesis(network),
46134632
});
46144633
let node_b_holder = NodeHolder { node: &node_b };
46154634

lightning/src/ln/functional_test_utils.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use chain::{Listen, Watch};
1414
use chain::channelmonitor::ChannelMonitor;
1515
use chain::transaction::OutPoint;
16-
use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
16+
use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
1717
use routing::router::{Route, get_route};
1818
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
1919
use ln::features::InitFeatures;
@@ -1279,8 +1279,7 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
12791279
let network = Network::Testnet;
12801280
let params = ChainParameters {
12811281
network,
1282-
latest_hash: genesis_block(network).header.block_hash(),
1283-
latest_height: 0,
1282+
best_block: BestBlock::from_genesis(network),
12841283
};
12851284
let node = ChannelManager::new(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 }, params);
12861285
chanmgrs.push(node);

0 commit comments

Comments
 (0)