[[package]]
name = "lightning"
version = "0.0.13"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bitcoin",
]
[[package]]
name = "lightning-background-processor"
version = "0.0.13"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bitcoin",
"lightning",
[[package]]
name = "lightning-block-sync"
version = "0.0.13"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bitcoin",
"chunked_transfer",
[[package]]
name = "lightning-invoice"
version = "0.4.0"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bech32 0.7.2",
"bitcoin_hashes",
+ "lightning",
"num-traits",
"secp256k1",
]
[[package]]
name = "lightning-net-tokio"
version = "0.0.13"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bitcoin",
"lightning",
[[package]]
name = "lightning-persister"
version = "0.0.13"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=3d51b11fe99c9d6a41b0d662efdf5693d9600552#3d51b11fe99c9d6a41b0d662efdf5693d9600552"
+source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d4d322580994857b1222488f8467311d6db61482#d4d322580994857b1222488f8467311d6db61482"
dependencies = [
"bitcoin",
"libc",
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
-# lightning-background-processor = { path = "../rust-lightning/background-processor" }
+# lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", branch = "main" }
+lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d4d322580994857b1222488f8467311d6db61482" }
+# lightning-background-processor = { path = "../rust-lightning/lightning-background-processor" }
base64 = "0.13.0"
bitcoin = "0.26"
bitcoin-bech32 = "0.7"
bech32 = "0.7"
hex = "0.3"
-lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
+
+# lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", branch = "main" }
+lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d4d322580994857b1222488f8467311d6db61482" }
# lightning = { path = "../rust-lightning/lightning" }
-lightning-block-sync = { git = "https://github.com/rust-bitcoin/rust-lightning", features = ["rpc-client"], rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
+
+# lightning-block-sync = { git = "https://github.com/rust-bitcoin/rust-lightning", features = ["rpc-client"], branch = "main" }
+lightning-block-sync = { git = "https://github.com/rust-bitcoin/rust-lightning", features = ["rpc-client"], rev = "d4d322580994857b1222488f8467311d6db61482" }
# lightning-block-sync = { path = "../rust-lightning/lightning-block-sync", features = ["rpc-client"] }
-lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
-lightning-net-tokio = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
+
+# lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning", branch = "main" }
+lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d4d322580994857b1222488f8467311d6db61482" }
+# lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
+
+# lightning-net-tokio = { git = "https://github.com/rust-bitcoin/rust-lightning", branch = "main" }
+lightning-net-tokio = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d4d322580994857b1222488f8467311d6db61482" }
# lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
-lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "3d51b11fe99c9d6a41b0d662efdf5693d9600552" }
+
+# lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", branch = "main" }
+lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d4d322580994857b1222488f8467311d6db61482" }
# lightning-persister = { path = "../rust-lightning/lightning-persister" }
+
time = "0.2"
rand = "0.4"
serde_json = { version = "1.0" }
use_field_init_shorthand = true
max_width = 100
use_small_heuristics = "Max"
-fn_args_layout = "Compressed"
\ No newline at end of file
+fn_args_layout = "Compressed"
ChannelManager, FilesystemLogger, HTLCStatus, MillisatAmount, PaymentInfo, PaymentInfoStorage,
PeerManager,
};
-use bitcoin::hashes::sha256::Hash as Sha256Hash;
-use bitcoin::hashes::Hash;
use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::key::{PublicKey, SecretKey};
-use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1::key::PublicKey;
use lightning::chain;
-use lightning::ln::channelmanager::{PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::chain::keysinterface::KeysManager;
use lightning::ln::features::InvoiceFeatures;
-use lightning::routing::network_graph::{NetGraphMsgHandler, RoutingFees};
+use lightning::ln::{PaymentHash, PaymentSecret};
+use lightning::routing::network_graph::NetGraphMsgHandler;
use lightning::routing::router;
-use lightning::routing::router::RouteHint;
+use lightning::routing::router::RouteHintHop;
use lightning::util::config::UserConfig;
-use lightning_invoice::{Currency, Invoice, InvoiceBuilder, Route, RouteHop};
-use rand;
-use rand::Rng;
+use lightning_invoice::{utils, Currency, Invoice};
use std::env;
use std::io;
use std::io::{BufRead, Write};
}
pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
- if env::args().len() < 4 {
+ if env::args().len() < 3 {
println!("ldk-tutorial-node requires 3 arguments: `cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> ldk_storage_directory_path [<ldk-incoming-peer-listening-port>] [bitcoin-network]`");
return Err(());
}
let mut ldk_peer_port_set = true;
let ldk_peer_listening_port: u16 = match env::args().skip(3).next().map(|p| p.parse()) {
Some(Ok(p)) => p,
- Some(Err(e)) => panic!(e),
+ Some(Err(e)) => panic!("{}", e),
None => {
ldk_peer_port_set = false;
9735
pub(crate) async fn poll_for_user_input(
peer_manager: Arc<PeerManager>, channel_manager: Arc<ChannelManager>,
- router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access>, Arc<FilesystemLogger>>>,
+ keys_manager: Arc<KeysManager>,
+ router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access + Send + Sync>, Arc<FilesystemLogger>>>,
inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage,
- node_privkey: SecretKey, event_notifier: mpsc::Sender<()>, ldk_data_dir: String,
- logger: Arc<FilesystemLogger>, network: Network,
+ event_notifier: mpsc::Sender<()>, ldk_data_dir: String, logger: Arc<FilesystemLogger>,
+ network: Network,
) {
println!("LDK startup successful. To view available commands: \"help\".\nLDK logs are available at <your-supplied-ldk-data-dir-path>/.ldk/logs");
let stdin = io::stdin();
continue;
}
- let invoice_res = Invoice::from_str(invoice_str.unwrap());
- if invoice_res.is_err() {
- println!("ERROR: invalid invoice: {:?}", invoice_res.unwrap_err());
- print!("> ");
- io::stdout().flush().unwrap();
- continue;
+ let invoice = match Invoice::from_str(invoice_str.unwrap()) {
+ Ok(inv) => inv,
+ Err(e) => {
+ println!("ERROR: invalid invoice: {:?}", e);
+ print!("> ");
+ io::stdout().flush().unwrap();
+ continue;
+ }
+ };
+ let mut route_hints = invoice.routes().clone();
+ let mut last_hops = Vec::new();
+ for hint in route_hints.drain(..) {
+ last_hops.push(hint[hint.len() - 1].clone());
}
- let invoice = invoice_res.unwrap();
- let route_hints: Vec<Route> =
- invoice.routes().iter().map(|&route| route.clone()).collect();
let amt_pico_btc = invoice.amount_pico_btc();
if amt_pico_btc.is_none() {
let amt_msat = amt_pico_btc.unwrap() / 10;
let payee_pubkey = invoice.recover_payee_pub_key();
- let final_cltv = *invoice.min_final_cltv_expiry().unwrap_or(&9) as u32;
+ let final_cltv = invoice.min_final_cltv_expiry() as u32;
let mut payment_hash = PaymentHash([0; 32]);
payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]);
None => None,
};
- // rust-lightning-invoice doesn't currently support features, so we parse features
- // manually from the invoice.
- let mut invoice_features = InvoiceFeatures::empty();
- for field in &invoice.into_signed_raw().raw_invoice().data.tagged_fields {
- match field {
- lightning_invoice::RawTaggedField::UnknownSemantics(vec) => {
- if vec[0] == bech32::u5::try_from_u8(5).unwrap() {
- if vec.len() >= 6 && vec[5].to_u8() & 0b10000 != 0 {
- invoice_features =
- invoice_features.set_variable_length_onion_optional();
- }
- if vec.len() >= 6 && vec[5].to_u8() & 0b01000 != 0 {
- invoice_features =
- invoice_features.set_variable_length_onion_required();
- }
- if vec.len() >= 4 && vec[3].to_u8() & 0b00001 != 0 {
- invoice_features =
- invoice_features.set_payment_secret_optional();
- }
- if vec.len() >= 5 && vec[4].to_u8() & 0b10000 != 0 {
- invoice_features =
- invoice_features.set_payment_secret_required();
- }
- if vec.len() >= 4 && vec[3].to_u8() & 0b00100 != 0 {
- invoice_features =
- invoice_features.set_basic_mpp_optional();
- }
- if vec.len() >= 4 && vec[3].to_u8() & 0b00010 != 0 {
- invoice_features =
- invoice_features.set_basic_mpp_required();
- }
- }
- }
- _ => {}
- }
- }
- let invoice_features_opt = match invoice_features == InvoiceFeatures::empty() {
- true => None,
- false => Some(invoice_features),
+ let invoice_features = match invoice.features() {
+ Some(feat) => Some(feat.clone()),
+ None => None,
};
+
send_payment(
payee_pubkey,
amt_msat,
final_cltv,
payment_hash,
payment_secret,
- invoice_features_opt,
- route_hints,
+ invoice_features,
+ last_hops,
router.clone(),
channel_manager.clone(),
outbound_payments.clone(),
get_invoice(
amt_msat.unwrap(),
inbound_payments.clone(),
- node_privkey.clone(),
channel_manager.clone(),
+ keys_manager.clone(),
network,
);
}
channel_id.copy_from_slice(&channel_id_vec.unwrap());
force_close_channel(channel_id, channel_manager.clone());
}
+ "nodeinfo" => node_info(channel_manager.clone(), peer_manager.clone()),
+ "listpeers" => list_peers(peer_manager.clone()),
_ => println!("Unknown command. See `\"help\" for available commands."),
}
}
println!("forceclosechannel <channel_id>");
}
+fn node_info(channel_manager: Arc<ChannelManager>, peer_manager: Arc<PeerManager>) {
+ println!("\t{{");
+ println!("\t\t node_pubkey: {}", channel_manager.get_our_node_id());
+ println!("\t\t num_channels: {}", channel_manager.list_channels().len());
+ println!("\t\t num_usable_channels: {}", channel_manager.list_usable_channels().len());
+ println!("\t\t num_peers: {}", peer_manager.get_peer_node_ids().len());
+ println!("\t}},");
+}
+
+fn list_peers(peer_manager: Arc<PeerManager>) {
+ println!("\t{{");
+ for pubkey in peer_manager.get_peer_node_ids() {
+ println!("\t\t pubkey: {}", pubkey);
+ }
+ println!("\t}},");
+}
+
fn list_channels(channel_manager: Arc<ChannelManager>) {
print!("[");
for chan_info in channel_manager.list_channels() {
fn send_payment(
payee: PublicKey, amt_msat: u64, final_cltv: u32, payment_hash: PaymentHash,
payment_secret: Option<PaymentSecret>, payee_features: Option<InvoiceFeatures>,
- mut route_hints: Vec<Route>,
- router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access>, Arc<FilesystemLogger>>>,
+ route_hints: Vec<RouteHintHop>,
+ router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access + Send + Sync>, Arc<FilesystemLogger>>>,
channel_manager: Arc<ChannelManager>, payment_storage: PaymentInfoStorage,
logger: Arc<FilesystemLogger>,
) {
let first_hops = channel_manager.list_usable_channels();
let payer_pubkey = channel_manager.get_our_node_id();
- let mut hints: Vec<RouteHint> = Vec::new();
- for route in route_hints.drain(..) {
- let route_hops = route.into_inner();
- let last_hop = &route_hops[route_hops.len() - 1];
- hints.push(RouteHint {
- src_node_id: last_hop.pubkey,
- short_channel_id: u64::from_be_bytes(last_hop.short_channel_id),
- fees: RoutingFees {
- base_msat: last_hop.fee_base_msat,
- proportional_millionths: last_hop.fee_proportional_millionths,
- },
- cltv_expiry_delta: last_hop.cltv_expiry_delta,
- htlc_minimum_msat: None,
- htlc_maximum_msat: None,
- })
- }
let route = router::get_route(
&payer_pubkey,
&network_graph,
&payee,
payee_features,
Some(&first_hops.iter().collect::<Vec<_>>()),
- &hints.iter().collect::<Vec<_>>(),
+ &route_hints.iter().collect::<Vec<_>>(),
amt_msat,
final_cltv,
logger,
}
fn get_invoice(
- amt_msat: u64, payment_storage: PaymentInfoStorage, our_node_privkey: SecretKey,
- channel_manager: Arc<ChannelManager>, network: Network,
+ amt_msat: u64, payment_storage: PaymentInfoStorage, channel_manager: Arc<ChannelManager>,
+ keys_manager: Arc<KeysManager>, network: Network,
) {
let mut payments = payment_storage.lock().unwrap();
- let secp_ctx = Secp256k1::new();
-
- let mut preimage = [0; 32];
- rand::thread_rng().fill_bytes(&mut preimage);
- let payment_hash = Sha256Hash::hash(&preimage);
-
- let our_node_pubkey = channel_manager.get_our_node_id();
- let mut invoice = InvoiceBuilder::new(match network {
+ let currency = match network {
Network::Bitcoin => Currency::Bitcoin,
Network::Testnet => Currency::BitcoinTestnet,
Network::Regtest => Currency::Regtest,
- Network::Signet => panic!("Signet invoices not supported"),
- })
- .payment_hash(payment_hash)
- .description("rust-lightning-bitcoinrpc invoice".to_string())
- .amount_pico_btc(amt_msat * 10)
- .current_timestamp()
- .payee_pub_key(our_node_pubkey);
-
- // Add route hints to the invoice.
- let our_channels = channel_manager.list_usable_channels();
- let mut min_final_cltv_expiry = 9;
- for channel in our_channels {
- let short_channel_id = match channel.short_channel_id {
- Some(id) => id.to_be_bytes(),
- None => continue,
- };
- let forwarding_info = match channel.counterparty_forwarding_info {
- Some(info) => info,
- None => continue,
- };
- if forwarding_info.cltv_expiry_delta > min_final_cltv_expiry {
- min_final_cltv_expiry = forwarding_info.cltv_expiry_delta;
+ Network::Signet => panic!("Signet unsupported"),
+ };
+ let invoice = match utils::create_invoice_from_channelmanager(
+ &channel_manager,
+ keys_manager,
+ currency,
+ Some(amt_msat),
+ "ldk-tutorial-node".to_string(),
+ ) {
+ Ok(inv) => {
+ println!("SUCCESS: generated invoice: {}", inv);
+ inv
}
- invoice = invoice.route(vec![RouteHop {
- pubkey: channel.remote_network_id,
- short_channel_id,
- fee_base_msat: forwarding_info.fee_base_msat,
- fee_proportional_millionths: forwarding_info.fee_proportional_millionths,
- cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
- }]);
- }
- invoice = invoice.min_final_cltv_expiry(min_final_cltv_expiry.into());
-
- // Sign the invoice.
- let invoice =
- invoice.build_signed(|msg_hash| secp_ctx.sign_recoverable(msg_hash, &our_node_privkey));
-
- match invoice {
- Ok(invoice) => println!("SUCCESS: generated invoice: {}", invoice),
- Err(e) => println!("ERROR: failed to create invoice: {:?}", e),
- }
+ Err(e) => {
+ println!("ERROR: failed to create invoice: {:?}", e);
+ return;
+ }
+ };
+ let mut payment_hash = PaymentHash([0; 32]);
+ payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]);
payments.insert(
- PaymentHash(payment_hash.into_inner()),
+ payment_hash,
PaymentInfo {
- preimage: Some(PaymentPreimage(preimage)),
+ preimage: None,
// We can't add payment secrets to invoices until we support features in invoices.
// Otherwise lnd errors with "destination hop doesn't understand payment addresses"
// (for context, lnd calls payment secrets "payment addresses").
- secret: None,
+ secret: Some(invoice.payment_secret().unwrap().clone()),
status: HTLCStatus::Pending,
amt_msat: MillisatAmount(Some(amt_msat)),
},
use lightning::chain::Watch;
use lightning::ln::channelmanager;
use lightning::ln::channelmanager::{
- ChainParameters, ChannelManagerReadArgs, PaymentHash, PaymentPreimage, PaymentSecret,
- SimpleArcChannelManager,
+ BestBlock, ChainParameters, ChannelManagerReadArgs, SimpleArcChannelManager,
};
use lightning::ln::peer_handler::{MessageHandler, SimpleArcPeerManager};
+use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::routing::network_graph::NetGraphMsgHandler;
use lightning::util::config::UserConfig;
use lightning::util::events::{Event, EventsProvider};
use lightning_net_tokio::SocketDescriptor;
use lightning_persister::FilesystemPersister;
use rand::{thread_rng, Rng};
+use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::fmt;
use std::fs;
use std::sync::{Arc, Mutex};
use std::time::{Duration, SystemTime};
use tokio::sync::mpsc;
+use tokio::sync::mpsc::Receiver;
pub(crate) enum HTLCStatus {
Pending,
type ChainMonitor = chainmonitor::ChainMonitor<
InMemorySigner,
- Arc<dyn Filter>,
+ Arc<dyn Filter + Send + Sync>,
Arc<BitcoindClient>,
Arc<BitcoindClient>,
Arc<FilesystemLogger>,
ChainMonitor,
BitcoindClient,
BitcoindClient,
- dyn chain::Access,
+ dyn chain::Access + Send + Sync,
FilesystemLogger,
>;
channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
bitcoind_client: Arc<BitcoindClient>, keys_manager: Arc<KeysManager>,
inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage, network: Network,
+ mut event_receiver: Receiver<()>,
) {
loop {
+ let received = event_receiver.recv();
+ if received.await.is_none() {
+ println!("LDK Event channel closed!");
+ return;
+ }
let loop_channel_manager = channel_manager.clone();
let mut events = channel_manager.get_and_clear_pending_events();
events.append(&mut chain_monitor.get_and_clear_pending_events());
.funding_transaction_generated(&temporary_channel_id, final_tx)
.unwrap();
}
- Event::PaymentReceived { payment_hash, payment_secret, amt } => {
+ Event::PaymentReceived {
+ payment_hash,
+ payment_preimage,
+ payment_secret,
+ amt,
+ ..
+ } => {
let mut payments = inbound_payments.lock().unwrap();
- if let Some(payment) = payments.get_mut(&payment_hash) {
- if payment.secret == payment_secret {
- assert!(loop_channel_manager.claim_funds(
- payment.preimage.unwrap().clone(),
- &payment.secret,
- payment.amt_msat.0.unwrap(),
- ));
+ let status = match loop_channel_manager.claim_funds(payment_preimage.unwrap()) {
+ true => {
println!(
- "\nEVENT: received payment from payment hash {} of {} millisatoshis",
- hex_utils::hex_str(&payment_hash.0),
- payment.amt_msat
- );
+ "\nEVENT: received payment from payment hash {} of {} millisatoshis",
+ hex_utils::hex_str(&payment_hash.0),
+ amt
+ );
print!("> ");
io::stdout().flush().unwrap();
- payment.status = HTLCStatus::Succeeded;
- } else {
- loop_channel_manager
- .fail_htlc_backwards(&payment_hash, &payment.secret);
- println!("\nERROR: we received a payment from payment hash {} but the payment secret didn't match", hex_utils::hex_str(&payment_hash.0));
- print!("> ");
- io::stdout().flush().unwrap();
- payment.status = HTLCStatus::Failed;
+ HTLCStatus::Succeeded
}
- } else {
- loop_channel_manager.fail_htlc_backwards(&payment_hash, &payment_secret);
- println!("\nERROR: we received a payment for payment hash {} but didn't know the preimage", hex_utils::hex_str(&payment_hash.0));
- print!("> ");
- io::stdout().flush().unwrap();
- payments.insert(
- payment_hash,
- PaymentInfo {
- preimage: None,
- secret: payment_secret,
- status: HTLCStatus::Failed,
+ _ => HTLCStatus::Failed,
+ };
+ match payments.entry(payment_hash) {
+ Entry::Occupied(mut e) => {
+ let payment = e.get_mut();
+ payment.status = status;
+ payment.preimage = Some(payment_preimage.unwrap());
+ payment.secret = Some(payment_secret);
+ }
+ Entry::Vacant(e) => {
+ e.insert(PaymentInfo {
+ preimage: Some(payment_preimage.unwrap()),
+ secret: Some(payment_secret),
+ status,
amt_msat: MillisatAmount(Some(amt)),
- },
- );
+ });
+ }
}
}
Event::PaymentSent { payment_preimage } => {
// Step 7: Read ChannelMonitor state from disk
let mut channelmonitors = persister.read_channelmonitors(keys_manager.clone()).unwrap();
- // Step 9: Initialize the ChannelManager
+ // Step 8: Initialize the ChannelManager
let user_config = UserConfig::default();
let mut restarting_node = true;
let (channel_manager_blockhash, mut channel_manager) = {
let chain_params = ChainParameters {
network: args.network,
- latest_hash: getinfo_resp.latest_blockhash,
- latest_height: getinfo_resp.latest_height,
+ best_block: BestBlock::new(
+ getinfo_resp.latest_blockhash,
+ getinfo_resp.latest_height as u32,
+ ),
};
let fresh_channel_manager = channelmanager::ChannelManager::new(
fee_estimator.clone(),
}
};
- // Step 10: Sync ChannelMonitors and ChannelManager to chain tip
+ // Step 9: Sync ChannelMonitors and ChannelManager to chain tip
let mut chain_listener_channel_monitors = Vec::new();
let mut cache = UnboundedCache::new();
let mut chain_tip: Option<poll::ValidatedBlockHeader> = None;
);
}
- // Step 11: Give ChannelMonitors to ChainMonitor
+ // Step 10: Give ChannelMonitors to ChainMonitor
for item in chain_listener_channel_monitors.drain(..) {
let channel_monitor = item.1 .0;
let funding_outpoint = item.2;
chain_monitor.watch_channel(funding_outpoint, channel_monitor).unwrap();
}
- // Step 13: Optional: Initialize the NetGraphMsgHandler
+ // Step 11: Optional: Initialize the NetGraphMsgHandler
// XXX persist routing data
let genesis = genesis_block(args.network).header.block_hash();
- let router =
- Arc::new(NetGraphMsgHandler::new(genesis, None::<Arc<dyn chain::Access>>, logger.clone()));
+ let router = Arc::new(NetGraphMsgHandler::new(
+ genesis,
+ None::<Arc<dyn chain::Access + Send + Sync>>,
+ logger.clone(),
+ ));
- // Step 14: Initialize the PeerManager
+ // Step 12: Initialize the PeerManager
let channel_manager: Arc<ChannelManager> = Arc::new(channel_manager);
let mut ephemeral_bytes = [0; 32];
rand::thread_rng().fill_bytes(&mut ephemeral_bytes);
));
// ## Running LDK
- // Step 16: Initialize Peer Connection Handling
+ // Step 13: Initialize networking
// We poll for events in handle_ldk_events(..) rather than waiting for them over the
// mpsc::channel, so we can leave the event receiver as unused.
- let (event_ntfn_sender, _event_ntfn_receiver) = mpsc::channel(2);
+ let (event_ntfn_sender, event_ntfn_receiver) = mpsc::channel(2);
let peer_manager_connection_handler = peer_manager.clone();
let event_notifier = event_ntfn_sender.clone();
let listening_port = args.ldk_peer_listening_port;
tokio::spawn(async move {
let listener = std::net::TcpListener::bind(format!("0.0.0.0:{}", listening_port)).unwrap();
loop {
+ let peer_mgr = peer_manager_connection_handler.clone();
+ let notifier = event_notifier.clone();
let tcp_stream = listener.accept().unwrap().0;
- lightning_net_tokio::setup_inbound(
- peer_manager_connection_handler.clone(),
- event_notifier.clone(),
- tcp_stream,
- )
- .await;
+ tokio::spawn(async move {
+ lightning_net_tokio::setup_inbound(peer_mgr.clone(), notifier.clone(), tcp_stream)
+ .await;
+ });
}
});
- // Step 17: Connect and Disconnect Blocks
+ // Step 14: Connect and Disconnect Blocks
if chain_tip.is_none() {
chain_tip =
Some(init::validate_best_block_header(&mut bitcoind_client.deref()).await.unwrap());
}
});
- // Step 17 & 18: Initialize ChannelManager persistence & Once Per Minute: ChannelManager's
- // timer_chan_freshness_every_min() and PeerManager's timer_tick_occurred
- let data_dir = ldk_data_dir.clone();
- let persist_channel_manager_callback =
- move |node: &ChannelManager| FilesystemPersister::persist_manager(data_dir.clone(), &*node);
- BackgroundProcessor::start(
- persist_channel_manager_callback,
- channel_manager.clone(),
- peer_manager.clone(),
- logger.clone(),
- );
-
// Step 15: Initialize LDK Event Handling
let channel_manager_event_listener = channel_manager.clone();
let chain_monitor_event_listener = chain_monitor.clone();
inbound_pmts_for_events,
outbound_pmts_for_events,
network,
+ event_ntfn_receiver,
)
.await;
});
+ // Step 16 & 17: Persist ChannelManager & Background Processing
+ let data_dir = ldk_data_dir.clone();
+ let persist_channel_manager_callback =
+ move |node: &ChannelManager| FilesystemPersister::persist_manager(data_dir.clone(), &*node);
+ BackgroundProcessor::start(
+ persist_channel_manager_callback,
+ channel_manager.clone(),
+ peer_manager.clone(),
+ logger.clone(),
+ );
+
// Reconnect to channel peers if possible.
let peer_data_path = format!("{}/channel_peer_data", ldk_data_dir.clone());
match disk::read_channel_peer_data(Path::new(&peer_data_path)) {
cli::poll_for_user_input(
peer_manager.clone(),
channel_manager.clone(),
+ keys_manager.clone(),
router.clone(),
inbound_payments,
outbound_payments,
- keys_manager.get_node_secret(),
event_ntfn_sender,
ldk_data_dir.clone(),
logger.clone(),