Skip to content

Commit d28fa54

Browse files
committed
Parameterize ChannelManager::new with a block hash
When ChannelMonitors are persisted, they need to store the most recent block hash seen. However, for newly created channels the default block hash is used. If persisted before a block is connected, the funding output may be missed when syncing after a restart. Instead, initialize ChannelManager with a "birthday" hash so it can be used later when creating channels.
1 parent af49a60 commit d28fa54

File tree

5 files changed

+61
-18
lines changed

5 files changed

+61
-18
lines changed

background-processor/src/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ mod tests {
106106
use lightning::chain::keysinterface::{Sign, InMemorySigner, KeysInterface, KeysManager};
107107
use lightning::chain::transaction::OutPoint;
108108
use lightning::get_event_msg;
109-
use lightning::ln::channelmanager::{ChannelManager, SimpleArcChannelManager};
109+
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, SimpleArcChannelManager};
110110
use lightning::ln::features::InitFeatures;
111111
use lightning::ln::msgs::ChannelMessageHandler;
112112
use lightning::util::config::UserConfig;
@@ -155,10 +155,16 @@ mod tests {
155155
let persister = Arc::new(FilesystemPersister::new(format!("{}_persister_{}", persist_dir, i)));
156156
let seed = [i as u8; 32];
157157
let network = Network::Testnet;
158-
let now = Duration::from_secs(genesis_block(network).header.time as u64);
158+
let genesis_block = genesis_block(network);
159+
let now = Duration::from_secs(genesis_block.header.time as u64);
159160
let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
160161
let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new(Some(chain_source.clone()), tx_broadcaster.clone(), logger.clone(), fee_estimator.clone(), persister.clone()));
161-
let manager = Arc::new(ChannelManager::new(Network::Testnet, fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster, logger.clone(), keys_manager.clone(), UserConfig::default(), i));
162+
let params = ChainParameters {
163+
network,
164+
latest_hash: genesis_block.block_hash(),
165+
latest_height: 0,
166+
};
167+
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster, logger.clone(), keys_manager.clone(), UserConfig::default(), params));
162168
let node = Node { node: manager, persister, logger };
163169
nodes.push(node);
164170
}

fuzz/src/chanmon_consistency.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
//! channel being force-closed.
2020
2121
use bitcoin::blockdata::block::BlockHeader;
22+
use bitcoin::blockdata::constants::genesis_block;
2223
use bitcoin::blockdata::transaction::{Transaction, TxOut};
2324
use bitcoin::blockdata::script::{Builder, Script};
2425
use bitcoin::blockdata::opcodes;
@@ -35,7 +36,7 @@ use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr,
3536
use lightning::chain::transaction::OutPoint;
3637
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3738
use lightning::chain::keysinterface::{KeysInterface, InMemorySigner};
38-
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
39+
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
3940
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4041
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init};
4142
use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER};
@@ -318,7 +319,13 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
318319
config.channel_options.fee_proportional_millionths = 0;
319320
config.channel_options.announced_channel = true;
320321
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
321-
(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0),
322+
let network = Network::Bitcoin;
323+
let params = ChainParameters {
324+
network,
325+
latest_hash: genesis_block(network).block_hash(),
326+
latest_height: 0,
327+
};
328+
(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params),
322329
monitor, keys_manager)
323330
} }
324331
}

fuzz/src/full_stack.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget,
3131
use lightning::chain::chainmonitor;
3232
use lightning::chain::transaction::OutPoint;
3333
use lightning::chain::keysinterface::{InMemorySigner, KeysInterface};
34-
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
34+
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
3535
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
3636
use lightning::ln::msgs::DecodeError;
3737
use lightning::routing::router::get_route;
@@ -348,9 +348,16 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
348348
config.channel_options.fee_proportional_millionths = slice_to_be32(get_slice!(4));
349349
config.channel_options.announced_channel = get_slice!(1)[0] != 0;
350350
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
351-
let channelmanager = Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0));
351+
let network = Network::Bitcoin;
352+
let genesis_hash = genesis_block(network).block_hash();
353+
let params = ChainParameters {
354+
network,
355+
latest_hash: genesis_hash,
356+
latest_height: 0,
357+
};
358+
let channelmanager = Arc::new(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params));
352359
let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret());
353-
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_block(Network::Bitcoin).header.block_hash(), None, Arc::clone(&logger)));
360+
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_hash, None, Arc::clone(&logger)));
354361

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

lightning/src/ln/channelmanager.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,24 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
461461
logger: L,
462462
}
463463

464+
/// Chain-related parameters used to construct a new `ChannelManager`.
465+
///
466+
/// Typically, the block-specific parameters are derived from the best block hash for the network,
467+
/// as a newly constructed `ChannelManager` will not have created any channels yet. These parameters
468+
/// are not needed when deserializing a previously constructed `ChannelManager`.
469+
pub struct ChainParameters {
470+
/// The network for determining the `chain_hash` in Lightning messages.
471+
pub network: Network,
472+
473+
/// The hash of the latest block successfully connected.
474+
pub latest_hash: BlockHash,
475+
476+
/// The height of the latest block successfully connected.
477+
///
478+
/// Used to track on-chain channel funding outputs and send payments with reliable timelocks.
479+
pub latest_height: usize,
480+
}
481+
464482
/// Whenever we release the `ChannelManager`'s `total_consistency_lock`, from read mode, it is
465483
/// desirable to notify any listeners on `wait_timeout`/`wait` that new updates are available for
466484
/// persistence. Therefore, this struct is responsible for locking the total consistency lock and,
@@ -770,24 +788,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
770788
///
771789
/// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
772790
///
773-
/// Users must provide the current blockchain height from which to track onchain channel
774-
/// funding outpoints and send payments with reliable timelocks.
775-
///
776791
/// Users need to notify the new ChannelManager when a new block is connected or
777-
/// disconnected using its `block_connected` and `block_disconnected` methods.
778-
pub fn new(network: Network, fee_est: F, chain_monitor: M, tx_broadcaster: T, logger: L, keys_manager: K, config: UserConfig, current_blockchain_height: usize) -> Self {
792+
/// disconnected using its `block_connected` and `block_disconnected` methods, starting
793+
/// from after `params.latest_hash`.
794+
pub fn new(fee_est: F, chain_monitor: M, tx_broadcaster: T, logger: L, keys_manager: K, config: UserConfig, params: ChainParameters) -> Self {
779795
let mut secp_ctx = Secp256k1::new();
780796
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
781797

782798
ChannelManager {
783799
default_configuration: config.clone(),
784-
genesis_hash: genesis_block(network).header.block_hash(),
800+
genesis_hash: genesis_block(params.network).header.block_hash(),
785801
fee_estimator: fee_est,
786802
chain_monitor,
787803
tx_broadcaster,
788804

789-
latest_block_height: AtomicUsize::new(current_blockchain_height),
790-
last_block_hash: Mutex::new(Default::default()),
805+
latest_block_height: AtomicUsize::new(params.latest_height),
806+
last_block_hash: Mutex::new(params.latest_hash),
791807
secp_ctx,
792808

793809
channel_state: Mutex::new(ChannelHolder{

lightning/src/ln/functional_test_utils.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use chain::Watch;
1414
use chain::channelmonitor::ChannelMonitor;
1515
use chain::transaction::OutPoint;
16-
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
16+
use ln::channelmanager::{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;
@@ -28,6 +28,7 @@ use util::config::UserConfig;
2828
use util::ser::{ReadableArgs, Writeable, Readable};
2929

3030
use bitcoin::blockdata::block::{Block, BlockHeader};
31+
use bitcoin::blockdata::constants::genesis_block;
3132
use bitcoin::blockdata::transaction::{Transaction, TxOut};
3233
use bitcoin::network::constants::Network;
3334

@@ -1163,7 +1164,13 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
11631164
default_config.channel_options.announced_channel = true;
11641165
default_config.peer_channel_config_limits.force_announced_channel_preference = false;
11651166
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
1166-
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);
1167+
let network = Network::Testnet;
1168+
let params = ChainParameters {
1169+
network,
1170+
latest_hash: genesis_block(network).header.block_hash(),
1171+
latest_height: 0,
1172+
};
1173+
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);
11671174
chanmgrs.push(node);
11681175
}
11691176

0 commit comments

Comments
 (0)