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"
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",
[[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",
[[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",
[[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",
[[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",
name = "ldk-tutorial-node"
version = "0.1.0"
authors = ["Valentine Wallace <vwallace@protonmail.com>"]
+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" ] }
# 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 <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> <ldk_storage_directory_path> [<ldk-peer-listening-port>] [bitcoin-network]
+```
+`bitcoin-network`: defaults to `testnet`. Options: `testnet`, `regtest`.
+
+`ldk-peer-listening-port`: defaults to 9735.
## License
rpc_user,
rpc_password,
runtime: Mutex::new(Runtime::new().unwrap()),
- // runtime: Mutex::new(runtime),
};
Ok(client)
}
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() {
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(|| {
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;
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<LdkUserInfo, ()> {
if env::args().len() < 4 {
- 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 [optional: <ldk-incoming-peer-listening-port>]`");
+ 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 bitcoind_rpc_info = env::args().skip(1).next().unwrap();
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,
bitcoind_rpc_port,
ldk_storage_dir_path,
ldk_peer_listening_port,
+ network,
})
}
chain::Access>, Arc<FilesystemLogger>>>, payment_storage:
PaymentInfoStorage, node_privkey: SecretKey, event_notifier:
mpsc::Sender<()>, ldk_data_dir: String, logger: Arc<FilesystemLogger>,
- runtime_handle: Handle) {
- println!("LDK startup successful. To view available commands: \"help\".\nLDK logs are available in the `logs` folder of <your-supplied-ldk-data-dir-path>/.ldk/logs");
+ runtime_handle: Handle, 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();
print!("> "); io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
for line in stdin.lock().lines() {
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();
}
}
},
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();
}
fn help() {
- println!("openchannel pubkey@host:port channel_amt_satoshis");
+ println!("openchannel pubkey@host:port <channel_amt_satoshis>");
println!("sendpayment <invoice>");
println!("getinvoice <amt_in_satoshis>");
println!("connectpeer pubkey@host:port");
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",
}
fn send_payment(payee: PublicKey, amt_msat: u64, final_cltv: u32, payment_hash: PaymentHash,
- payment_secret: Option<PaymentSecret>, payee_features:
- Option<InvoiceFeatures>, router: Arc<NetGraphMsgHandler<Arc<dyn
- chain::Access>, Arc<FilesystemLogger>>>, channel_manager:
- Arc<ChannelManager>, payment_storage: PaymentInfoStorage, logger:
- Arc<FilesystemLogger>) {
+ payment_secret: Option<PaymentSecret>, payee_features: Option<InvoiceFeatures>,
+ router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access>, Arc<FilesystemLogger>>>,
+ channel_manager: Arc<ChannelManager>, payment_storage: PaymentInfoStorage, logger:
+ Arc<FilesystemLogger>) {
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();
}
};
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<ChannelManager>, router: Arc<NetGraphMsgHandler<Arc<dyn
- chain::Access>, Arc<FilesystemLogger>>>) {
+ channel_manager: Arc<ChannelManager>, network: Network) {
let mut payments = payment_storage.lock().unwrap();
let secp_ctx = Secp256k1::new();
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| {
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<ChannelManager>) {
}
-pub(crate) fn read_channelmonitors_from_disk(path: String, keys_manager: Arc<KeysManager>) ->
+pub(crate) fn read_channelmonitors(path: String, keys_manager: Arc<KeysManager>) ->
Result<HashMap<OutPoint, (BlockHash, ChannelMonitor<InMemorySigner>)>, std::io::Error>
{
if !Path::new(&path).exists() {
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;
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;
use tokio::runtime::Runtime;
use tokio::sync::mpsc;
-pub(crate) const NETWORK: Network = Network::Regtest;
-
#[derive(PartialEq)]
pub(crate) enum HTLCDirection {
Inbound,
Failed,
}
+pub(crate) struct SatoshiAmount(Option<u64>);
+
+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<Mutex<HashMap<PaymentHash, (Option<PaymentPreimage>,
- HTLCDirection, HTLCStatus)>>>;
+ HTLCDirection, HTLCStatus,
+ SatoshiAmount)>>>;
type ArcChainMonitor = ChainMonitor<InMemorySigner, Arc<dyn Filter>, Arc<BitcoindClient>,
Arc<BitcoindClient>, Arc<FilesystemLogger>, Arc<FilesystemPersister>>;
fn handle_ldk_events(peer_manager: Arc<PeerManager>, channel_manager: Arc<ChannelManager>,
chain_monitor: Arc<ArcChainMonitor>, bitcoind_client: Arc<BitcoindClient>,
- keys_manager: Arc<KeysManager>, payment_storage: PaymentInfoStorage)
+ keys_manager: Arc<KeysManager>, payment_storage: PaymentInfoStorage,
+ network: Network)
{
let mut pending_txs: HashMap<OutPoint, Transaction> = HashMap::new();
loop {
output_script, .. } => {
// 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,
},
Event::PaymentReceived { payment_hash, payment_secret, amt: amt_msat } => {
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();
}
}
let mut payments = payment_storage.lock().unwrap();
if payments.contains_key(&payment_hash) {
- let (_, _, ref mut status) = payments.get_mut(&payment_hash).unwrap();
+ let (_, _, ref mut status, _) = payments.get_mut(&payment_hash).unwrap();
*status = HTLCStatus::Failed;
}
},
destination_address.script_pubkey(),
tx_feerate, &Secp256k1::new()).unwrap();
bitcoind_client.broadcast_transaction(&spending_tx);
- // XXX maybe need to rescan and blah? but contrary to what matt's saying, it
- // looks like spend_spendable's got us covered
+ // XXX maybe need to rescan and blah?
}
}
}
fs::create_dir_all(ldk_data_dir.clone()).unwrap();
// Initialize our bitcoind client.
- let bitcoind_client = Arc::new(BitcoindClient::new(args.bitcoind_rpc_host.clone(),
- args.bitcoind_rpc_port,
- args.bitcoind_rpc_username.clone(),
- args.bitcoind_rpc_password.clone()).unwrap());
+ let bitcoind_client = match BitcoindClient::new(args.bitcoind_rpc_host.clone(),
+ args.bitcoind_rpc_port, args.bitcoind_rpc_username.clone(),
+ args.bitcoind_rpc_password.clone()) {
+ Ok(client) => 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
// 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();
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,
};
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());
}
// 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::<Arc<dyn chain::Access>>, logger.clone()));
// Step 14: Initialize the PeerManager
}
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);
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.
// 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);
}