From: Valentine Wallace Date: Thu, 18 Mar 2021 16:00:01 +0000 (-0400) Subject: Add readme, fix license and a few other cleanups X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=ldk-sample;a=commitdiff_plain;h=25a4f605443ed2bc2bb9548f5679a86fc76d0333 Add readme, fix license and a few other cleanups --- diff --git a/Cargo.lock b/Cargo.lock index 6204cdd..aa92a5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,15 +6,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "background-processor" -version = "0.1.0" -dependencies = [ - "bitcoin", - "lightning", - "lightning-persister", -] - [[package]] name = "base-x" version = "0.2.8" @@ -239,13 +230,13 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" name = "ldk-tutorial-node" version = "0.1.0" dependencies = [ - "background-processor", "base64", "bech32 0.7.2", "bitcoin", "bitcoin-bech32", "hex", "lightning", + "lightning-background-processor", "lightning-block-sync", "lightning-invoice", "lightning-net-tokio", @@ -264,14 +255,26 @@ checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" [[package]] name = "lightning" -version = "0.0.12" +version = "0.0.13" +source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=32f6205848806a3b2876a2ae36b1db7d5fa22f7d#32f6205848806a3b2876a2ae36b1db7d5fa22f7d" dependencies = [ "bitcoin", ] +[[package]] +name = "lightning-background-processor" +version = "0.0.13" +source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=32f6205848806a3b2876a2ae36b1db7d5fa22f7d#32f6205848806a3b2876a2ae36b1db7d5fa22f7d" +dependencies = [ + "bitcoin", + "lightning", + "lightning-persister", +] + [[package]] name = "lightning-block-sync" -version = "0.0.1" +version = "0.0.13" +source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=32f6205848806a3b2876a2ae36b1db7d5fa22f7d#32f6205848806a3b2876a2ae36b1db7d5fa22f7d" dependencies = [ "bitcoin", "chunked_transfer", @@ -284,6 +287,7 @@ dependencies = [ [[package]] name = "lightning-invoice" version = "0.4.0" +source = "git+https://github.com/rust-bitcoin/rust-lightning-invoice?rev=aa3a57b9dca5205fa25fa333a2db165d7e77b3b0#aa3a57b9dca5205fa25fa333a2db165d7e77b3b0" dependencies = [ "bech32 0.7.2", "bitcoin_hashes", @@ -293,7 +297,8 @@ dependencies = [ [[package]] name = "lightning-net-tokio" -version = "0.0.5" +version = "0.0.13" +source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=32f6205848806a3b2876a2ae36b1db7d5fa22f7d#32f6205848806a3b2876a2ae36b1db7d5fa22f7d" dependencies = [ "bitcoin", "lightning", @@ -302,7 +307,8 @@ dependencies = [ [[package]] name = "lightning-persister" -version = "0.0.1" +version = "0.0.13" +source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=32f6205848806a3b2876a2ae36b1db7d5fa22f7d#32f6205848806a3b2876a2ae36b1db7d5fa22f7d" dependencies = [ "bitcoin", "libc", diff --git a/Cargo.toml b/Cargo.toml index 7c097ca..1dd17c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,31 +2,24 @@ name = "ldk-tutorial-node" version = "0.1.0" authors = ["Valentine Wallace "] +license = "MIT OR Apache-2.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -# background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "d6f41d3c0b38b9ec9e06a3acfdd9f4b1d007a27d" } -background-processor = { path = "../rust-lightning/background-processor" } +lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "32f6205848806a3b2876a2ae36b1db7d5fa22f7d" } 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 = "c35002fa9c16042badfa5e7bf819df5f1d2ae60a" } -lightning = { path = "../rust-lightning/lightning" } -lightning-block-sync = { path = "../rust-lightning/lightning-block-sync", features = ["rpc-client"] } -# lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning-invoice", rev = "ea25dc7e46a6339493032c500db4fe3a8fdb1acd" } -lightning-invoice = { path = "../rust-lightning-invoice" } -# lightning-net-tokio = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "ff00f6f8861419b73269e6c51d75ac9de75f1d1f" } -lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" } -# lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "aa127f55edc4439b03426644d178e402397329e8" } -lightning-persister = { path = "../rust-lightning/lightning-persister" } +lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "32f6205848806a3b2876a2ae36b1db7d5fa22f7d" } +lightning-block-sync = { git = "https://github.com/rust-bitcoin/rust-lightning", features = ["rpc-client"], rev = "32f6205848806a3b2876a2ae36b1db7d5fa22f7d" } +lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning-invoice", rev = "aa3a57b9dca5205fa25fa333a2db165d7e77b3b0" } +lightning-net-tokio = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "32f6205848806a3b2876a2ae36b1db7d5fa22f7d" } +lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "32f6205848806a3b2876a2ae36b1db7d5fa22f7d" } time = "0.2" rand = "0.4" serde_json = { version = "1.0" } -# tokio = { version = "0.2", features = ["io-std", "io-util", "rt-threaded", "tcp", "time", "sync"] } -# tokio = { version = "1.0", features = [ "full", "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } -# tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } diff --git a/README.md b/README.md index 6358f4f..740aa25 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,19 @@ # ldk-sample -sample node implementation using LDK +Sample node implementation using LDK. + +## Installation +``` +git clone git@github.com:valentinewallace/ldk-sample.git +``` + +## Usage +``` +cd ldk-sample +cargo run :@: [] [bitcoin-network] +``` +`bitcoin-network`: defaults to `testnet`. Options: `testnet`, `regtest`. + +`ldk-peer-listening-port`: defaults to 9735. ## License diff --git a/src/bitcoind_client.rs b/src/bitcoind_client.rs index de9f870..71e6272 100644 --- a/src/bitcoind_client.rs +++ b/src/bitcoind_client.rs @@ -36,7 +36,6 @@ impl BitcoindClient { rpc_user, rpc_password, runtime: Mutex::new(Runtime::new().unwrap()), - // runtime: Mutex::new(runtime), }; Ok(client) } @@ -103,7 +102,8 @@ impl FeeEstimator for BitcoindClient { ConfirmationTarget::HighPriority => (6, "ECONOMICAL", 50000), }; - // If we're already in a tokio runtime, then we need to get out of it before we can broadcast. + // This function may be called from a tokio runtime, or not. So we need to check before + // making the call to avoid the error "cannot run a tokio runtime from within a tokio runtime". let conf_target_json = serde_json::json!(conf_target); let estimate_mode_json = serde_json::json!(estimate_mode); let resp = match Handle::try_current() { @@ -131,7 +131,8 @@ impl BroadcasterInterface for BitcoindClient { let runtime = self.runtime.lock().unwrap(); let tx_serialized = serde_json::json!(encode::serialize_hex(tx)); - // If we're already in a tokio runtime, then we need to get out of it before we can broadcast. + // This function may be called from a tokio runtime, or not. So we need to check before + // making the call to avoid the error "cannot run a tokio runtime from within a tokio runtime". match Handle::try_current() { Ok(_) => { tokio::task::block_in_place(|| { diff --git a/src/cli.rs b/src/cli.rs index 20c4314..1e11086 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,8 +3,8 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256Hash; use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::key::{PublicKey, SecretKey}; -use crate::{ChannelManager, FilesystemLogger, HTLCDirection, HTLCStatus, NETWORK, - PaymentInfoStorage, PeerManager}; +use crate::{ChannelManager, FilesystemLogger, HTLCDirection, HTLCStatus, + PaymentInfoStorage, PeerManager, SatoshiAmount}; use crate::disk; use crate::hex_utils; use lightning::chain; @@ -34,11 +34,12 @@ pub(crate) struct LdkUserInfo { pub(crate) bitcoind_rpc_host: String, pub(crate) ldk_storage_dir_path: String, pub(crate) ldk_peer_listening_port: u16, + pub(crate) network: Network, } pub(crate) fn parse_startup_args() -> Result { if env::args().len() < 4 { - println!("ldk-tutorial-node requires 3 arguments: `cargo run :@: ldk_storage_directory_path [optional: ]`"); + println!("ldk-tutorial-node requires 3 arguments: `cargo run :@: ldk_storage_directory_path [] [bitcoin-network]`"); return Err(()) } let bitcoind_rpc_info = env::args().skip(1).next().unwrap(); @@ -64,10 +65,25 @@ pub(crate) fn parse_startup_args() -> Result { let ldk_storage_dir_path = env::args().skip(2).next().unwrap(); + 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), - None => 9735, + None => { + ldk_peer_port_set = false; + 9735 + }, + }; + + let arg_idx = match ldk_peer_port_set { + true => 4, + false => 3, + }; + let network: Network = match env::args().skip(arg_idx).next().as_ref().map(String::as_str) { + Some("testnet") => Network::Testnet, + Some("regtest") => Network::Regtest, + Some(_) => panic!("Unsupported network provided. Options are: `regtest`, `testnet`"), + None => Network::Testnet }; Ok(LdkUserInfo { bitcoind_rpc_username, @@ -76,6 +92,7 @@ pub(crate) fn parse_startup_args() -> Result { bitcoind_rpc_port, ldk_storage_dir_path, ldk_peer_listening_port, + network, }) } @@ -84,8 +101,8 @@ pub(crate) fn poll_for_user_input(peer_manager: Arc, channel_manage chain::Access>, Arc>>, payment_storage: PaymentInfoStorage, node_privkey: SecretKey, event_notifier: mpsc::Sender<()>, ldk_data_dir: String, logger: Arc, - runtime_handle: Handle) { - println!("LDK startup successful. To view available commands: \"help\".\nLDK logs are available in the `logs` folder of /.ldk/logs"); + runtime_handle: Handle, network: Network) { + println!("LDK startup successful. To view available commands: \"help\".\nLDK logs are available at /.ldk/logs"); let stdin = io::stdin(); print!("> "); io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print for line in stdin.lock().lines() { @@ -165,28 +182,30 @@ pub(crate) fn poll_for_user_input(peer_manager: Arc, channel_manage 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.set_supports_var_onion_optin(); + invoice_features = invoice_features.set_variable_length_onion_optional(); } if vec.len() >= 6 && vec[5].to_u8() & 0b01000 != 0 { - invoice_features.set_requires_var_onion_optin(); + invoice_features = invoice_features.set_variable_length_onion_required(); } if vec.len() >= 4 && vec[3].to_u8() & 0b00001 != 0 { - invoice_features.set_supports_payment_secret(); + invoice_features = invoice_features.set_payment_secret_optional(); } if vec.len() >= 5 && vec[4].to_u8() & 0b10000 != 0 { - invoice_features.set_requires_payment_secret(); + invoice_features = invoice_features.set_payment_secret_required(); } if vec.len() >= 4 && vec[3].to_u8() & 0b00100 != 0 { - invoice_features.set_supports_basic_mpp(); + invoice_features = invoice_features.set_basic_mpp_optional(); } if vec.len() >= 4 && vec[3].to_u8() & 0b00010 != 0 { - invoice_features.set_requires_basic_mpp(); + invoice_features = invoice_features.set_basic_mpp_required(); } } }, @@ -215,7 +234,7 @@ pub(crate) fn poll_for_user_input(peer_manager: Arc, channel_manage print!("> "); io::stdout().flush().unwrap(); continue; } get_invoice(amt_sat.unwrap(), payment_storage.clone(), node_privkey.clone(), - channel_manager.clone(), router.clone()); + channel_manager.clone(), network); }, "connectpeer" => { let peer_pubkey_and_ip_addr = words.next(); @@ -277,7 +296,7 @@ pub(crate) fn poll_for_user_input(peer_manager: Arc, channel_manage } fn help() { - println!("openchannel pubkey@host:port channel_amt_satoshis"); + println!("openchannel pubkey@host:port "); println!("sendpayment "); println!("getinvoice "); println!("connectpeer pubkey@host:port"); @@ -313,10 +332,15 @@ fn list_payments(payment_storage: PaymentInfoStorage) { let payments = payment_storage.lock().unwrap(); print!("["); for (payment_hash, payment_info) in payments.deref() { + let direction_str = match payment_info.1 { + HTLCDirection::Inbound => "inbound", + HTLCDirection::Outbound => "outbound", + }; println!(""); println!("\t{{"); + println!("\t\tamount_satoshis: {},", payment_info.3); println!("\t\tpayment_hash: {},", hex_utils::hex_str(&payment_hash.0)); - println!("\t\thtlc_direction: {},", if payment_info.1 == HTLCDirection::Inbound { "inbound" } else { "outbound" }); + println!("\t\thtlc_direction: {},", direction_str); println!("\t\thtlc_status: {},", match payment_info.2 { HTLCStatus::Pending => "pending", HTLCStatus::Succeeded => "succeeded", @@ -376,11 +400,10 @@ fn open_channel(peer_pubkey: PublicKey, channel_amt_sat: u64, channel_manager: A } fn send_payment(payee: PublicKey, amt_msat: u64, final_cltv: u32, payment_hash: PaymentHash, - payment_secret: Option, payee_features: - Option, router: Arc, Arc>>, channel_manager: - Arc, payment_storage: PaymentInfoStorage, logger: - Arc) { + payment_secret: Option, payee_features: Option, + router: Arc, Arc>>, + channel_manager: Arc, payment_storage: PaymentInfoStorage, logger: + Arc) { let network_graph = router.network_graph.read().unwrap(); let first_hops = channel_manager.list_usable_channels(); let payer_pubkey = channel_manager.get_our_node_id(); @@ -403,12 +426,12 @@ fn send_payment(payee: PublicKey, amt_msat: u64, final_cltv: u32, payment_hash: } }; let mut payments = payment_storage.lock().unwrap(); - payments.insert(payment_hash, (None, HTLCDirection::Outbound, status)); + payments.insert(payment_hash, (None, HTLCDirection::Outbound, status, + SatoshiAmount(Some(amt_msat * 1000)))); } fn get_invoice(amt_sat: u64, payment_storage: PaymentInfoStorage, our_node_privkey: SecretKey, - channel_manager: Arc, router: Arc, Arc>>) { + channel_manager: Arc, network: Network) { let mut payments = payment_storage.lock().unwrap(); let secp_ctx = Secp256k1::new(); @@ -418,54 +441,39 @@ fn get_invoice(amt_sat: u64, payment_storage: PaymentInfoStorage, our_node_privk let our_node_pubkey = channel_manager.get_our_node_id(); - let invoice = lightning_invoice::InvoiceBuilder::new(match NETWORK { + let mut invoice = lightning_invoice::InvoiceBuilder::new(match network { Network::Bitcoin => lightning_invoice::Currency::Bitcoin, Network::Testnet => lightning_invoice::Currency::BitcoinTestnet, Network::Regtest => lightning_invoice::Currency::Regtest, Network::Signet => panic!("Signet invoices not supported") - }).payment_hash(payment_hash).description("rust-lightning-bitcoinrpc invoice".to_string()) - .amount_pico_btc(amt_sat * 10) + }) + .payment_hash(payment_hash).description("rust-lightning-bitcoinrpc invoice".to_string()) + .amount_pico_btc(amt_sat * 10_000) .current_timestamp() .payee_pub_key(our_node_pubkey); // Add route hints to the invoice. - // let our_channels = channel_manager.list_usable_channels(); - // let network_graph = router.network_graph.read().unwrap(); - // let network_channels = network_graph.get_channels(); - // for channel in our_channels { - // let short_channel_id_opt = channel.short_channel_id; - // if short_channel_id_opt.is_none() { - // continue - // } - - // let short_channel_id = short_channel_id_opt.unwrap(); - // let channel_routing_info_opt = network_channels.get(&short_channel_id); - // if channel_routing_info_opt.is_none() { - // continue - // } - - // let channel_routing_info = channel_routing_info_opt.unwrap(); - // let mut counterparty = channel_routing_info.node_two; - // let mut counterparty_chan_fees_opt = channel_routing_info.one_to_two.as_ref(); - // if channel_routing_info.node_two != our_node_pubkey { // e.g. if our counterparty is node_one - // counterparty = channel_routing_info.node_one; - // counterparty_chan_fees_opt = channel_routing_info.two_to_one.as_ref(); - // } - // if counterparty_chan_fees_opt.is_none() { - // continue - // } - - // let counterparty_chan_fees = counterparty_chan_fees_opt.unwrap(); - // invoice = invoice.route(vec![ - // lightning_invoice::RouteHop { - // short_channel_id: short_channel_id.to_be_bytes(), - // cltv_expiry_delta: counterparty_chan_fees.cltv_expiry_delta, - // fee_base_msat: counterparty_chan_fees.fees.base_msat, - // fee_proportional_millionths: counterparty_chan_fees.fees.proportional_millionths, - // pubkey: counterparty, - // } - // ]); - // } + let our_channels = channel_manager.list_usable_channels(); + 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, + }; + println!("VMW: adding routehop, info.fee base: {}", forwarding_info.fee_base_msat); + invoice = invoice.route(vec![ + lightning_invoice::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, + } + ]); + } // Sign the invoice. let invoice = invoice.build_signed(|msg_hash| { @@ -479,7 +487,8 @@ fn get_invoice(amt_sat: u64, payment_storage: PaymentInfoStorage, our_node_privk payments.insert(PaymentHash(payment_hash.into_inner()), (Some(PaymentPreimage(preimage)), HTLCDirection::Inbound, - HTLCStatus::Pending)); + HTLCStatus::Pending, + SatoshiAmount(Some(amt_sat)))); } fn close_channel(channel_id: [u8; 32], channel_manager: Arc) { diff --git a/src/disk.rs b/src/disk.rs index 81e2e95..cd4ea90 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -63,7 +63,7 @@ pub(crate) fn read_channel_peer_data(path: &Path) -> Result) -> +pub(crate) fn read_channelmonitors(path: String, keys_manager: Arc) -> Result)>, std::io::Error> { if !Path::new(&path).exists() { diff --git a/src/main.rs b/src/main.rs index 3c417ef..421db95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod convert; mod disk; mod hex_utils; -use background_processor::BackgroundProcessor; +use lightning_background_processor::BackgroundProcessor; use bitcoin::BlockHash; use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::transaction::Transaction; @@ -39,6 +39,7 @@ use lightning_persister::FilesystemPersister; use rand::{thread_rng, Rng}; use lightning::routing::network_graph::NetGraphMsgHandler; use std::collections::HashMap; +use std::fmt; use std::fs; use std::fs::File; use std::io; @@ -50,8 +51,6 @@ use std::time::{Duration, SystemTime}; use tokio::runtime::Runtime; use tokio::sync::mpsc; -pub(crate) const NETWORK: Network = Network::Regtest; - #[derive(PartialEq)] pub(crate) enum HTLCDirection { Inbound, @@ -64,8 +63,21 @@ pub(crate) enum HTLCStatus { Failed, } +pub(crate) struct SatoshiAmount(Option); + +impl fmt::Display for SatoshiAmount { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + Some(amt) => write!(f, "{}", amt), + None => write!(f, "unknown") + + } + } +} + pub(crate) type PaymentInfoStorage = Arc, - HTLCDirection, HTLCStatus)>>>; + HTLCDirection, HTLCStatus, + SatoshiAmount)>>>; type ArcChainMonitor = ChainMonitor, Arc, Arc, Arc, Arc>; @@ -78,7 +90,8 @@ FilesystemLogger>; fn handle_ldk_events(peer_manager: Arc, channel_manager: Arc, chain_monitor: Arc, bitcoind_client: Arc, - keys_manager: Arc, payment_storage: PaymentInfoStorage) + keys_manager: Arc, payment_storage: PaymentInfoStorage, + network: Network) { let mut pending_txs: HashMap = HashMap::new(); loop { @@ -92,7 +105,7 @@ fn handle_ldk_events(peer_manager: Arc, channel_manager: Arc { // Construct the raw transaction with one output, that is paid the amount of the // channel. - let addr = WitnessProgram::from_scriptpubkey(&output_script[..], match NETWORK { + let addr = WitnessProgram::from_scriptpubkey(&output_script[..], match network { Network::Bitcoin => bitcoin_bech32::constants::Network::Bitcoin, Network::Testnet => bitcoin_bech32::constants::Network::Testnet, Network::Regtest => bitcoin_bech32::constants::Network::Regtest, @@ -129,31 +142,33 @@ fn handle_ldk_events(peer_manager: Arc, channel_manager: Arc { let mut payments = payment_storage.lock().unwrap(); - if let Some((Some(preimage), _, _)) = payments.get(&payment_hash) { + if let Some((Some(preimage), _, _, _)) = payments.get(&payment_hash) { assert!(loop_channel_manager.claim_funds(preimage.clone(), &payment_secret, amt_msat)); println!("\nEVENT: received payment from payment_hash {} of {} satoshis", hex_utils::hex_str(&payment_hash.0), amt_msat / 1000); print!("> "); io::stdout().flush().unwrap(); - let (_, _, ref mut status) = payments.get_mut(&payment_hash).unwrap(); + let (_, _, ref mut status, _) = payments.get_mut(&payment_hash).unwrap(); *status = HTLCStatus::Succeeded; } else { println!("\nERROR: we received a payment but didn't know the preimage"); print!("> "); io::stdout().flush().unwrap(); loop_channel_manager.fail_htlc_backwards(&payment_hash, &payment_secret); - payments.insert(payment_hash, (None, HTLCDirection::Inbound, HTLCStatus::Failed)); + payments.insert(payment_hash, (None, HTLCDirection::Inbound, + HTLCStatus::Failed, SatoshiAmount(None))); } }, Event::PaymentSent { payment_preimage } => { let hashed = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); let mut payments = payment_storage.lock().unwrap(); - for (payment_hash, (preimage_option, _, status)) in payments.iter_mut() { + for (payment_hash, (preimage_option, _, status, amt_sat)) in payments.iter_mut() { if *payment_hash == hashed { *preimage_option = Some(payment_preimage); *status = HTLCStatus::Succeeded; - println!("\nNEW EVENT: successfully sent payment from payment hash \ - {:?} with preimage {:?}", hex_utils::hex_str(&payment_hash.0), - hex_utils::hex_str(&payment_preimage.0)); + println!("\nNEW EVENT: successfully sent payment of {} satoshis from \ + payment hash {:?} with preimage {:?}", amt_sat, + hex_utils::hex_str(&payment_hash.0), + hex_utils::hex_str(&payment_preimage.0)); print!("> "); io::stdout().flush().unwrap(); } } @@ -170,7 +185,7 @@ fn handle_ldk_events(peer_manager: Arc, channel_manager: Arc, channel_manager: Arc Arc::new(client), + Err(e) => { + println!("Failed to connect to bitcoind client: {}", e); + return + } + }; let mut bitcoind_rpc_client = bitcoind_client.get_new_rpc_client().unwrap(); // ## Setup @@ -258,8 +277,8 @@ fn main() { // Step 7: Read ChannelMonitor state from disk let monitors_path = format!("{}/monitors", ldk_data_dir.clone()); - let mut outpoint_to_channelmonitor = disk::read_channelmonitors_from_disk(monitors_path.to_string(), - keys_manager.clone()).unwrap(); + let mut outpoint_to_channelmonitor = disk::read_channelmonitors(monitors_path.to_string(), + keys_manager.clone()).unwrap(); // Step 9: Initialize the ChannelManager let user_config = UserConfig::default(); @@ -280,7 +299,7 @@ fn main() { restarting_node = false; let getinfo_resp = bitcoind_client.get_blockchain_info(); let chain_params = ChainParameters { - network: NETWORK, + network: args.network, latest_hash: getinfo_resp.latest_blockhash, latest_height: getinfo_resp.latest_height, }; @@ -314,7 +333,7 @@ fn main() { chain_listeners.push((monitor_listener_info.0, &mut monitor_listener_info.1 as &mut dyn chain::Listen)); } - chain_tip = Some(runtime.block_on(init::synchronize_listeners(&mut bitcoind_rpc_client, NETWORK, + chain_tip = Some(runtime.block_on(init::synchronize_listeners(&mut bitcoind_rpc_client, args.network, &mut cache, chain_listeners)).unwrap()); } @@ -327,7 +346,7 @@ fn main() { // Step 13: Optional: Initialize the NetGraphMsgHandler // XXX persist routing data - let genesis = genesis_block(NETWORK).header.block_hash(); + let genesis = genesis_block(args.network).header.block_hash(); let router = Arc::new(NetGraphMsgHandler::new(genesis, None::>, logger.clone())); // Step 14: Initialize the PeerManager @@ -364,8 +383,9 @@ fn main() { } let channel_manager_listener = channel_manager.clone(); let chain_monitor_listener = chain_monitor.clone(); + let network = args.network; runtime.spawn(async move { - let chain_poller = poll::ChainPoller::new(&mut bitcoind_rpc_client, NETWORK); + let chain_poller = poll::ChainPoller::new(&mut bitcoind_rpc_client, network); let chain_listener = (chain_monitor_listener, channel_manager_listener); let mut spv_client = SpvClient::new(chain_tip.unwrap(), chain_poller, &mut cache, &chain_listener); @@ -401,10 +421,11 @@ fn main() { let payment_info: PaymentInfoStorage = Arc::new(Mutex::new(HashMap::new())); let payment_info_for_events = payment_info.clone(); let handle = runtime_handle.clone(); + let network = args.network; thread::spawn(move || { handle_ldk_events(peer_manager_event_listener, channel_manager_event_listener, chain_monitor_event_listener, bitcoind_client.clone(), - keys_manager_listener, payment_info_for_events); + keys_manager_listener, payment_info_for_events, network); }); // Reconnect to channel peers if possible. @@ -422,5 +443,5 @@ fn main() { // Start the CLI. cli::poll_for_user_input(peer_manager.clone(), channel_manager.clone(), router.clone(), payment_info, keys_manager.get_node_secret(), event_ntfn_sender, - ldk_data_dir.clone(), logger.clone(), handle); + ldk_data_dir.clone(), logger.clone(), handle, args.network); }