+ let bitcoind_client = Arc::new(BitcoindClient::new(bitcoind_host.clone(), bitcoind_port, None,
+ rpc_user.clone(), rpc_password.clone()).unwrap());
+
+ // ## Setup
+ // Step 1: Initialize the FeeEstimator
+ let fee_estimator = bitcoind_client.clone();
+
+ // Step 2: Initialize the Logger
+ let logger = Arc::new(FilesystemLogger{});
+
+ // Step 3: Initialize the BroadcasterInterface
+ let broadcaster = bitcoind_client.clone();
+
+ // Step 4: Initialize Persist
+ let persister = Arc::new(FilesystemPersister::new(".".to_string()));
+
+ // Step 5: Initialize the ChainMonitor
+ let chain_monitor: Arc<ArcChainMonitor> = Arc::new(ChainMonitor::new(None, broadcaster.clone(),
+ logger.clone(), fee_estimator.clone(),
+ persister.clone()));
+
+ // Step 6: Initialize the KeysManager
+ let node_privkey = if let Ok(seed) = fs::read("./key_seed") { // the private key that corresponds
+ assert_eq!(seed.len(), 32); // to our lightning node's pubkey
+ let mut key = [0; 32];
+ key.copy_from_slice(&seed);
+ key
+ } else {
+ let mut key = [0; 32];
+ thread_rng().fill_bytes(&mut key);
+ let mut f = File::create("./key_seed").unwrap();
+ f.write_all(&key).expect("Failed to write seed to disk");
+ f.sync_all().expect("Failed to sync seed to disk");
+ key
+ };
+ let cur = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let keys_manager = Arc::new(KeysManager::new(&node_privkey, cur.as_secs(), cur.subsec_nanos()));
+
+ // Step 7: Read ChannelMonitor state from disk
+ let mut outpoint_to_channelmonitor = read_channelmonitors_from_disk("./monitors".to_string(),
+ keys_manager.clone()).unwrap();
+
+ // Step 9: Read ChannelManager state from disk
+ let user_config = UserConfig::default();
+ let mut channel_manager: ChannelManager;
+ let mut channel_manager_last_blockhash: Option<BlockHash> = None;
+ if let Ok(mut f) = fs::File::open("./manager") {
+ let (last_block_hash_option, channel_manager_from_disk) = {
+ let mut channel_monitor_mut_references = Vec::new();
+ for (_, channel_monitor) in outpoint_to_channelmonitor.iter_mut() {
+ channel_monitor_mut_references.push(&mut channel_monitor.1);
+ }
+ let read_args = ChannelManagerReadArgs::new(keys_manager.clone(), fee_estimator.clone(),
+ chain_monitor.clone(), broadcaster.clone(),
+ logger.clone(), user_config,
+ channel_monitor_mut_references);
+ <(Option<BlockHash>, ChannelManager)>::read(&mut f, read_args).unwrap()
+ };
+ channel_manager = channel_manager_from_disk;
+ channel_manager_last_blockhash = last_block_hash_option;
+ } else {
+ let mut bitcoind_rpc_client = bitcoind_client.bitcoind_rpc_client.lock().unwrap();
+ let current_chain_height: usize = bitcoind_rpc_client
+ .call_method("getblockchaininfo", &vec![]).unwrap()["blocks"].as_u64().unwrap() as usize;
+ channel_manager = channelmanager::ChannelManager::new(Network::Regtest, fee_estimator.clone(),
+ chain_monitor.clone(), broadcaster.clone(),
+ logger.clone(), keys_manager.clone(),
+ user_config, current_chain_height);
+ }
+
+ // Step 10: Sync ChannelMonitors to chain tip if restarting
+ let mut chain_tip = None;
+ let mut chain_listener_channel_monitors = Vec::new();
+ let mut cache = UnboundedCache::new();
+ let rpc_credentials = base64::encode(format!("{}:{}", rpc_user, rpc_password));
+ let mut block_source = RpcClient::new(&rpc_credentials, HttpEndpoint::for_host(bitcoind_host)
+ .with_port(bitcoind_port)).unwrap();
+ let runtime = Runtime::new().expect("Unable to create a runtime");
+ if outpoint_to_channelmonitor.len() > 0 {
+ for (outpoint, blockhash_and_monitor) in outpoint_to_channelmonitor.drain() {
+ let blockhash = blockhash_and_monitor.0;
+ let channel_monitor = blockhash_and_monitor.1;
+ chain_listener_channel_monitors.push((blockhash, (RefCell::new(channel_monitor),
+ broadcaster.clone(), fee_estimator.clone(),
+ logger.clone()), outpoint));
+ }
+
+ let mut chain_listeners = Vec::new();
+ for monitor_listener_info in chain_listener_channel_monitors.iter_mut() {
+ chain_listeners.push((monitor_listener_info.0,
+ &mut monitor_listener_info.1 as &mut dyn chain::Listen));
+ }
+ // Because `sync_listeners` is an async function and we want to run it synchronously,
+ // we run it in a tokio Runtime.
+ chain_tip = Some(runtime.block_on(init::sync_listeners(&mut block_source, Network::Regtest,
+ &mut cache, chain_listeners)).unwrap());
+ }
+
+ // Step 11: Give ChannelMonitors to ChainMonitor
+ if chain_listener_channel_monitors.len() > 0 {
+ for item in chain_listener_channel_monitors.drain(..) {
+ let channel_monitor = item.1.0.into_inner();
+ let funding_outpoint = item.2;
+ chain_monitor.watch_channel(funding_outpoint, channel_monitor).unwrap();
+ }
+ }
+
+ // Step 12: Sync ChannelManager to chain tip if restarting
+ if let Some(channel_manager_blockhash) = channel_manager_last_blockhash {
+ let chain_listener = vec![
+ (channel_manager_blockhash, &mut channel_manager as &mut dyn chain::Listen)];
+ chain_tip = Some(runtime.block_on(init::sync_listeners(&mut block_source, Network::Regtest,
+ &mut cache, chain_listener)).unwrap());
+ }
+
+ // Step 13: Optional: Initialize the NetGraphMsgHandler
+ // XXX persist routing data
+ let genesis = genesis_block(Network::Regtest).header.block_hash();
+ let router = Arc::new(NetGraphMsgHandler::new(genesis, None::<Arc<dyn chain::Access>>, logger.clone()));
+
+ // Step 14: Initialize the PeerManager
+ let channel_manager = Arc::new(channel_manager);
+ let mut ephemeral_bytes = [0; 32];
+ rand::thread_rng().fill_bytes(&mut ephemeral_bytes);
+ let lightning_msg_handler = MessageHandler { chan_handler: channel_manager.clone(),
+ route_handler: router.clone() };
+ let peer_manager: Arc<PeerManager> = Arc::new(PeerManager::new(lightning_msg_handler,
+ keys_manager.get_node_secret(),
+ &ephemeral_bytes, logger.clone()));
+
+ // ## Running LDK
+ // Step 15: Initialize LDK Event Handling
+ let (event_ntfn_sender, mut event_ntfn_receiver) = mpsc::channel(2);
+ let peer_manager_event_listener = peer_manager.clone();
+ let channel_manager_event_listener = channel_manager.clone();
+ let chain_monitor_event_listener = chain_monitor.clone();
+ let payment_info: PaymentInfoStorage = Arc::new(Mutex::new(HashMap::new()));
+ let payment_info_for_events = payment_info.clone();
+ thread::spawn(move || async move {
+ let mut pending_txs = HashMap::new();
+ loop {
+ event_ntfn_receiver.recv().await.unwrap();
+ pending_txs = handle_ldk_events(peer_manager_event_listener.clone(),
+ channel_manager_event_listener.clone(),
+ chain_monitor_event_listener.clone(),
+ bitcoind_client.clone(), keys_manager.clone(),
+ pending_txs, payment_info_for_events.clone());
+ }
+ });
+
+ // Step 16: Initialize Peer Connection Handling
+ let peer_manager_connection_handler = peer_manager.clone();
+ let event_notifier = event_ntfn_sender.clone();
+ thread::spawn(move || async move {
+ let listener = std::net::TcpListener::bind("0.0.0.0:9735").unwrap();
+ loop {
+ let tcp_stream = listener.accept().unwrap().0;
+ lightning_net_tokio::setup_inbound(peer_manager_connection_handler.clone(),
+ event_notifier.clone(), tcp_stream).await;
+ }
+ });
+
+ // Step 17: Connect and Disconnect Blocks
+ let mut chain_poller = poll::ChainPoller::new(&mut block_source, Network::Regtest);
+ if chain_tip.is_none() {
+ match runtime.block_on(chain_poller.poll_chain_tip(None)).unwrap() {
+ ChainTip::Better(header) => chain_tip = Some(header),
+ _ => panic!("Unexpected chain tip")
+ }
+ }
+ let chain_listener = (chain_monitor.clone(), channel_manager.clone());
+ let _spv_client = SpvClient::new(chain_tip.unwrap(), chain_poller, &mut cache, &chain_listener);
+
+ // Step 17 & 18: Initialize ChannelManager persistence & Once Per Minute: ChannelManager's
+ // timer_chan_freshness_every_min() and PeerManager's timer_tick_occurred
+ let persist_channel_manager_callback = move |node: &ChannelManager| {
+ FilesystemPersister::persist_manager("./".to_string(), &*node)
+ };
+ BackgroundProcessor::start(persist_channel_manager_callback, channel_manager.clone(), logger.clone());
+ let peer_manager_processor = peer_manager.clone();
+ thread::spawn(move || {
+ loop {
+ peer_manager_processor.timer_tick_occured();
+ thread::sleep(Duration::new(60, 0));
+ }
+ });
+ cli::poll_for_user_input(peer_manager.clone(), channel_manager.clone(), event_ntfn_sender.clone());