Merge pull request #40 from jkczyz/2021-11-release-103
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Thu, 4 Nov 2021 21:13:12 +0000 (21:13 +0000)
committerGitHub <noreply@github.com>
Thu, 4 Nov 2021 21:13:12 +0000 (21:13 +0000)
Update sample for 0.0.103

Cargo.lock
Cargo.toml
src/cli.rs
src/disk.rs
src/main.rs

index e0c7e9f398f93c5b4c6a03b5d80a7a22bc4dcd64..f2bdbc7fbe043fbdc7c4730de40b030dff8104b3 100644 (file)
@@ -8,12 +8,6 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
-[[package]]
-name = "base-x"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
-
 [[package]]
 name = "base64"
 version = "0.13.0"
@@ -52,12 +46,6 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "006cc91e1a1d99819bc5b8214be3555c1f0611b169f527a1fdc54ed1f2b745b0"
 
-[[package]]
-name = "bumpalo"
-version = "3.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
-
 [[package]]
 name = "bytes"
 version = "1.0.1"
@@ -77,22 +65,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
-name = "chunked_transfer"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
-
-[[package]]
-name = "const_fn"
-version = "0.4.8"
+name = "chrono"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time",
+ "winapi",
+]
 
 [[package]]
-name = "discard"
-version = "1.0.4"
+name = "chunked_transfer"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
+checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
 
 [[package]]
 name = "fuchsia-cprng"
@@ -215,12 +204,6 @@ version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
 
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
 [[package]]
 name = "ldk-tutorial-node"
 version = "0.1.0"
@@ -229,6 +212,7 @@ dependencies = [
  "bech32",
  "bitcoin",
  "bitcoin-bech32",
+ "chrono",
  "futures",
  "hex",
  "lightning",
@@ -239,7 +223,6 @@ dependencies = [
  "lightning-persister",
  "rand",
  "serde_json",
- "time",
  "tokio",
 ]
 
@@ -251,8 +234,9 @@ checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
 
 [[package]]
 name = "lightning"
-version = "0.0.100"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f4cc6a6bc500226fe2716b8557fe66b57fd8d86348e4478b57de13a4dd6b8f0"
 dependencies = [
  "bitcoin",
  "secp256k1",
@@ -260,8 +244,9 @@ dependencies = [
 
 [[package]]
 name = "lightning-background-processor"
-version = "0.0.100"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c0cded269444c0b1d19d92b79a60b1d9188f377c2e7ddd6d0c8860b80f3ea4a"
 dependencies = [
  "bitcoin",
  "lightning",
@@ -270,12 +255,12 @@ dependencies = [
 
 [[package]]
 name = "lightning-block-sync"
-version = "0.0.100"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0af7169b0f238dd5c845ee1d95201fbb69acb2b93d9aea5a75b6d593abcd674f"
 dependencies = [
  "bitcoin",
  "chunked_transfer",
- "futures",
  "lightning",
  "serde",
  "serde_json",
@@ -283,8 +268,9 @@ dependencies = [
 
 [[package]]
 name = "lightning-invoice"
-version = "0.8.0"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f7cc25650f634e074b0b64a793ac535f7ad2ae418dd7f0ac88972832d2f22bc"
 dependencies = [
  "bech32",
  "bitcoin_hashes",
@@ -295,8 +281,9 @@ dependencies = [
 
 [[package]]
 name = "lightning-net-tokio"
-version = "0.0.100"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af4ba9c57851bfaa872a9fbea41065812d03da30bf24680e08c074b972cb3e8d"
 dependencies = [
  "bitcoin",
  "lightning",
@@ -305,8 +292,9 @@ dependencies = [
 
 [[package]]
 name = "lightning-persister"
-version = "0.0.100"
-source = "git+https://github.com/rust-bitcoin/rust-lightning?rev=d523b6e#d523b6e42b5b0fde07a89770906e0193ea987538"
+version = "0.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ea68c7b0a8b0bc01103d189206bd09c8501bd0fad721229d1e36743a80ed010"
 dependencies = [
  "bitcoin",
  "libc",
@@ -360,6 +348,16 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.14"
@@ -458,15 +456,6 @@ dependencies = [
  "rand_core 0.3.1",
 ]
 
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
 [[package]]
 name = "ryu"
 version = "1.0.5"
@@ -491,21 +480,6 @@ dependencies = [
  "cc",
 ]
 
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
 [[package]]
 name = "serde"
 version = "1.0.127"
@@ -537,76 +511,12 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "sha1"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
-
 [[package]]
 name = "slab"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
 
-[[package]]
-name = "standback"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
-dependencies = [
- "version_check",
-]
-
-[[package]]
-name = "stdweb"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
-dependencies = [
- "discard",
- "rustc_version",
- "stdweb-derive",
- "stdweb-internal-macros",
- "stdweb-internal-runtime",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "stdweb-derive"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-macros"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
-dependencies = [
- "base-x",
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "serde_json",
- "sha1",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-runtime"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
-
 [[package]]
 name = "syn"
 version = "1.0.74"
@@ -620,42 +530,15 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.2.27"
+version = "0.1.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
 dependencies = [
- "const_fn",
  "libc",
- "standback",
- "stdweb",
- "time-macros",
- "version_check",
+ "wasi",
  "winapi",
 ]
 
-[[package]]
-name = "time-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
-dependencies = [
- "proc-macro-hack",
- "time-macros-impl",
-]
-
-[[package]]
-name = "time-macros-impl"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
-dependencies = [
- "proc-macro-hack",
- "proc-macro2",
- "quote",
- "standback",
- "syn",
-]
-
 [[package]]
 name = "tokio"
 version = "1.10.0"
@@ -691,64 +574,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 
 [[package]]
-name = "version_check"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.75"
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
 
 [[package]]
 name = "winapi"
index cc9f50143a57d0d3e5c89cef281bcde97ff637b9..32f6cf4346cc13f57db70b521387da82373cf1eb 100644 (file)
@@ -8,12 +8,12 @@ edition = "2018"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-lightning = { version = "0.0.102" }
-lightning-block-sync = { version = "0.0.102", features = [ "rpc-client" ] }
-lightning-invoice = { version = "0.10.0" }
-lightning-net-tokio = { version = "0.0.102" }
-lightning-persister = { version = "0.0.102" }
-lightning-background-processor = { version = "0.0.102" }
+lightning = { version = "0.0.103" }
+lightning-block-sync = { version = "0.0.103", features = [ "rpc-client" ] }
+lightning-invoice = { version = "0.11.0" }
+lightning-net-tokio = { version = "0.0.103" }
+lightning-persister = { version = "0.0.103" }
+lightning-background-processor = { version = "0.0.103" }
 
 base64 = "0.13.0"
 bitcoin = "0.27"
index b8db89dcfb217f4a625d5b2215b7d4f3e3ca17d7..54b2eab7c5f46fda4ba7f60c39ee85a09c3fc6fb 100644 (file)
@@ -1,22 +1,22 @@
 use crate::disk;
 use crate::hex_utils;
 use crate::{
-       ChannelManager, FilesystemLogger, HTLCStatus, MillisatAmount, PaymentInfo, PaymentInfoStorage,
-       PeerManager,
+       ChannelManager, FilesystemLogger, HTLCStatus, InvoicePayer, MillisatAmount, PaymentInfo,
+       PaymentInfoStorage, PeerManager,
 };
 use bitcoin::hashes::Hash;
 use bitcoin::network::constants::Network;
 use bitcoin::secp256k1::key::PublicKey;
-use lightning::chain;
 use lightning::chain::keysinterface::{KeysInterface, KeysManager};
-use lightning::ln::features::InvoiceFeatures;
 use lightning::ln::msgs::NetAddress;
-use lightning::ln::{PaymentHash, PaymentSecret};
-use lightning::routing::network_graph::NetGraphMsgHandler;
+use lightning::ln::PaymentHash;
+use lightning::routing::network_graph::NetworkGraph;
 use lightning::routing::router;
-use lightning::routing::router::RouteHint;
+use lightning::routing::router::{Payee, RouteParameters};
 use lightning::routing::scorer::Scorer;
 use lightning::util::config::{ChannelConfig, ChannelHandshakeLimits, UserConfig};
+use lightning::util::events::EventHandler;
+use lightning_invoice::payment::PaymentError;
 use lightning_invoice::{utils, Currency, Invoice};
 use std::env;
 use std::io;
@@ -25,7 +25,7 @@ use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
 use std::ops::Deref;
 use std::path::Path;
 use std::str::FromStr;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 use std::time::Duration;
 
 pub(crate) struct LdkUserInfo {
@@ -140,10 +140,10 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
        })
 }
 
-pub(crate) async fn poll_for_user_input(
-       peer_manager: Arc<PeerManager>, channel_manager: Arc<ChannelManager>,
-       keys_manager: Arc<KeysManager>,
-       router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access + Send + Sync>, Arc<FilesystemLogger>>>,
+pub(crate) async fn poll_for_user_input<E: EventHandler>(
+       invoice_payer: Arc<InvoicePayer<E>>, peer_manager: Arc<PeerManager>,
+       channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>,
+       network_graph: Arc<NetworkGraph>, scorer: Arc<Mutex<Scorer>>,
        inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage,
        ldk_data_dir: String, logger: Arc<FilesystemLogger>, network: Network,
 ) {
@@ -242,36 +242,8 @@ pub(crate) async fn poll_for_user_input(
                                                        continue;
                                                }
                                        };
-                                       let last_hops = invoice.route_hints();
 
-                                       let amt_pico_btc = invoice.amount_pico_btc();
-                                       if amt_pico_btc.is_none() {
-                                               println!("ERROR: invalid invoice: must contain amount to pay");
-                                               print!("> ");
-                                               io::stdout().flush().unwrap();
-                                               continue;
-                                       }
-                                       let amt_msat = amt_pico_btc.unwrap() / 10;
-
-                                       let payee_pubkey = invoice.recover_payee_pub_key();
-                                       let final_cltv = invoice.min_final_cltv_expiry() as u32;
-                                       let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-                                       let payment_secret = Some(invoice.payment_secret().clone());
-                                       let invoice_features = invoice.features().cloned();
-
-                                       send_payment(
-                                               payee_pubkey,
-                                               amt_msat,
-                                               final_cltv,
-                                               payment_hash,
-                                               payment_secret,
-                                               invoice_features,
-                                               last_hops,
-                                               router.clone(),
-                                               channel_manager.clone(),
-                                               outbound_payments.clone(),
-                                               logger.clone(),
-                                       );
+                                       send_payment(&*invoice_payer, &invoice, outbound_payments.clone());
                                }
                                "keysend" => {
                                        let dest_pubkey = match words.next() {
@@ -313,10 +285,11 @@ pub(crate) async fn poll_for_user_input(
                                        keysend(
                                                dest_pubkey,
                                                amt_msat,
-                                               router.clone(),
+                                               network_graph.clone(),
                                                channel_manager.clone(),
                                                outbound_payments.clone(),
                                                logger.clone(),
+                                               scorer.clone(),
                                        );
                                }
                                "getinvoice" => {
@@ -606,45 +579,36 @@ fn open_channel(
        }
 }
 
-fn send_payment(
-       payee: PublicKey, amt_msat: u64, final_cltv: u32, payment_hash: PaymentHash,
-       payment_secret: Option<PaymentSecret>, payee_features: Option<InvoiceFeatures>,
-       route_hints: Vec<&RouteHint>,
-       router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access + Send + Sync>, Arc<FilesystemLogger>>>,
-       channel_manager: Arc<ChannelManager>, payment_storage: PaymentInfoStorage,
-       logger: Arc<FilesystemLogger>,
+fn send_payment<E: EventHandler>(
+       invoice_payer: &InvoicePayer<E>, invoice: &Invoice, payment_storage: PaymentInfoStorage,
 ) {
-       let network_graph = &router.network_graph;
-       let first_hops = channel_manager.list_usable_channels();
-       let payer_pubkey = channel_manager.get_our_node_id();
-
-       let route = router::get_route(
-               &payer_pubkey,
-               &network_graph,
-               &payee,
-               payee_features,
-               Some(&first_hops.iter().collect::<Vec<_>>()),
-               &route_hints,
-               amt_msat,
-               final_cltv,
-               logger,
-               &Scorer::default(),
-       );
-       if let Err(e) = route {
-               println!("ERROR: failed to find route: {}", e.err);
-               return;
-       }
-       let status = match channel_manager.send_payment(&route.unwrap(), payment_hash, &payment_secret)
-       {
+       let status = match invoice_payer.pay_invoice(invoice) {
                Ok(_payment_id) => {
-                       println!("EVENT: initiated sending {} msats to {}", amt_msat, payee);
+                       let payee_pubkey = invoice.recover_payee_pub_key();
+                       let amt_msat = invoice.amount_milli_satoshis().unwrap();
+                       println!("EVENT: initiated sending {} msats to {}", amt_msat, payee_pubkey);
+                       print!("> ");
                        HTLCStatus::Pending
                }
-               Err(e) => {
+               Err(PaymentError::Invoice(e)) => {
+                       println!("ERROR: invalid invoice: {}", e);
+                       print!("> ");
+                       return;
+               }
+               Err(PaymentError::Routing(e)) => {
+                       println!("ERROR: failed to find route: {}", e.err);
+                       print!("> ");
+                       return;
+               }
+               Err(PaymentError::Sending(e)) => {
                        println!("ERROR: failed to send payment: {:?}", e);
+                       print!("> ");
                        HTLCStatus::Failed
                }
        };
+       let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
+       let payment_secret = Some(invoice.payment_secret().clone());
+
        let mut payments = payment_storage.lock().unwrap();
        payments.insert(
                payment_hash,
@@ -652,31 +616,29 @@ fn send_payment(
                        preimage: None,
                        secret: payment_secret,
                        status,
-                       amt_msat: MillisatAmount(Some(amt_msat)),
+                       amt_msat: MillisatAmount(invoice.amount_milli_satoshis()),
                },
        );
 }
 
 fn keysend(
-       payee: PublicKey, amt_msat: u64,
-       router: Arc<NetGraphMsgHandler<Arc<dyn chain::Access + Send + Sync>, Arc<FilesystemLogger>>>,
+       payee_pubkey: PublicKey, amt_msat: u64, network_graph: Arc<NetworkGraph>,
        channel_manager: Arc<ChannelManager>, payment_storage: PaymentInfoStorage,
-       logger: Arc<FilesystemLogger>,
+       logger: Arc<FilesystemLogger>, scorer: Arc<Mutex<Scorer>>,
 ) {
-       let network_graph = &router.network_graph;
        let first_hops = channel_manager.list_usable_channels();
        let payer_pubkey = channel_manager.get_our_node_id();
 
-       let route = match router::get_keysend_route(
+       let payee = Payee::for_keysend(payee_pubkey);
+       let params = RouteParameters { payee, final_value_msat: amt_msat, final_cltv_expiry_delta: 40 };
+
+       let route = match router::find_route(
                &payer_pubkey,
+               &params,
                &network_graph,
-               &payee,
                Some(&first_hops.iter().collect::<Vec<_>>()),
-               &vec![],
-               amt_msat,
-               40,
                logger,
-               &Scorer::default(),
+               &scorer.lock().unwrap(),
        ) {
                Ok(r) => r,
                Err(e) => {
index b641ebb053167b01c6f397c1ef40d0decd98ad61..7be070c962f4d73e3c9445c8a5a8730fedd71fe3 100644 (file)
@@ -3,6 +3,7 @@ use bitcoin::secp256k1::key::PublicKey;
 use bitcoin::BlockHash;
 use chrono::Utc;
 use lightning::routing::network_graph::NetworkGraph;
+use lightning::routing::scorer::Scorer;
 use lightning::util::logger::{Logger, Record};
 use lightning::util::ser::{Readable, Writeable, Writer};
 use std::collections::HashMap;
@@ -92,3 +93,25 @@ pub(crate) fn read_network(path: &Path, genesis_hash: BlockHash) -> NetworkGraph
        }
        NetworkGraph::new(genesis_hash)
 }
+
+pub(crate) fn persist_scorer(path: &Path, scorer: &Scorer) -> std::io::Result<()> {
+       let mut tmp_path = path.to_path_buf().into_os_string();
+       tmp_path.push(".tmp");
+       let file = fs::OpenOptions::new().write(true).create(true).open(&tmp_path)?;
+       let write_res = scorer.write(&mut BufWriter::new(file));
+       if let Err(e) = write_res.and_then(|_| fs::rename(&tmp_path, path)) {
+               let _ = fs::remove_file(&tmp_path);
+               Err(e)
+       } else {
+               Ok(())
+       }
+}
+
+pub(crate) fn read_scorer(path: &Path) -> Scorer {
+       if let Ok(file) = File::open(path) {
+               if let Ok(scorer) = Scorer::read(&mut BufReader::new(file)) {
+                       return scorer;
+               }
+       }
+       Scorer::default()
+}
index f66d4ed393eabfb82aa82fb2cc190c2d249e4444..421069b804ed2aae75ebecc35389a4a4705203f0 100644 (file)
@@ -24,7 +24,8 @@ use lightning::ln::channelmanager::{
 };
 use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler, SimpleArcPeerManager};
 use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::routing::network_graph::NetGraphMsgHandler;
+use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
+use lightning::routing::scorer::Scorer;
 use lightning::util::config::UserConfig;
 use lightning::util::events::{Event, PaymentPurpose};
 use lightning::util::ser::ReadableArgs;
@@ -33,6 +34,8 @@ use lightning_block_sync::init;
 use lightning_block_sync::poll;
 use lightning_block_sync::SpvClient;
 use lightning_block_sync::UnboundedCache;
+use lightning_invoice::payment;
+use lightning_invoice::utils::DefaultRouter;
 use lightning_net_tokio::SocketDescriptor;
 use lightning_persister::FilesystemPersister;
 use rand::{thread_rng, Rng};
@@ -95,6 +98,16 @@ pub(crate) type PeerManager = SimpleArcPeerManager<
 pub(crate) type ChannelManager =
        SimpleArcChannelManager<ChainMonitor, BitcoindClient, BitcoindClient, FilesystemLogger>;
 
+pub(crate) type InvoicePayer<E> = payment::InvoicePayer<
+       Arc<ChannelManager>,
+       Router,
+       Arc<Mutex<Scorer>>,
+       Arc<FilesystemLogger>,
+       E,
+>;
+
+type Router = DefaultRouter<Arc<NetworkGraph>, Arc<FilesystemLogger>>;
+
 async fn handle_ldk_events(
        channel_manager: Arc<ChannelManager>, bitcoind_client: Arc<BitcoindClient>,
        keys_manager: Arc<KeysManager>, inbound_payments: PaymentInfoStorage,
@@ -182,7 +195,7 @@ async fn handle_ldk_events(
                                }
                        }
                }
-               Event::PaymentSent { payment_preimage, payment_hash } => {
+               Event::PaymentSent { payment_preimage, payment_hash, .. } => {
                        let mut payments = outbound_payments.lock().unwrap();
                        for (hash, payment) in payments.iter_mut() {
                                if *hash == *payment_hash {
@@ -203,10 +216,9 @@ async fn handle_ldk_events(
                Event::PaymentPathFailed {
                        payment_hash,
                        rejected_by_dest,
-                       network_update: _,
                        all_paths_failed,
-                       path: _,
                        short_channel_id,
+                       ..
                } => {
                        print!(
                                "\nEVENT: Failed to send payment{} to payment hash {:?}",
@@ -219,7 +231,7 @@ async fn handle_ldk_events(
                        if *rejected_by_dest {
                                println!(": re-attempting the payment will not succeed");
                        } else {
-                               println!(": payment may be retried");
+                               println!(": exhausted payment retry attempts");
                        }
                        print!("> ");
                        io::stdout().flush().unwrap();
@@ -479,18 +491,18 @@ async fn start_ldk() {
        // Step 11: Optional: Initialize the NetGraphMsgHandler
        let genesis = genesis_block(args.network).header.block_hash();
        let network_graph_path = format!("{}/network_graph", ldk_data_dir.clone());
-       let network_graph = disk::read_network(Path::new(&network_graph_path), genesis);
-       let router = Arc::new(NetGraphMsgHandler::new(
-               network_graph,
+       let network_graph = Arc::new(disk::read_network(Path::new(&network_graph_path), genesis));
+       let network_gossip = Arc::new(NetGraphMsgHandler::new(
+               Arc::clone(&network_graph),
                None::<Arc<dyn chain::Access + Send + Sync>>,
                logger.clone(),
        ));
-       let router_persist = Arc::clone(&router);
+       let network_graph_persist = Arc::clone(&network_graph);
        tokio::spawn(async move {
                let mut interval = tokio::time::interval(Duration::from_secs(600));
                loop {
                        interval.tick().await;
-                       if disk::persist_network(Path::new(&network_graph_path), &router_persist.network_graph)
+                       if disk::persist_network(Path::new(&network_graph_path), &network_graph_persist)
                                .is_err()
                        {
                                // Persistence errors here are non-fatal as we can just fetch the routing graph
@@ -506,8 +518,10 @@ async fn start_ldk() {
        let channel_manager: Arc<ChannelManager> = 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 lightning_msg_handler = MessageHandler {
+               chan_handler: channel_manager.clone(),
+               route_handler: network_gossip.clone(),
+       };
        let peer_manager: Arc<PeerManager> = Arc::new(PeerManager::new(
                lightning_msg_handler,
                keys_manager.get_node_secret(),
@@ -581,17 +595,48 @@ async fn start_ldk() {
                        event,
                ));
        };
-       // Step 16: Persist ChannelManager
+
+       // Step 16: Initialize routing Scorer
+       let scorer_path = format!("{}/scorer", ldk_data_dir.clone());
+       let scorer = Arc::new(Mutex::new(disk::read_scorer(Path::new(&scorer_path))));
+       let scorer_persist = Arc::clone(&scorer);
+       tokio::spawn(async move {
+               let mut interval = tokio::time::interval(Duration::from_secs(600));
+               loop {
+                       interval.tick().await;
+                       if disk::persist_scorer(Path::new(&scorer_path), &scorer_persist.lock().unwrap())
+                               .is_err()
+                       {
+                               // Persistence errors here are non-fatal as channels will be re-scored as payments
+                               // fail, but they may indicate a disk error which could be fatal elsewhere.
+                               eprintln!("Warning: Failed to persist scorer, check your disk and permissions");
+                       }
+               }
+       });
+
+       // Step 17: Create InvoicePayer
+       let router = DefaultRouter::new(network_graph.clone(), logger.clone());
+       let invoice_payer = Arc::new(InvoicePayer::new(
+               channel_manager.clone(),
+               router,
+               scorer.clone(),
+               logger.clone(),
+               event_handler,
+               payment::RetryAttempts(5),
+       ));
+
+       // Step 18: Persist ChannelManager
        let data_dir = ldk_data_dir.clone();
        let persist_channel_manager_callback =
                move |node: &ChannelManager| FilesystemPersister::persist_manager(data_dir.clone(), &*node);
-       // Step 17: Background Processing
+
+       // Step 19: Background Processing
        let background_processor = BackgroundProcessor::start(
                persist_channel_manager_callback,
-               event_handler,
+               invoice_payer.clone(),
                chain_monitor.clone(),
                channel_manager.clone(),
-               Some(router.clone()),
+               Some(network_gossip.clone()),
                peer_manager.clone(),
                logger.clone(),
        );
@@ -635,10 +680,12 @@ async fn start_ldk() {
 
        // Start the CLI.
        cli::poll_for_user_input(
+               invoice_payer.clone(),
                peer_manager.clone(),
                channel_manager.clone(),
                keys_manager.clone(),
-               router.clone(),
+               network_graph.clone(),
+               scorer.clone(),
                inbound_payments,
                outbound_payments,
                ldk_data_dir.clone(),