Merge pull request #1972 from jkczyz/2023-01-bolt12-spec-updates
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Mon, 30 Jan 2023 23:36:20 +0000 (23:36 +0000)
committerGitHub <noreply@github.com>
Mon, 30 Jan 2023 23:36:20 +0000 (23:36 +0000)
BOLT 12 spec updates

56 files changed:
.github/workflows/build.yml
CONTRIBUTING.md
fuzz/Cargo.toml
fuzz/src/bin/gen_target.sh
fuzz/src/bin/indexedmap_target.rs [new file with mode: 0644]
fuzz/src/bin/msg_channel_details_target.rs [new file with mode: 0644]
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/indexedmap.rs [new file with mode: 0644]
fuzz/src/lib.rs
fuzz/src/onion_message.rs
fuzz/src/peer_crypt.rs
fuzz/targets.h
lightning-background-processor/src/lib.rs
lightning-block-sync/Cargo.toml
lightning-invoice/src/de.rs
lightning-invoice/src/lib.rs
lightning-invoice/src/payment.rs
lightning-invoice/src/ser.rs
lightning-invoice/src/utils.rs
lightning-invoice/tests/ser_de.rs
lightning-net-tokio/Cargo.toml
lightning-net-tokio/src/lib.rs
lightning/src/chain/chainmonitor.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/keysinterface.rs
lightning/src/chain/mod.rs
lightning/src/chain/onchaintx.rs
lightning/src/chain/package.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/features.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/inbound_payment.rs
lightning/src/ln/monitor_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/ln/outbound_payment.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/peer_channel_encryptor.rs
lightning/src/ln/peer_handler.rs
lightning/src/ln/priv_short_conf_tests.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/routing/gossip.rs
lightning/src/routing/router.rs
lightning/src/util/config.rs
lightning/src/util/enforcing_trait_impls.rs
lightning/src/util/events.rs
lightning/src/util/indexed_map.rs [new file with mode: 0644]
lightning/src/util/macro_logger.rs
lightning/src/util/mod.rs
lightning/src/util/persist.rs
lightning/src/util/test_utils.rs
pending_changelog/1878.txt [new file with mode: 0644]

index f27a2ccf863fa0348295a3f0c56810fa48280eb7..340b7f898d9ded31ba5b035e71fcf0ca83924419 100644 (file)
@@ -242,19 +242,19 @@ jobs:
         id: cache-graph
         uses: actions/cache@v3
         with:
-          path: lightning/net_graph-2021-05-31.bin
-          key: ldk-net_graph-v0.0.15-2021-05-31.bin
+          path: lightning/net_graph-2023-01-18.bin
+          key: ldk-net_graph-v0.0.113-2023-01-18.bin
       - name: Fetch routing graph snapshot
         if: steps.cache-graph.outputs.cache-hit != 'true'
         run: |
-          curl --verbose -L -o lightning/net_graph-2021-05-31.bin https://bitcoin.ninja/ldk-net_graph-v0.0.15-2021-05-31.bin
-          echo "Sha sum: $(sha256sum lightning/net_graph-2021-05-31.bin | awk '{ print $1 }')"
-          if [ "$(sha256sum lightning/net_graph-2021-05-31.bin | awk '{ print $1 }')" != "${EXPECTED_ROUTING_GRAPH_SNAPSHOT_SHASUM}" ]; then
+          curl --verbose -L -o lightning/net_graph-2023-01-18.bin https://bitcoin.ninja/ldk-net_graph-v0.0.113-2023-01-18.bin
+          echo "Sha sum: $(sha256sum lightning/net_graph-2023-01-18.bin | awk '{ print $1 }')"
+          if [ "$(sha256sum lightning/net_graph-2023-01-18.bin | awk '{ print $1 }')" != "${EXPECTED_ROUTING_GRAPH_SNAPSHOT_SHASUM}" ]; then
             echo "Bad hash"
             exit 1
           fi
         env:
-          EXPECTED_ROUTING_GRAPH_SNAPSHOT_SHASUM: 05a5361278f68ee2afd086cc04a1f927a63924be451f3221d380533acfacc303
+          EXPECTED_ROUTING_GRAPH_SNAPSHOT_SHASUM: da6066f2bddcddbe7d8a6debbd53545697137b310bbb8c4911bc8c81fc5ff48c
       - name: Fetch rapid graph sync reference input
         run: |
           curl --verbose -L -o lightning-rapid-gossip-sync/res/full_graph.lngossip https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin
index 6f12c21e9f9d6c9035d3225316d3e5ed42b5d3eb..e795ecb9fba7b3c48a5f7732ce96719b28d32c16 100644 (file)
@@ -12,6 +12,8 @@ testing and risk-minimization. Any bug may cost users real money. That being
 said, we deeply welcome people contributing for the first time to an open source
 project or pick up Rust while contributing. Don't be shy, you'll learn.
 
+For the project Code of Conduct, see our [website](https://lightningdevkit.org/code_of_conduct).
+
 Communication Channels
 -----------------------
 
@@ -41,7 +43,7 @@ This doesn't mean don't be ambitious with the breadth and depth of your
 contributions but rather understand the project culture before investing an
 asymmetric number of hours on development compared to your merged work.
 
-Browsing through the [meeting minutes](https://github.com/lightningdevkit/rust-lightning/wiki/Meetings)
+Browsing through the [meeting minutes](https://github.com/lightningdevkit/rust-lightning/wiki/Meeting-Notes)
 is a good first step. You will learn who is working on what, how releases are
 drafted, what are the pending tasks to deliver, where you can contribute review
 bandwidth, etc.
index b0b6910ae2f035a1eedc3f956ba9e1b9ca5b8cb0..5daebb3506681503e197ba92656eb1ddd4eb4c06 100644 (file)
@@ -18,7 +18,7 @@ libfuzzer_fuzz = ["libfuzzer-sys"]
 stdin_fuzz = []
 
 [dependencies]
-lightning = { path = "../lightning", features = ["regex", "hashbrown"] }
+lightning = { path = "../lightning", features = ["regex", "hashbrown", "_test_utils"] }
 lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
 bitcoin = { version = "0.29.0", features = ["secp-lowmemory"] }
 hex = "0.3"
index 95e65695eb868c798aba81b1d3684ba870154521..fa29540f96b35cae0ad5e43e1b8ef485d620520b 100755 (executable)
@@ -14,6 +14,7 @@ GEN_TEST peer_crypt
 GEN_TEST process_network_graph
 GEN_TEST router
 GEN_TEST zbase32
+GEN_TEST indexedmap
 
 GEN_TEST msg_accept_channel msg_targets::
 GEN_TEST msg_announcement_signatures msg_targets::
diff --git a/fuzz/src/bin/indexedmap_target.rs b/fuzz/src/bin/indexedmap_target.rs
new file mode 100644 (file)
index 0000000..238566d
--- /dev/null
@@ -0,0 +1,113 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This file is auto-generated by gen_target.sh based on target_template.txt
+// To modify it, modify target_template.txt and run gen_target.sh instead.
+
+#![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+
+#[cfg(not(fuzzing))]
+compile_error!("Fuzz targets need cfg=fuzzing");
+
+extern crate lightning_fuzz;
+use lightning_fuzz::indexedmap::*;
+
+#[cfg(feature = "afl")]
+#[macro_use] extern crate afl;
+#[cfg(feature = "afl")]
+fn main() {
+       fuzz!(|data| {
+               indexedmap_run(data.as_ptr(), data.len());
+       });
+}
+
+#[cfg(feature = "honggfuzz")]
+#[macro_use] extern crate honggfuzz;
+#[cfg(feature = "honggfuzz")]
+fn main() {
+       loop {
+               fuzz!(|data| {
+                       indexedmap_run(data.as_ptr(), data.len());
+               });
+       }
+}
+
+#[cfg(feature = "libfuzzer_fuzz")]
+#[macro_use] extern crate libfuzzer_sys;
+#[cfg(feature = "libfuzzer_fuzz")]
+fuzz_target!(|data: &[u8]| {
+       indexedmap_run(data.as_ptr(), data.len());
+});
+
+#[cfg(feature = "stdin_fuzz")]
+fn main() {
+       use std::io::Read;
+
+       let mut data = Vec::with_capacity(8192);
+       std::io::stdin().read_to_end(&mut data).unwrap();
+       indexedmap_run(data.as_ptr(), data.len());
+}
+
+#[test]
+fn run_test_cases() {
+       use std::fs;
+       use std::io::Read;
+       use lightning_fuzz::utils::test_logger::StringBuffer;
+
+       use std::sync::{atomic, Arc};
+       {
+               let data: Vec<u8> = vec![0];
+               indexedmap_run(data.as_ptr(), data.len());
+       }
+       let mut threads = Vec::new();
+       let threads_running = Arc::new(atomic::AtomicUsize::new(0));
+       if let Ok(tests) = fs::read_dir("test_cases/indexedmap") {
+               for test in tests {
+                       let mut data: Vec<u8> = Vec::new();
+                       let path = test.unwrap().path();
+                       fs::File::open(&path).unwrap().read_to_end(&mut data).unwrap();
+                       threads_running.fetch_add(1, atomic::Ordering::AcqRel);
+
+                       let thread_count_ref = Arc::clone(&threads_running);
+                       let main_thread_ref = std::thread::current();
+                       threads.push((path.file_name().unwrap().to_str().unwrap().to_string(),
+                               std::thread::spawn(move || {
+                                       let string_logger = StringBuffer::new();
+
+                                       let panic_logger = string_logger.clone();
+                                       let res = if ::std::panic::catch_unwind(move || {
+                                               indexedmap_test(&data, panic_logger);
+                                       }).is_err() {
+                                               Some(string_logger.into_string())
+                                       } else { None };
+                                       thread_count_ref.fetch_sub(1, atomic::Ordering::AcqRel);
+                                       main_thread_ref.unpark();
+                                       res
+                               })
+                       ));
+                       while threads_running.load(atomic::Ordering::Acquire) > 32 {
+                               std::thread::park();
+                       }
+               }
+       }
+       let mut failed_outputs = Vec::new();
+       for (test, thread) in threads.drain(..) {
+               if let Some(output) = thread.join().unwrap() {
+                       println!("\nOutput of {}:\n{}\n", test, output);
+                       failed_outputs.push(test);
+               }
+       }
+       if !failed_outputs.is_empty() {
+               println!("Test cases which failed: ");
+               for case in failed_outputs {
+                       println!("{}", case);
+               }
+               panic!();
+       }
+}
diff --git a/fuzz/src/bin/msg_channel_details_target.rs b/fuzz/src/bin/msg_channel_details_target.rs
new file mode 100644 (file)
index 0000000..cb5021a
--- /dev/null
@@ -0,0 +1,113 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This file is auto-generated by gen_target.sh based on target_template.txt
+// To modify it, modify target_template.txt and run gen_target.sh instead.
+
+#![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+
+#[cfg(not(fuzzing))]
+compile_error!("Fuzz targets need cfg=fuzzing");
+
+extern crate lightning_fuzz;
+use lightning_fuzz::msg_targets::msg_channel_details::*;
+
+#[cfg(feature = "afl")]
+#[macro_use] extern crate afl;
+#[cfg(feature = "afl")]
+fn main() {
+       fuzz!(|data| {
+               msg_channel_details_run(data.as_ptr(), data.len());
+       });
+}
+
+#[cfg(feature = "honggfuzz")]
+#[macro_use] extern crate honggfuzz;
+#[cfg(feature = "honggfuzz")]
+fn main() {
+       loop {
+               fuzz!(|data| {
+                       msg_channel_details_run(data.as_ptr(), data.len());
+               });
+       }
+}
+
+#[cfg(feature = "libfuzzer_fuzz")]
+#[macro_use] extern crate libfuzzer_sys;
+#[cfg(feature = "libfuzzer_fuzz")]
+fuzz_target!(|data: &[u8]| {
+       msg_channel_details_run(data.as_ptr(), data.len());
+});
+
+#[cfg(feature = "stdin_fuzz")]
+fn main() {
+       use std::io::Read;
+
+       let mut data = Vec::with_capacity(8192);
+       std::io::stdin().read_to_end(&mut data).unwrap();
+       msg_channel_details_run(data.as_ptr(), data.len());
+}
+
+#[test]
+fn run_test_cases() {
+       use std::fs;
+       use std::io::Read;
+       use lightning_fuzz::utils::test_logger::StringBuffer;
+
+       use std::sync::{atomic, Arc};
+       {
+               let data: Vec<u8> = vec![0];
+               msg_channel_details_run(data.as_ptr(), data.len());
+       }
+       let mut threads = Vec::new();
+       let threads_running = Arc::new(atomic::AtomicUsize::new(0));
+       if let Ok(tests) = fs::read_dir("test_cases/msg_channel_details") {
+               for test in tests {
+                       let mut data: Vec<u8> = Vec::new();
+                       let path = test.unwrap().path();
+                       fs::File::open(&path).unwrap().read_to_end(&mut data).unwrap();
+                       threads_running.fetch_add(1, atomic::Ordering::AcqRel);
+
+                       let thread_count_ref = Arc::clone(&threads_running);
+                       let main_thread_ref = std::thread::current();
+                       threads.push((path.file_name().unwrap().to_str().unwrap().to_string(),
+                               std::thread::spawn(move || {
+                                       let string_logger = StringBuffer::new();
+
+                                       let panic_logger = string_logger.clone();
+                                       let res = if ::std::panic::catch_unwind(move || {
+                                               msg_channel_details_test(&data, panic_logger);
+                                       }).is_err() {
+                                               Some(string_logger.into_string())
+                                       } else { None };
+                                       thread_count_ref.fetch_sub(1, atomic::Ordering::AcqRel);
+                                       main_thread_ref.unpark();
+                                       res
+                               })
+                       ));
+                       while threads_running.load(atomic::Ordering::Acquire) > 32 {
+                               std::thread::park();
+                       }
+               }
+       }
+       let mut failed_outputs = Vec::new();
+       for (test, thread) in threads.drain(..) {
+               if let Some(output) = thread.join().unwrap() {
+                       println!("\nOutput of {}:\n{}\n", test, output);
+                       failed_outputs.push(test);
+               }
+       }
+       if !failed_outputs.is_empty() {
+               println!("Test cases which failed: ");
+               for case in failed_outputs {
+                       println!("{}", case);
+               }
+               panic!();
+       }
+}
index 3c174f3093f2e20da4ec78f71558367af5b715f1..0caee0801aa1d747ec6f564a2cc86f9658172f78 100644 (file)
@@ -29,6 +29,7 @@ use bitcoin::network::constants::Network;
 
 use bitcoin::hashes::Hash as TraitImport;
 use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::{BlockHash, WPubkeyHash};
 
 use lightning::chain;
@@ -54,10 +55,9 @@ use lightning::routing::router::{InFlightHtlcs, Route, RouteHop, RouteParameters
 use crate::utils::test_logger::{self, Output};
 use crate::utils::test_persister::TestPersister;
 
-use bitcoin::secp256k1::{PublicKey, SecretKey, Scalar};
+use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
 use bitcoin::secp256k1::ecdh::SharedSecret;
-use bitcoin::secp256k1::ecdsa::RecoverableSignature;
-use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
 
 use std::mem;
 use std::cmp::{self, Ordering};
@@ -174,7 +174,7 @@ impl chain::Watch<EnforcingSigner> for TestChainMonitor {
 }
 
 struct KeyProvider {
-       node_id: u8,
+       node_secret: SecretKey,
        rand_bytes_id: atomic::AtomicU32,
        enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
 }
@@ -182,37 +182,45 @@ struct KeyProvider {
 impl EntropySource for KeyProvider {
        fn get_secure_random_bytes(&self) -> [u8; 32] {
                let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
-               let mut res = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, self.node_id];
+               let mut res = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, self.node_secret[31]];
                res[30-4..30].copy_from_slice(&id.to_le_bytes());
                res
        }
 }
 
 impl NodeSigner for KeyProvider {
-       fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
-               Ok(SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id]).unwrap())
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
-               let secp_ctx = Secp256k1::signing_only();
-               Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+               let node_secret = match recipient {
+                       Recipient::Node => Ok(&self.node_secret),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret))
        }
 
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
-               let mut node_secret = self.get_node_secret(recipient)?;
+               let mut node_secret = match recipient {
+                       Recipient::Node => Ok(self.node_secret.clone()),
+                       Recipient::PhantomNode => Err(())
+               }?;
                if let Some(tweak) = tweak {
-                       node_secret = node_secret.mul_tweak(tweak).unwrap();
+                       node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
                }
                Ok(SharedSecret::new(other_key, &node_secret))
        }
 
        fn get_inbound_payment_key_material(&self) -> KeyMaterial {
-               KeyMaterial([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id])
+               KeyMaterial([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_secret[31]])
        }
 
        fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
+
+       fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
+               let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
+               let secp_ctx = Secp256k1::signing_only();
+               Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
+       }
 }
 
 impl SignerProvider for KeyProvider {
@@ -228,13 +236,12 @@ impl SignerProvider for KeyProvider {
                let id = channel_keys_id[0];
                let keys = InMemorySigner::new(
                        &secp_ctx,
-                       self.get_node_secret(Recipient::Node).unwrap(),
-                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, self.node_id]).unwrap(),
-                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, self.node_id]).unwrap(),
-                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, self.node_id]).unwrap(),
-                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(),
-                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(),
-                       [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id],
+                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, self.node_secret[31]]).unwrap(),
+                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, self.node_secret[31]]).unwrap(),
+                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, self.node_secret[31]]).unwrap(),
+                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_secret[31]]).unwrap(),
+                       SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_secret[31]]).unwrap(),
+                       [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_secret[31]],
                        channel_value_satoshis,
                        channel_keys_id,
                );
@@ -245,7 +252,7 @@ impl SignerProvider for KeyProvider {
        fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
                let mut reader = std::io::Cursor::new(buffer);
 
-               let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?;
+               let inner: InMemorySigner = Readable::read(&mut reader)?;
                let state = self.make_enforcement_state_cell(inner.commitment_seed);
 
                Ok(EnforcingSigner {
@@ -257,14 +264,14 @@ impl SignerProvider for KeyProvider {
 
        fn get_destination_script(&self) -> Script {
                let secp_ctx = Secp256k1::signing_only();
-               let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_id]).unwrap();
+               let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_secret[31]]).unwrap();
                let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
                Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
        }
 
        fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
                let secp_ctx = Secp256k1::signing_only();
-               let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap();
+               let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_secret[31]]).unwrap();
                let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
                ShutdownScript::new_p2wpkh(&pubkey_hash)
        }
@@ -333,7 +340,7 @@ fn get_payment_secret_hash(dest: &ChanMan, payment_id: &mut u8) -> Option<(Payme
        let mut payment_hash;
        for _ in 0..256 {
                payment_hash = PaymentHash(Sha256::hash(&[*payment_id; 1]).into_inner());
-               if let Ok(payment_secret) = dest.create_inbound_payment_for_hash(payment_hash, None, 3600) {
+               if let Ok(payment_secret) = dest.create_inbound_payment_for_hash(payment_hash, None, 3600, None) {
                        return Some((payment_secret, payment_hash));
                }
                *payment_id = payment_id.wrapping_add(1);
@@ -402,7 +409,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
        macro_rules! make_node {
                ($node_id: expr, $fee_estimator: expr) => { {
                        let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
-                       let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU32::new(0), enforcement_states: Mutex::new(HashMap::new()) });
+                       let node_secret = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, $node_id]).unwrap();
+                       let keys_manager = Arc::new(KeyProvider { node_secret, rand_bytes_id: atomic::AtomicU32::new(0), enforcement_states: Mutex::new(HashMap::new()) });
                        let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(),
                                Arc::new(TestPersister {
                                        update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed)
index 6d952b42d3cd4bc324e510e7b18546258e1fb861..fb2740c1de9c26acadb2f0e30f1b04f27cd85a48 100644 (file)
@@ -26,6 +26,7 @@ use bitcoin::network::constants::Network;
 use bitcoin::hashes::Hash as TraitImport;
 use bitcoin::hashes::HashEngine as TraitImportEngine;
 use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
 
 use lightning::chain;
@@ -47,15 +48,14 @@ use lightning::util::errors::APIError;
 use lightning::util::events::Event;
 use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
 use lightning::util::logger::Logger;
-use lightning::util::ser::ReadableArgs;
+use lightning::util::ser::{Readable, Writeable};
 
 use crate::utils::test_logger;
 use crate::utils::test_persister::TestPersister;
 
-use bitcoin::secp256k1::{PublicKey, SecretKey, Scalar};
+use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
 use bitcoin::secp256k1::ecdh::SharedSecret;
-use bitcoin::secp256k1::ecdsa::RecoverableSignature;
-use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
 
 use std::cell::RefCell;
 use hashbrown::{HashMap, hash_map};
@@ -183,7 +183,7 @@ impl<'a> std::hash::Hash for Peer<'a> {
 type ChannelMan<'a> = ChannelManager<
        Arc<chainmonitor::ChainMonitor<EnforcingSigner, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<TestPersister>>>,
        Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<KeyProvider>, Arc<KeyProvider>, Arc<FuzzEstimator>, &'a FuzzRouter, Arc<dyn Logger>>;
-type PeerMan<'a> = PeerManager<Peer<'a>, Arc<ChannelMan<'a>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<dyn Logger>>>, Arc<dyn chain::Access>, Arc<dyn Logger>>>, IgnoringMessageHandler, Arc<dyn Logger>, IgnoringMessageHandler>;
+type PeerMan<'a> = PeerManager<Peer<'a>, Arc<ChannelMan<'a>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<dyn Logger>>>, Arc<dyn chain::Access>, Arc<dyn Logger>>>, IgnoringMessageHandler, Arc<dyn Logger>, IgnoringMessageHandler, Arc<KeyProvider>>;
 
 struct MoneyLossDetector<'a> {
        manager: Arc<ChannelMan<'a>>,
@@ -293,19 +293,21 @@ impl EntropySource for KeyProvider {
 }
 
 impl NodeSigner for KeyProvider {
-       fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
-               Ok(self.node_secret.clone())
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
-               let secp_ctx = Secp256k1::signing_only();
-               Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+               let node_secret = match recipient {
+                       Recipient::Node => Ok(&self.node_secret),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret))
        }
 
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
-               let mut node_secret = self.get_node_secret(recipient)?;
+               let mut node_secret = match recipient {
+                       Recipient::Node => Ok(self.node_secret.clone()),
+                       Recipient::PhantomNode => Err(())
+               }?;
                if let Some(tweak) = tweak {
-                       node_secret = node_secret.mul_tweak(tweak).unwrap();
+                       node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
                }
                Ok(SharedSecret::new(other_key, &node_secret))
        }
@@ -317,6 +319,12 @@ impl NodeSigner for KeyProvider {
        fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
+
+       fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
+               let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
+               let secp_ctx = Secp256k1::signing_only();
+               Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
+       }
 }
 
 impl SignerProvider for KeyProvider {
@@ -335,7 +343,6 @@ impl SignerProvider for KeyProvider {
                EnforcingSigner::new_with_revoked(if inbound {
                        InMemorySigner::new(
                                &secp_ctx,
-                               self.node_secret.clone(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ctr]).unwrap(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ctr]).unwrap(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ctr]).unwrap(),
@@ -348,7 +355,6 @@ impl SignerProvider for KeyProvider {
                } else {
                        InMemorySigner::new(
                                &secp_ctx,
-                               self.node_secret.clone(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, ctr]).unwrap(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, ctr]).unwrap(),
                                SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, ctr]).unwrap(),
@@ -362,7 +368,7 @@ impl SignerProvider for KeyProvider {
        }
 
        fn read_chan_signer(&self, mut data: &[u8]) -> Result<EnforcingSigner, DecodeError> {
-               let inner: InMemorySigner = ReadableArgs::read(&mut data, self.node_secret.clone())?;
+               let inner: InMemorySigner = Readable::read(&mut data)?;
                let state = Arc::new(Mutex::new(EnforcementState::new()));
 
                Ok(EnforcingSigner::new_with_revoked(
@@ -446,7 +452,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
        // keys subsequently generated in this test. Rather than regenerating all the messages manually,
        // it's easier to just increment the counter here so the keys don't change.
        keys_manager.counter.fetch_sub(3, Ordering::AcqRel);
-       let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret(Recipient::Node).unwrap());
+       let our_id = &keys_manager.get_node_id(Recipient::Node).unwrap();
        let network_graph = Arc::new(NetworkGraph::new(genesis_block(network).block_hash(), Arc::clone(&logger)));
        let gossip_sync = Arc::new(P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger)));
        let scorer = FixedPenaltyScorer::with_penalty(0);
@@ -456,7 +462,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                chan_handler: channelmanager.clone(),
                route_handler: gossip_sync.clone(),
                onion_message_handler: IgnoringMessageHandler {},
-       }, our_network_key, 0, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{}));
+       }, 0, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{}, keys_manager.clone()));
 
        let mut should_forward = false;
        let mut payments_received: Vec<PaymentHash> = Vec::new();
@@ -599,7 +605,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                let payment_hash = PaymentHash(Sha256::from_engine(sha).into_inner());
                                // Note that this may fail - our hashes may collide and we'll end up trying to
                                // double-register the same payment_hash.
-                               let _ = channelmanager.create_inbound_payment_for_hash(payment_hash, None, 1);
+                               let _ = channelmanager.create_inbound_payment_for_hash(payment_hash, None, 1, None);
                        },
                        9 => {
                                for payment in payments_received.drain(..) {
diff --git a/fuzz/src/indexedmap.rs b/fuzz/src/indexedmap.rs
new file mode 100644 (file)
index 0000000..795d617
--- /dev/null
@@ -0,0 +1,137 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use lightning::util::indexed_map::{IndexedMap, self};
+use std::collections::{BTreeMap, btree_map};
+use hashbrown::HashSet;
+
+use crate::utils::test_logger;
+
+fn check_eq(btree: &BTreeMap<u8, u8>, indexed: &IndexedMap<u8, u8>) {
+       assert_eq!(btree.len(), indexed.len());
+       assert_eq!(btree.is_empty(), indexed.is_empty());
+
+       let mut btree_clone = btree.clone();
+       assert!(btree_clone == *btree);
+       let mut indexed_clone = indexed.clone();
+       assert!(indexed_clone == *indexed);
+
+       for k in 0..=255 {
+               assert_eq!(btree.contains_key(&k), indexed.contains_key(&k));
+               assert_eq!(btree.get(&k), indexed.get(&k));
+
+               let btree_entry = btree_clone.entry(k);
+               let indexed_entry = indexed_clone.entry(k);
+               match btree_entry {
+                       btree_map::Entry::Occupied(mut bo) => {
+                               if let indexed_map::Entry::Occupied(mut io) = indexed_entry {
+                                       assert_eq!(bo.get(), io.get());
+                                       assert_eq!(bo.get_mut(), io.get_mut());
+                               } else { panic!(); }
+                       },
+                       btree_map::Entry::Vacant(_) => {
+                               if let indexed_map::Entry::Vacant(_) = indexed_entry {
+                               } else { panic!(); }
+                       }
+               }
+       }
+
+       const STRIDE: u8 = 16;
+       for k in 0..=255/STRIDE {
+               let lower_bound = k * STRIDE;
+               let upper_bound = lower_bound + (STRIDE - 1);
+               let mut btree_iter = btree.range(lower_bound..=upper_bound);
+               let mut indexed_iter = indexed.range(lower_bound..=upper_bound);
+               loop {
+                       let b_v = btree_iter.next();
+                       let i_v = indexed_iter.next();
+                       assert_eq!(b_v, i_v);
+                       if b_v.is_none() { break; }
+               }
+       }
+
+       let mut key_set = HashSet::with_capacity(256);
+       for k in indexed.unordered_keys() {
+               assert!(key_set.insert(*k));
+               assert!(btree.contains_key(k));
+       }
+       assert_eq!(key_set.len(), btree.len());
+
+       key_set.clear();
+       for (k, v) in indexed.unordered_iter() {
+               assert!(key_set.insert(*k));
+               assert_eq!(btree.get(k).unwrap(), v);
+       }
+       assert_eq!(key_set.len(), btree.len());
+
+       key_set.clear();
+       for (k, v) in indexed_clone.unordered_iter_mut() {
+               assert!(key_set.insert(*k));
+               assert_eq!(btree.get(k).unwrap(), v);
+       }
+       assert_eq!(key_set.len(), btree.len());
+}
+
+#[inline]
+pub fn do_test(data: &[u8]) {
+       if data.len() % 2 != 0 { return; }
+       let mut btree = BTreeMap::new();
+       let mut indexed = IndexedMap::new();
+
+       // Read in k-v pairs from the input and insert them into the maps then check that the maps are
+       // equivalent in every way we can read them.
+       for tuple in data.windows(2) {
+               let prev_value_b = btree.insert(tuple[0], tuple[1]);
+               let prev_value_i = indexed.insert(tuple[0], tuple[1]);
+               assert_eq!(prev_value_b, prev_value_i);
+       }
+       check_eq(&btree, &indexed);
+
+       // Now, modify the maps in all the ways we have to do so, checking that the maps remain
+       // equivalent as we go.
+       for (k, v) in indexed.unordered_iter_mut() {
+               *v = *k;
+               *btree.get_mut(k).unwrap() = *k;
+       }
+       check_eq(&btree, &indexed);
+
+       for k in 0..=255 {
+               match btree.entry(k) {
+                       btree_map::Entry::Occupied(mut bo) => {
+                               if let indexed_map::Entry::Occupied(mut io) = indexed.entry(k) {
+                                       if k < 64 {
+                                               *io.get_mut() ^= 0xff;
+                                               *bo.get_mut() ^= 0xff;
+                                       } else if k < 128 {
+                                               *io.into_mut() ^= 0xff;
+                                               *bo.get_mut() ^= 0xff;
+                                       } else {
+                                               assert_eq!(bo.remove_entry(), io.remove_entry());
+                                       }
+                               } else { panic!(); }
+                       },
+                       btree_map::Entry::Vacant(bv) => {
+                               if let indexed_map::Entry::Vacant(iv) = indexed.entry(k) {
+                                       bv.insert(k);
+                                       iv.insert(k);
+                               } else { panic!(); }
+                       },
+               }
+       }
+       check_eq(&btree, &indexed);
+}
+
+pub fn indexedmap_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
+       do_test(data);
+}
+
+#[no_mangle]
+pub extern "C" fn indexedmap_run(data: *const u8, datalen: usize) {
+       do_test(unsafe { std::slice::from_raw_parts(data, datalen) });
+}
index 2238a9702a9563a78e59ef8010f6e816f282b4b1..462307d55b42a6e977276065825cc325c8c3c807 100644 (file)
@@ -17,6 +17,7 @@ pub mod utils;
 pub mod chanmon_deser;
 pub mod chanmon_consistency;
 pub mod full_stack;
+pub mod indexedmap;
 pub mod onion_message;
 pub mod peer_crypt;
 pub mod process_network_graph;
index a86734d4575a6fb7f4c65ea74a2844e9b3d60bca..9bbf8b9cdffa5010e6463ae96d5de071b19d8285 100644 (file)
@@ -100,17 +100,19 @@ impl EntropySource for KeyProvider {
 }
 
 impl NodeSigner for KeyProvider {
-       fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
-               Ok(self.node_secret.clone())
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
-               let secp_ctx = Secp256k1::signing_only();
-               Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+               let node_secret = match recipient {
+                       Recipient::Node => Ok(&self.node_secret),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret))
        }
 
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
-               let mut node_secret = self.get_node_secret(recipient)?;
+               let mut node_secret = match recipient {
+                       Recipient::Node => Ok(self.node_secret.clone()),
+                       Recipient::PhantomNode => Err(())
+               }?;
                if let Some(tweak) = tweak {
                        node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
                }
@@ -122,6 +124,10 @@ impl NodeSigner for KeyProvider {
        fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
+
+       fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
+               unreachable!()
+       }
 }
 
 impl SignerProvider for KeyProvider {
index 15e9486a35e1c44e2a085db4bc862219bfb1b277..f6df392fcef5407623b6c0f0cfcf9b8690cdbc75 100644 (file)
@@ -8,6 +8,7 @@
 // licenses.
 
 use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor;
+use lightning::util::test_utils::TestNodeSigner;
 
 use bitcoin::secp256k1::{Secp256k1, PublicKey, SecretKey};
 
@@ -41,6 +42,7 @@ pub fn do_test(data: &[u8]) {
                Ok(key) => key,
                Err(_) => return,
        };
+       let node_signer = TestNodeSigner::new(our_network_key);
        let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) {
                Ok(key) => key,
                Err(_) => return,
@@ -53,15 +55,15 @@ pub fn do_test(data: &[u8]) {
                };
                let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key);
                crypter.get_act_one(&secp_ctx);
-               match crypter.process_act_two(get_slice!(50), &our_network_key, &secp_ctx) {
+               match crypter.process_act_two(get_slice!(50), &&node_signer) {
                        Ok(_) => {},
                        Err(_) => return,
                }
                assert!(crypter.is_ready_for_encryption());
                crypter
        } else {
-               let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key, &secp_ctx);
-               match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key, &secp_ctx) {
+               let mut crypter = PeerChannelEncryptor::new_inbound(&&node_signer);
+               match crypter.process_act_one_with_keys(get_slice!(50), &&node_signer, ephemeral_key, &secp_ctx) {
                        Ok(_) => {},
                        Err(_) => return,
                }
index cff3f9bdbb52dd87e5f2cfbd68525768e109963e..5bfee07dafbb149e4db2a8262a22209355ec11ba 100644 (file)
@@ -7,6 +7,7 @@ void peer_crypt_run(const unsigned char* data, size_t data_len);
 void process_network_graph_run(const unsigned char* data, size_t data_len);
 void router_run(const unsigned char* data, size_t data_len);
 void zbase32_run(const unsigned char* data, size_t data_len);
+void indexedmap_run(const unsigned char* data, size_t data_len);
 void msg_accept_channel_run(const unsigned char* data, size_t data_len);
 void msg_announcement_signatures_run(const unsigned char* data, size_t data_len);
 void msg_channel_reestablish_run(const unsigned char* data, size_t data_len);
index 4759c272dc758e2a4bbdaf097fcdc895a2fa01f2..4bd5e463f93d5a877d157e9d5d668e30f7ca9808 100644 (file)
@@ -385,7 +385,7 @@ pub async fn process_events_async<
        PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
        RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
        UMH: 'static + Deref + Send + Sync,
-       PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, OMH, L, UMH>> + Send + Sync,
+       PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, OMH, L, UMH, NS>> + Send + Sync,
        S: 'static + Deref<Target = SC> + Send + Sync,
        SC: WriteableScore<'a>,
        SleepFuture: core::future::Future<Output = bool> + core::marker::Unpin,
@@ -514,7 +514,7 @@ impl BackgroundProcessor {
                PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
                RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
                UMH: 'static + Deref + Send + Sync,
-               PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, OMH, L, UMH>> + Send + Sync,
+               PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, OMH, L, UMH, NS>> + Send + Sync,
                S: 'static + Deref<Target = SC> + Send + Sync,
                SC: WriteableScore<'a>,
        >(
@@ -615,7 +615,7 @@ mod tests {
        use bitcoin::network::constants::Network;
        use lightning::chain::{BestBlock, Confirm, chainmonitor};
        use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
-       use lightning::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, KeysManager, NodeSigner};
+       use lightning::chain::keysinterface::{InMemorySigner, EntropySource, KeysManager};
        use lightning::chain::transaction::OutPoint;
        use lightning::get_event_msg;
        use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
@@ -663,7 +663,7 @@ mod tests {
                node: Arc<SimpleArcChannelManager<ChainMonitor, test_utils::TestBroadcaster, test_utils::TestFeeEstimator, test_utils::TestLogger>>,
                p2p_gossip_sync: PGS,
                rapid_gossip_sync: RGS,
-               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, IgnoringMessageHandler, Arc<test_utils::TestLogger>, IgnoringMessageHandler>>,
+               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, IgnoringMessageHandler, Arc<test_utils::TestLogger>, IgnoringMessageHandler, Arc<KeysManager>>>,
                chain_monitor: Arc<ChainMonitor>,
                persister: Arc<FilesystemPersister>,
                tx_broadcaster: Arc<test_utils::TestBroadcaster>,
@@ -786,7 +786,7 @@ mod tests {
                        let p2p_gossip_sync = Arc::new(P2PGossipSync::new(network_graph.clone(), Some(chain_source.clone()), logger.clone()));
                        let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone()));
                        let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: IgnoringMessageHandler{}};
-                       let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), 0, &seed, logger.clone(), IgnoringMessageHandler{}));
+                       let peer_manager = Arc::new(PeerManager::new(msg_handler, 0, &seed, logger.clone(), IgnoringMessageHandler{}, keys_manager.clone()));
                        let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, persister, tx_broadcaster, network_graph, logger, best_block, scorer };
                        nodes.push(node);
                }
index 8b185ff3babcb4e31f76bfb47260cf088c9ee11c..c605f5ef3a2ef4b3201cec0e7a979b1bda7b9ecc 100644 (file)
@@ -27,4 +27,5 @@ serde_json = { version = "1.0", optional = true }
 chunked_transfer = { version = "1.4", optional = true }
 
 [dev-dependencies]
+lightning = { version = "0.0.113", path = "../lightning", features = ["_test_utils"] }
 tokio = { version = "~1.14", features = [ "macros", "rt" ] }
index 0759698b1603476b890198ebe14b99ce8948016c..92c1cb5c28f5385b5eb2f37c2cbbac62b58ac398 100644 (file)
@@ -22,7 +22,7 @@ use secp256k1;
 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
 use secp256k1::PublicKey;
 
-use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
+use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
        SemanticError, PrivateRoute, ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice,
        constants, SignedRawInvoice, RawDataPart, InvoiceFeatures};
 
@@ -451,8 +451,8 @@ impl FromBase32 for TaggedField {
                                Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)),
                        constants::TAG_EXPIRY_TIME =>
                                Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)),
-                       constants::TAG_MIN_FINAL_CLTV_EXPIRY =>
-                               Ok(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry::from_base32(field_data)?)),
+                       constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA =>
+                               Ok(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta::from_base32(field_data)?)),
                        constants::TAG_FALLBACK =>
                                Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)),
                        constants::TAG_PRIVATE_ROUTE =>
@@ -523,13 +523,13 @@ impl FromBase32 for ExpiryTime {
        }
 }
 
-impl FromBase32 for MinFinalCltvExpiry {
+impl FromBase32 for MinFinalCltvExpiryDelta {
        type Err = ParseError;
 
-       fn from_base32(field_data: &[u5]) -> Result<MinFinalCltvExpiry, ParseError> {
+       fn from_base32(field_data: &[u5]) -> Result<MinFinalCltvExpiryDelta, ParseError> {
                let expiry = parse_int_be::<u64, u5>(field_data, 32);
                if let Some(expiry) = expiry {
-                       Ok(MinFinalCltvExpiry(expiry))
+                       Ok(MinFinalCltvExpiryDelta(expiry))
                } else {
                        Err(ParseError::IntegerOverflowError)
                }
@@ -840,14 +840,14 @@ mod test {
        }
 
        #[test]
-       fn test_parse_min_final_cltv_expiry() {
-               use crate::MinFinalCltvExpiry;
+       fn test_parse_min_final_cltv_expiry_delta() {
+               use crate::MinFinalCltvExpiryDelta;
                use bech32::FromBase32;
 
                let input = from_bech32("pr".as_bytes());
-               let expected = Ok(MinFinalCltvExpiry(35));
+               let expected = Ok(MinFinalCltvExpiryDelta(35));
 
-               assert_eq!(MinFinalCltvExpiry::from_base32(&input), expected);
+               assert_eq!(MinFinalCltvExpiryDelta::from_base32(&input), expected);
        }
 
        #[test]
index c01dfa47ba0b086f8de39691de88df06ce3f2e91..17b6e2de2b6efe8582f9f78823289f306c9f4991 100644 (file)
@@ -154,11 +154,11 @@ pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
 /// Default minimum final CLTV expiry as defined by [BOLT 11].
 ///
 /// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
-/// provided in [`MIN_FINAL_CLTV_EXPIRY`].
+/// provided in [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
 ///
 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
-/// [`MIN_FINAL_CLTV_EXPIRY`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY
-pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
+/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
+pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
 
 /// Builder for `Invoice`s. It's the most convenient and advised way to use this library. It ensures
 /// that only a semantically and syntactically correct Invoice can be built using it.
@@ -199,7 +199,7 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
 ///    .payment_hash(payment_hash)
 ///    .payment_secret(payment_secret)
 ///    .current_timestamp()
-///    .min_final_cltv_expiry(144)
+///    .min_final_cltv_expiry_delta(144)
 ///    .build_signed(|hash| {
 ///            Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
 ///    })
@@ -410,7 +410,7 @@ pub enum TaggedField {
        PayeePubKey(PayeePubKey),
        DescriptionHash(Sha256),
        ExpiryTime(ExpiryTime),
-       MinFinalCltvExpiry(MinFinalCltvExpiry),
+       MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta),
        Fallback(Fallback),
        PrivateRoute(PrivateRoute),
        PaymentSecret(PaymentSecret),
@@ -438,9 +438,9 @@ pub struct PayeePubKey(pub PublicKey);
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
 pub struct ExpiryTime(Duration);
 
-/// `min_final_cltv_expiry` to use for the last HTLC in the route
+/// `min_final_cltv_expiry_delta` to use for the last HTLC in the route
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
-pub struct MinFinalCltvExpiry(pub u64);
+pub struct MinFinalCltvExpiryDelta(pub u64);
 
 // TODO: better types instead onf byte arrays
 /// Fallback address in case no LN payment is possible
@@ -475,7 +475,7 @@ pub mod constants {
        pub const TAG_PAYEE_PUB_KEY: u8 = 19;
        pub const TAG_DESCRIPTION_HASH: u8 = 23;
        pub const TAG_EXPIRY_TIME: u8 = 6;
-       pub const TAG_MIN_FINAL_CLTV_EXPIRY: u8 = 24;
+       pub const TAG_MIN_FINAL_CLTV_EXPIRY_DELTA: u8 = 24;
        pub const TAG_FALLBACK: u8 = 9;
        pub const TAG_PRIVATE_ROUTE: u8 = 3;
        pub const TAG_PAYMENT_SECRET: u8 = 16;
@@ -654,9 +654,9 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
 }
 
 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, tb::False, S> {
-       /// Sets `min_final_cltv_expiry`.
-       pub fn min_final_cltv_expiry(mut self, min_final_cltv_expiry: u64) -> InvoiceBuilder<D, H, T, tb::True, S> {
-               self.tagged_fields.push(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry(min_final_cltv_expiry)));
+       /// Sets `min_final_cltv_expiry_delta`.
+       pub fn min_final_cltv_expiry_delta(mut self, min_final_cltv_expiry_delta: u64) -> InvoiceBuilder<D, H, T, tb::True, S> {
+               self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta(min_final_cltv_expiry_delta)));
                self.set_flags()
        }
 }
@@ -929,8 +929,8 @@ impl RawInvoice {
                find_extract!(self.known_tagged_fields(), TaggedField::ExpiryTime(ref x), x)
        }
 
-       pub fn min_final_cltv_expiry(&self) -> Option<&MinFinalCltvExpiry> {
-               find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiry(ref x), x)
+       pub fn min_final_cltv_expiry_delta(&self) -> Option<&MinFinalCltvExpiryDelta> {
+               find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiryDelta(ref x), x)
        }
 
        pub fn payment_secret(&self) -> Option<&PaymentSecret> {
@@ -1243,12 +1243,12 @@ impl Invoice {
                        .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time
        }
 
-       /// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
-       /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
-       pub fn min_final_cltv_expiry(&self) -> u64 {
-               self.signed_invoice.min_final_cltv_expiry()
+       /// Returns the invoice's `min_final_cltv_expiry_delta` time, if present, otherwise
+       /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA`].
+       pub fn min_final_cltv_expiry_delta(&self) -> u64 {
+               self.signed_invoice.min_final_cltv_expiry_delta()
                        .map(|x| x.0)
-                       .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY)
+                       .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA)
        }
 
        /// Returns a list of all fallback addresses
@@ -1301,7 +1301,7 @@ impl TaggedField {
                        TaggedField::PayeePubKey(_) => constants::TAG_PAYEE_PUB_KEY,
                        TaggedField::DescriptionHash(_) => constants::TAG_DESCRIPTION_HASH,
                        TaggedField::ExpiryTime(_) => constants::TAG_EXPIRY_TIME,
-                       TaggedField::MinFinalCltvExpiry(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY,
+                       TaggedField::MinFinalCltvExpiryDelta(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA,
                        TaggedField::Fallback(_) => constants::TAG_FALLBACK,
                        TaggedField::PrivateRoute(_) => constants::TAG_PRIVATE_ROUTE,
                        TaggedField::PaymentSecret(_) => constants::TAG_PAYMENT_SECRET,
@@ -1448,6 +1448,11 @@ pub enum CreationError {
        ///
        /// [phantom invoices]: crate::utils::create_phantom_invoice
        MissingRouteHints,
+
+       /// The provided `min_final_cltv_expiry_delta` was less than [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
+       ///
+       /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
+       MinFinalCltvExpiryDeltaTooShort,
 }
 
 impl Display for CreationError {
@@ -1458,6 +1463,8 @@ impl Display for CreationError {
                        CreationError::TimestampOutOfBounds => f.write_str("The Unix timestamp of the supplied date is less than zero or greater than 35-bits"),
                        CreationError::InvalidAmount => f.write_str("The supplied millisatoshi amount was greater than the total bitcoin supply"),
                        CreationError::MissingRouteHints => f.write_str("The invoice required route hints and they weren't provided"),
+                       CreationError::MinFinalCltvExpiryDeltaTooShort => f.write_str(
+                               "The supplied final CLTV expiry delta was less than LDK's `MIN_FINAL_CLTV_EXPIRY_DELTA`"),
                }
        }
 }
@@ -1804,7 +1811,7 @@ mod test {
                let builder = InvoiceBuilder::new(Currency::Bitcoin)
                        .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
                        .duration_since_epoch(Duration::from_secs(1234567))
-                       .min_final_cltv_expiry(144);
+                       .min_final_cltv_expiry_delta(144);
 
                let too_long_string = String::from_iter(
                        (0..1024).map(|_| '?')
@@ -1922,7 +1929,7 @@ mod test {
                        .duration_since_epoch(Duration::from_secs(1234567))
                        .payee_pub_key(public_key.clone())
                        .expiry_time(Duration::from_secs(54321))
-                       .min_final_cltv_expiry(144)
+                       .min_final_cltv_expiry_delta(144)
                        .fallback(Fallback::PubKeyHash([0;20]))
                        .private_route(route_1.clone())
                        .private_route(route_2.clone())
@@ -1948,7 +1955,7 @@ mod test {
                );
                assert_eq!(invoice.payee_pub_key(), Some(&public_key));
                assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
-               assert_eq!(invoice.min_final_cltv_expiry(), 144);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), 144);
                assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash([0;20])]);
                assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]);
                assert_eq!(
@@ -1989,7 +1996,7 @@ mod test {
                        .unwrap();
                let invoice = Invoice::from_signed(signed_invoice).unwrap();
 
-               assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA);
                assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
                assert!(!invoice.would_expire(Duration::from_secs(1234568)));
        }
index 82f1149db1fbf5771d043b6582a33e510f8ab5f6..a3517264b4a0bd1e8846f26afbf975f0f77b42eb 100644 (file)
@@ -431,7 +431,7 @@ where
                let route_params = RouteParameters {
                        payment_params,
                        final_value_msat: invoice.amount_milli_satoshis().or(amount_msats).unwrap(),
-                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32,
+                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
                };
 
                let send_payment = |route: &Route| {
@@ -764,7 +764,7 @@ mod tests {
                        .payment_hash(payment_hash)
                        .payment_secret(PaymentSecret([0; 32]))
                        .duration_since_epoch(duration_since_epoch())
-                       .min_final_cltv_expiry(144)
+                       .min_final_cltv_expiry_delta(144)
                        .amount_milli_satoshis(128)
                        .build_signed(|hash| {
                                Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
@@ -790,7 +790,7 @@ mod tests {
                        .payment_hash(payment_hash)
                        .payment_secret(PaymentSecret([0; 32]))
                        .duration_since_epoch(duration_since_epoch())
-                       .min_final_cltv_expiry(144)
+                       .min_final_cltv_expiry_delta(144)
                        .build_signed(|hash| {
                                Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
                        })
@@ -809,7 +809,7 @@ mod tests {
                        .payment_hash(payment_hash)
                        .payment_secret(PaymentSecret([0; 32]))
                        .duration_since_epoch(duration)
-                       .min_final_cltv_expiry(144)
+                       .min_final_cltv_expiry_delta(144)
                        .amount_milli_satoshis(128)
                        .build_signed(|hash| {
                                Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
@@ -1665,7 +1665,7 @@ mod tests {
                        RouteParameters {
                                payment_params,
                                final_value_msat,
-                               final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32,
+                               final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
                        }
                }
        }
@@ -2085,7 +2085,7 @@ mod tests {
 
                assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::Bitcoin,
-                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600).unwrap())
+                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600, None).unwrap())
                        .is_ok());
                let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(htlc_msgs.len(), 2);
@@ -2130,7 +2130,7 @@ mod tests {
 
                assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::Bitcoin,
-                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600).unwrap())
+                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600, None).unwrap())
                        .is_ok());
                let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(htlc_msgs.len(), 2);
@@ -2211,7 +2211,7 @@ mod tests {
 
                assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::Bitcoin,
-                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600).unwrap())
+                       Some(100_010_000), "Invoice".to_string(), duration_since_epoch(), 3600, None).unwrap())
                        .is_ok());
                let htlc_updates = SendEvent::from_node(&nodes[0]);
                check_added_monitors!(nodes[0], 1);
index 0bb1715e728c5ac53f50fb978f32e9105c5faa4d..f5742289118ba1e21382ad899770d9fb028831ce 100644 (file)
@@ -3,7 +3,7 @@ use core::fmt::{Display, Formatter};
 use bech32::{ToBase32, u5, WriteBase32, Base32Len};
 use crate::prelude::*;
 
-use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
+use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
        PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, constants, SignedRawInvoice, RawDataPart};
 
 /// Converts a stream of bytes written to it to base32. On finalization the according padding will
@@ -313,13 +313,13 @@ impl Base32Len for ExpiryTime {
        }
 }
 
-impl ToBase32 for MinFinalCltvExpiry {
+impl ToBase32 for MinFinalCltvExpiryDelta {
        fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
                writer.write(&encode_int_be_base32(self.0))
        }
 }
 
-impl Base32Len for MinFinalCltvExpiry {
+impl Base32Len for MinFinalCltvExpiryDelta {
        fn base32_len(&self) -> usize {
                encoded_int_be_base32_size(self.0)
        }
@@ -434,8 +434,8 @@ impl ToBase32 for TaggedField {
                        TaggedField::ExpiryTime(ref duration) => {
                                write_tagged_field(writer, constants::TAG_EXPIRY_TIME, duration)
                        },
-                       TaggedField::MinFinalCltvExpiry(ref expiry) => {
-                               write_tagged_field(writer, constants::TAG_MIN_FINAL_CLTV_EXPIRY, expiry)
+                       TaggedField::MinFinalCltvExpiryDelta(ref expiry) => {
+                               write_tagged_field(writer, constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA, expiry)
                        },
                        TaggedField::Fallback(ref fallback_address) => {
                                write_tagged_field(writer, constants::TAG_FALLBACK, fallback_address)
index 76d5cf38ce6a65e7c4533ddbcc3b542536e3f8d0..763e3a4f7b0bc301b4411aeacea1795b3ced104c 100644 (file)
@@ -10,8 +10,7 @@ use lightning::chain;
 use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
 use lightning::chain::keysinterface::{Recipient, NodeSigner, SignerProvider, EntropySource};
 use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY};
-#[cfg(feature = "std")]
+use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY_DELTA};
 use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
 use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
 use lightning::routing::gossip::RoutingFees;
@@ -21,7 +20,6 @@ use secp256k1::PublicKey;
 use core::ops::Deref;
 use core::time::Duration;
 
-#[cfg(feature = "std")]
 /// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
 /// See [`PhantomKeysManager`] for more information on phantom node payments.
 ///
@@ -41,6 +39,16 @@ use core::time::Duration;
 ///
 /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
 /// in excess of the current time.
+/// 
+/// 'duration_since_epoch' is the current time since epoch in seconds.
+/// 
+/// ['std::time::SystemTime'] has been removed to allow this function to be used in a 'no_std' environment, 
+/// where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.
+///
+/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to
+/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`] - 3.
+/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block
+/// confirmations during routing.
 ///
 /// Note that the provided `keys_manager`'s `NodeSigner` implementation must support phantom
 /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -51,10 +59,11 @@ use core::time::Duration;
 /// [`ChannelManager::create_inbound_payment`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment
 /// [`ChannelManager::create_inbound_payment_for_hash`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
 /// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
+/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
 pub fn create_phantom_invoice<ES: Deref, NS: Deref, L: Deref>(
        amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: String,
        invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
-       node_signer: NS, logger: L, network: Currency,
+       node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
 ) -> Result<Invoice, SignOrCreationError<()>>
 where
        ES::Target: EntropySource,
@@ -65,11 +74,10 @@ where
        let description = InvoiceDescription::Direct(&description,);
        _create_phantom_invoice::<ES, NS, L>(
                amt_msat, payment_hash, description, invoice_expiry_delta_secs, phantom_route_hints,
-               entropy_source, node_signer, logger, network,
+               entropy_source, node_signer, logger, network, min_final_cltv_expiry_delta, duration_since_epoch,
        )
 }
 
-#[cfg(feature = "std")]
 /// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
 /// See [`PhantomKeysManager`] for more information on phantom node payments.
 ///
@@ -91,6 +99,11 @@ where
 ///
 /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
 /// in excess of the current time.
+/// 
+/// 'duration_since_epoch' is the current time since epoch in seconds.
+/// 
+/// ['std::time::SystemTime'] has been removed to allow this function to be used in a 'no_std' environment, 
+/// where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.
 ///
 /// Note that the provided `keys_manager`'s `NodeSigner` implementation must support phantom
 /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -104,7 +117,7 @@ where
 pub fn create_phantom_invoice_with_description_hash<ES: Deref, NS: Deref, L: Deref>(
        amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, invoice_expiry_delta_secs: u32,
        description_hash: Sha256, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
-       node_signer: NS, logger: L, network: Currency
+       node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
 ) -> Result<Invoice, SignOrCreationError<()>>
 where
        ES::Target: EntropySource,
@@ -114,21 +127,20 @@ where
        _create_phantom_invoice::<ES, NS, L>(
                amt_msat, payment_hash, InvoiceDescription::Hash(&description_hash),
                invoice_expiry_delta_secs, phantom_route_hints, entropy_source, node_signer, logger, network,
+               min_final_cltv_expiry_delta, duration_since_epoch,
        )
 }
 
-#[cfg(feature = "std")]
 fn _create_phantom_invoice<ES: Deref, NS: Deref, L: Deref>(
        amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: InvoiceDescription,
        invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
-       node_signer: NS, logger: L, network: Currency,
+       node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
 ) -> Result<Invoice, SignOrCreationError<()>>
 where
        ES::Target: EntropySource,
        NS::Target: NodeSigner,
        L::Target: Logger,
 {
-       use std::time::{SystemTime, UNIX_EPOCH};
 
        if phantom_route_hints.len() == 0 {
                return Err(SignOrCreationError::CreationError(
@@ -136,6 +148,10 @@ where
                ));
        }
 
+       if min_final_cltv_expiry_delta.is_some() && min_final_cltv_expiry_delta.unwrap().saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA {
+               return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort));
+       }
+
        let invoice = match description {
                InvoiceDescription::Direct(description) => {
                        InvoiceBuilder::new(network).description(description.0.clone())
@@ -151,10 +167,9 @@ where
                        amt_msat,
                        payment_hash,
                        invoice_expiry_delta_secs,
-                       SystemTime::now()
-                               .duration_since(UNIX_EPOCH)
-                               .expect("Time must be > 1970")
+                       duration_since_epoch
                                .as_secs(),
+                       min_final_cltv_expiry_delta,
                )
                .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
                (payment_hash, payment_secret)
@@ -164,10 +179,9 @@ where
                        amt_msat,
                        invoice_expiry_delta_secs,
                        &entropy_source,
-                       SystemTime::now()
-                               .duration_since(UNIX_EPOCH)
-                               .expect("Time must be > 1970")
+                       duration_since_epoch
                                .as_secs(),
+                       min_final_cltv_expiry_delta,
                )
                .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))?
        };
@@ -176,10 +190,12 @@ where
                phantom_route_hints.len(), log_bytes!(payment_hash.0));
 
        let mut invoice = invoice
-               .current_timestamp()
+               .duration_since_epoch(duration_since_epoch)
                .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
                .payment_secret(payment_secret)
-               .min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
+               .min_final_cltv_expiry_delta(
+                       // Add a buffer of 3 to the delta if present, otherwise use LDK's minimum.
+                       min_final_cltv_expiry_delta.map(|x| x.saturating_add(3)).unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA).into())
                .expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
        if let Some(amt) = amt_msat {
                invoice = invoice.amount_milli_satoshis(amt);
@@ -235,9 +251,17 @@ where
 ///
 /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
 /// in excess of the current time.
+///
+/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to
+/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
+/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block
+/// confirmations during routing.
+///
+/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
 pub fn create_invoice_from_channelmanager<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
-       network: Currency, amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32
+       network: Currency, amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32,
+       min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
 where
        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -254,7 +278,7 @@ where
                .expect("for the foreseeable future this shouldn't happen");
        create_invoice_from_channelmanager_and_duration_since_epoch(
                channelmanager, node_signer, logger, network, amt_msat,
-               description, duration, invoice_expiry_delta_secs
+               description, duration, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
        )
 }
 
@@ -268,10 +292,17 @@ where
 ///
 /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
 /// in excess of the current time.
+///
+/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to
+/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
+/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block
+/// confirmations during routing.
+///
+/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
 pub fn create_invoice_from_channelmanager_with_description_hash<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description_hash: Sha256,
-       invoice_expiry_delta_secs: u32
+       invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
 where
        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -291,7 +322,7 @@ where
 
        create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
                channelmanager, node_signer, logger, network, amt_msat,
-               description_hash, duration, invoice_expiry_delta_secs
+               description_hash, duration, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
        )
 }
 
@@ -301,7 +332,7 @@ where
 pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description_hash: Sha256,
-       duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
+       duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
                where
                        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -316,7 +347,7 @@ pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_sin
        _create_invoice_from_channelmanager_and_duration_since_epoch(
                channelmanager, node_signer, logger, network, amt_msat,
                InvoiceDescription::Hash(&description_hash),
-               duration_since_epoch, invoice_expiry_delta_secs
+               duration_since_epoch, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
        )
 }
 
@@ -326,7 +357,7 @@ pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_sin
 pub fn create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
-       invoice_expiry_delta_secs: u32
+       invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
                where
                        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -343,14 +374,14 @@ pub fn create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T:
                InvoiceDescription::Direct(
                        &Description::new(description).map_err(SignOrCreationError::CreationError)?,
                ),
-               duration_since_epoch, invoice_expiry_delta_secs
+               duration_since_epoch, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
        )
 }
 
 fn _create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description: InvoiceDescription,
-       duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
+       duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
                where
                        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -362,13 +393,18 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T: Der
                        R::Target: Router,
                        L::Target: Logger,
 {
+       if min_final_cltv_expiry_delta.is_some() && min_final_cltv_expiry_delta.unwrap().saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA {
+               return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort));
+       }
+
        // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
        // supply.
        let (payment_hash, payment_secret) = channelmanager
-               .create_inbound_payment(amt_msat, invoice_expiry_delta_secs)
+               .create_inbound_payment(amt_msat, invoice_expiry_delta_secs, min_final_cltv_expiry_delta)
                .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
        _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
-               channelmanager, node_signer, logger, network, amt_msat, description, duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret)
+               channelmanager, node_signer, logger, network, amt_msat, description, duration_since_epoch,
+               invoice_expiry_delta_secs, payment_hash, payment_secret, min_final_cltv_expiry_delta)
 }
 
 /// See [`create_invoice_from_channelmanager_and_duration_since_epoch`]
@@ -378,7 +414,7 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T: Der
 pub fn create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
-       invoice_expiry_delta_secs: u32, payment_hash: PaymentHash
+       invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
        where
                M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -391,21 +427,24 @@ pub fn create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_
                L::Target: Logger,
 {
        let payment_secret = channelmanager
-               .create_inbound_payment_for_hash(payment_hash,amt_msat, invoice_expiry_delta_secs)
+               .create_inbound_payment_for_hash(payment_hash, amt_msat, invoice_expiry_delta_secs,
+                       min_final_cltv_expiry_delta)
                .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
        _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
                channelmanager, node_signer, logger, network, amt_msat,
                InvoiceDescription::Direct(
                        &Description::new(description).map_err(SignOrCreationError::CreationError)?,
                ),
-               duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret
+               duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret,
+               min_final_cltv_expiry_delta,
        )
 }
 
 fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
        channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
        network: Currency, amt_msat: Option<u64>, description: InvoiceDescription, duration_since_epoch: Duration,
-       invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret
+       invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret,
+       min_final_cltv_expiry_delta: Option<u16>,
 ) -> Result<Invoice, SignOrCreationError<()>>
        where
                M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -420,6 +459,10 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
        let our_node_pubkey = channelmanager.get_our_node_id();
        let channels = channelmanager.list_channels();
 
+       if min_final_cltv_expiry_delta.is_some() && min_final_cltv_expiry_delta.unwrap().saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA {
+               return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort));
+       }
+
        log_trace!(logger, "Creating invoice with payment hash {}", log_bytes!(payment_hash.0));
 
        let invoice = match description {
@@ -435,7 +478,9 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
                .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
                .payment_secret(payment_secret)
                .basic_mpp()
-               .min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
+               .min_final_cltv_expiry_delta(
+                       // Add a buffer of 3 to the delta if present, otherwise use LDK's minimum.
+                       min_final_cltv_expiry_delta.map(|x| x.saturating_add(3)).unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA).into())
                .expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
        if let Some(amt) = amt_msat {
                invoice = invoice.amount_milli_satoshis(amt);
@@ -637,12 +682,12 @@ where
 #[cfg(test)]
 mod test {
        use core::time::Duration;
-       use crate::{Currency, Description, InvoiceDescription};
+       use crate::{Currency, Description, InvoiceDescription, SignOrCreationError, CreationError};
        use bitcoin_hashes::{Hash, sha256};
        use bitcoin_hashes::sha256::Hash as Sha256;
        use lightning::chain::keysinterface::{EntropySource, PhantomKeysManager};
        use lightning::ln::{PaymentPreimage, PaymentHash};
-       use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY, PaymentId};
+       use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId};
        use lightning::ln::functional_test_utils::*;
        use lightning::ln::msgs::ChannelMessageHandler;
        use lightning::routing::router::{PaymentParameters, RouteParameters, find_route};
@@ -663,9 +708,10 @@ mod test {
                let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
                        Some(10_000), "test".to_string(), Duration::from_secs(1234567),
-                       non_default_invoice_expiry_secs).unwrap();
+                       non_default_invoice_expiry_secs, None).unwrap();
                assert_eq!(invoice.amount_pico_btc(), Some(100_000));
-               assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
+               // If no `min_final_cltv_expiry_delta` is specified, then it should be `MIN_FINAL_CLTV_EXPIRY_DELTA`.
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
                assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
 
@@ -685,7 +731,7 @@ mod test {
                let route_params = RouteParameters {
                        payment_params,
                        final_value_msat: invoice.amount_milli_satoshis().unwrap(),
-                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32,
+                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
                };
                let first_hops = nodes[0].node.list_usable_channels();
                let network_graph = &node_cfgs[0].network_graph;
@@ -719,6 +765,44 @@ mod test {
                assert_eq!(events.len(), 2);
        }
 
+       fn do_create_invoice_min_final_cltv_delta(with_custom_delta: bool) {
+               let chanmon_cfgs = create_chanmon_cfgs(2);
+               let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+               let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+               let custom_min_final_cltv_expiry_delta = Some(50);
+
+               let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
+                       &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
+                       Some(10_000), "".into(), Duration::from_secs(1234567), 3600,
+                       if with_custom_delta { custom_min_final_cltv_expiry_delta } else { None },
+               ).unwrap();
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), if with_custom_delta {
+                       custom_min_final_cltv_expiry_delta.unwrap() + 3 /* Buffer */} else { MIN_FINAL_CLTV_EXPIRY_DELTA } as u64);
+       }
+
+       #[test]
+       fn test_create_invoice_custom_min_final_cltv_delta() {
+               do_create_invoice_min_final_cltv_delta(true);
+               do_create_invoice_min_final_cltv_delta(false);
+       }
+
+       #[test]
+       fn create_invoice_min_final_cltv_delta_equals_htlc_fail_buffer() {
+               let chanmon_cfgs = create_chanmon_cfgs(2);
+               let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+               let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+               let custom_min_final_cltv_expiry_delta = Some(21);
+
+               let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
+                       &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
+                       Some(10_000), "".into(), Duration::from_secs(1234567), 3600,
+                       custom_min_final_cltv_expiry_delta,
+               ).unwrap();
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
+       }
+
        #[test]
        fn test_create_invoice_with_description_hash() {
                let chanmon_cfgs = create_chanmon_cfgs(2);
@@ -728,10 +812,10 @@ mod test {
                let description_hash = crate::Sha256(Hash::hash("Testing description_hash".as_bytes()));
                let invoice = crate::utils::create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
-                       Some(10_000), description_hash, Duration::from_secs(1234567), 3600
+                       Some(10_000), description_hash, Duration::from_secs(1234567), 3600, None,
                ).unwrap();
                assert_eq!(invoice.amount_pico_btc(), Some(100_000));
-               assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Testing description_hash".as_bytes()))));
        }
 
@@ -745,10 +829,10 @@ mod test {
                let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
                        &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
                        Some(10_000), "test".to_string(), Duration::from_secs(1234567), 3600,
-                       payment_hash
+                       payment_hash, None,
                ).unwrap();
                assert_eq!(invoice.amount_pico_btc(), Some(100_000));
-               assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
                assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap());
        }
@@ -936,7 +1020,7 @@ mod test {
                let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
                        &invoice_node.node, invoice_node.keys_manager, invoice_node.logger,
                        Currency::BitcoinTestnet, invoice_amt, "test".to_string(), Duration::from_secs(1234567),
-                       3600).unwrap();
+                       3600, None).unwrap();
                let hints = invoice.private_routes();
 
                for hint in hints {
@@ -988,7 +1072,8 @@ mod test {
                let invoice =
                        crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(
                                Some(payment_amt), payment_hash, "test".to_string(), non_default_invoice_expiry_secs,
-                               route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger, Currency::BitcoinTestnet
+                               route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger,
+                               Currency::BitcoinTestnet, None, Duration::from_secs(1234567)
                        ).unwrap();
                let (payment_hash, payment_secret) = (PaymentHash(invoice.payment_hash().into_inner()), *invoice.payment_secret());
                let payment_preimage = if user_generated_pmt_hash {
@@ -997,7 +1082,7 @@ mod test {
                        nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap()
                };
 
-               assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
                assert_eq!(invoice.route_hints().len(), 2);
                assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
@@ -1009,7 +1094,7 @@ mod test {
                let params = RouteParameters {
                        payment_params,
                        final_value_msat: invoice.amount_milli_satoshis().unwrap(),
-                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32,
+                       final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
                };
                let first_hops = nodes[0].node.list_usable_channels();
                let network_graph = &node_cfgs[0].network_graph;
@@ -1089,13 +1174,16 @@ mod test {
                create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001);
 
                let payment_amt = 20_000;
-               let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
+               let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600, None).unwrap();
                let route_hints = vec![
                        nodes[1].node.get_phantom_route_hints(),
                        nodes[2].node.get_phantom_route_hints(),
                ];
 
-               let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), Some(payment_hash), "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger, Currency::BitcoinTestnet).unwrap();
+               let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
+                       &test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), Some(payment_hash),
+                               "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager,
+                               &nodes[1].logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
 
                let chan_0_1 = &nodes[1].node.list_usable_channels()[0];
                assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat);
@@ -1126,15 +1214,43 @@ mod test {
                        &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger,
                >(
                        Some(payment_amt), None, non_default_invoice_expiry_secs, description_hash,
-                       route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger, Currency::BitcoinTestnet
+                       route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger,
+                       Currency::BitcoinTestnet, None, Duration::from_secs(1234567),
                )
                .unwrap();
                assert_eq!(invoice.amount_pico_btc(), Some(200_000));
-               assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
                assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
                assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Description hash phantom invoice".as_bytes()))));
        }
 
+       #[test]
+       #[cfg(feature = "std")]
+       fn create_phantom_invoice_with_custom_payment_hash_and_custom_min_final_cltv_delta() {
+               let chanmon_cfgs = create_chanmon_cfgs(3);
+               let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+               let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+               let payment_amt = 20_000;
+               let route_hints = vec![
+                       nodes[1].node.get_phantom_route_hints(),
+                       nodes[2].node.get_phantom_route_hints(),
+               ];
+               let user_payment_preimage = PaymentPreimage([1; 32]);
+               let payment_hash = Some(PaymentHash(Sha256::hash(&user_payment_preimage.0[..]).into_inner()));
+               let non_default_invoice_expiry_secs = 4200;
+               let min_final_cltv_expiry_delta = Some(100);
+               let duration_since_epoch = Duration::from_secs(1234567);
+               let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
+                       &test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), payment_hash,
+                               "".to_string(), non_default_invoice_expiry_secs, route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager,
+                               &nodes[1].logger, Currency::BitcoinTestnet, min_final_cltv_expiry_delta, duration_since_epoch).unwrap();
+               assert_eq!(invoice.amount_pico_btc(), Some(200_000));
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), (min_final_cltv_expiry_delta.unwrap() + 3) as u64);
+               assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
+       }
+
        #[test]
        #[cfg(feature = "std")]
        fn test_multi_node_hints_includes_single_channels_to_participating_nodes() {
@@ -1440,7 +1556,10 @@ mod test {
                        .map(|route_hint| route_hint.phantom_scid)
                        .collect::<HashSet<u64>>();
 
-               let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(invoice_amt, None, "test".to_string(), 3600, phantom_route_hints, &invoice_node.keys_manager, &invoice_node.keys_manager, &invoice_node.logger, Currency::BitcoinTestnet).unwrap();
+               let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
+                       &test_utils::TestKeysInterface, &test_utils::TestLogger>(invoice_amt, None, "test".to_string(),
+                               3600, phantom_route_hints, &invoice_node.keys_manager, &invoice_node.keys_manager,
+                               &invoice_node.logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
 
                let invoice_hints = invoice.private_routes();
 
@@ -1463,4 +1582,20 @@ mod test {
                }
                assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match);
        }
+
+       #[test]
+       fn test_create_invoice_fails_with_invalid_custom_min_final_cltv_expiry_delta() {
+               let chanmon_cfgs = create_chanmon_cfgs(2);
+               let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+               let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+               let result = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
+                       &nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
+                       Some(10_000), "Some description".into(), Duration::from_secs(1234567), 3600, Some(MIN_FINAL_CLTV_EXPIRY_DELTA - 4),
+               );
+               match result {
+                       Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort)) => {},
+                       _ => panic!(),
+               }
+       }
 }
index ffac702ce1a99582f42ae75e2e26cf7af98f8f6d..272d9062a6e4c9a062e622c55f2ed568bbae5409 100644 (file)
@@ -246,7 +246,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawInvoice, bool, bool)> {
                                        "462264ede7e14047e9b249da94fefc47f41f7d02ee9b091815a5506bc8abf75f"
                                ).unwrap())
                                .expiry_time(Duration::from_secs(604800))
-                               .min_final_cltv_expiry(10)
+                               .min_final_cltv_expiry_delta(10)
                                .description("Blockstream Store: 88.85 USD for Blockstream Ledger Nano S x 1, \"Back In My Day\" Sticker x 2, \"I Got Lightning Working\" Sticker x 2 and 1 more items".to_owned())
                                .private_route(RouteHint(vec![RouteHintHop {
                                        src_node_id: PublicKey::from_slice(&hex::decode(
index 07f9f313307c0cd493ab2e2e54b00489aba283c5..8a518638c5f789de307d1fa47cdc3f37422c61ac 100644 (file)
@@ -21,3 +21,4 @@ tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "sync", "net"
 
 [dev-dependencies]
 tokio = { version = "~1.14", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] }
+lightning = { version = "0.0.113", path = "../lightning", features = ["_test_utils"] }
index 45fe9b12f61b17a7b078805de1e6344efa91fbf3..c4a4bedad8f14f91e3efae01d1488de7428f3ee4 100644 (file)
@@ -32,6 +32,7 @@
 //! type TxBroadcaster = dyn lightning::chain::chaininterface::BroadcasterInterface + Send + Sync;
 //! type FeeEstimator = dyn lightning::chain::chaininterface::FeeEstimator + Send + Sync;
 //! type Logger = dyn lightning::util::logger::Logger + Send + Sync;
+//! type NodeSigner = dyn lightning::chain::keysinterface::NodeSigner + Send + Sync;
 //! type ChainAccess = dyn lightning::chain::Access + Send + Sync;
 //! type ChainFilter = dyn lightning::chain::Filter + Send + Sync;
 //! type DataPersister = dyn lightning::chain::chainmonitor::Persist<lightning::chain::keysinterface::InMemorySigner> + Send + Sync;
@@ -80,6 +81,7 @@ use tokio::{io, time};
 use tokio::sync::mpsc;
 use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
 
+use lightning::chain::keysinterface::NodeSigner;
 use lightning::ln::peer_handler;
 use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait;
 use lightning::ln::peer_handler::CustomMessageHandler;
@@ -123,21 +125,23 @@ struct Connection {
        id: u64,
 }
 impl Connection {
-       async fn poll_event_process<PM, CMH, RMH, OMH, L, UMH>(
+       async fn poll_event_process<PM, CMH, RMH, OMH, L, UMH, NS>(
                peer_manager: PM,
                mut event_receiver: mpsc::Receiver<()>,
        ) where
-                       PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH>> + 'static + Send + Sync,
+                       PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH, NS>> + 'static + Send + Sync,
                        CMH: Deref + 'static + Send + Sync,
                        RMH: Deref + 'static + Send + Sync,
                        OMH: Deref + 'static + Send + Sync,
                        L: Deref + 'static + Send + Sync,
                        UMH: Deref + 'static + Send + Sync,
+                       NS: Deref + 'static + Send + Sync,
                        CMH::Target: ChannelMessageHandler + Send + Sync,
                        RMH::Target: RoutingMessageHandler + Send + Sync,
                        OMH::Target: OnionMessageHandler + Send + Sync,
                        L::Target: Logger + Send + Sync,
                        UMH::Target: CustomMessageHandler + Send + Sync,
+                       NS::Target: NodeSigner + Send + Sync,
        {
                loop {
                        if event_receiver.recv().await.is_none() {
@@ -147,24 +151,26 @@ impl Connection {
                }
        }
 
-       async fn schedule_read<PM, CMH, RMH, OMH, L, UMH>(
+       async fn schedule_read<PM, CMH, RMH, OMH, L, UMH, NS>(
                peer_manager: PM,
                us: Arc<Mutex<Self>>,
                mut reader: io::ReadHalf<TcpStream>,
                mut read_wake_receiver: mpsc::Receiver<()>,
                mut write_avail_receiver: mpsc::Receiver<()>,
        ) where
-                       PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH>> + 'static + Send + Sync + Clone,
+                       PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH, NS>> + 'static + Send + Sync + Clone,
                        CMH: Deref + 'static + Send + Sync,
                        RMH: Deref + 'static + Send + Sync,
                        OMH: Deref + 'static + Send + Sync,
                        L: Deref + 'static + Send + Sync,
                        UMH: Deref + 'static + Send + Sync,
+                       NS: Deref + 'static + Send + Sync,
                        CMH::Target: ChannelMessageHandler + 'static + Send + Sync,
                        RMH::Target: RoutingMessageHandler + 'static + Send + Sync,
                        OMH::Target: OnionMessageHandler + 'static + Send + Sync,
                        L::Target: Logger + 'static + Send + Sync,
                        UMH::Target: CustomMessageHandler + 'static + Send + Sync,
+                       NS::Target: NodeSigner + 'static + Send + Sync,
                {
                // Create a waker to wake up poll_event_process, above
                let (event_waker, event_receiver) = mpsc::channel(1);
@@ -283,25 +289,27 @@ fn get_addr_from_stream(stream: &StdTcpStream) -> Option<NetAddress> {
 /// The returned future will complete when the peer is disconnected and associated handling
 /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do
 /// not need to poll the provided future in order to make progress.
-pub fn setup_inbound<PM, CMH, RMH, OMH, L, UMH>(
+pub fn setup_inbound<PM, CMH, RMH, OMH, L, UMH, NS>(
        peer_manager: PM,
        stream: StdTcpStream,
 ) -> impl std::future::Future<Output=()> where
-               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH>> + 'static + Send + Sync + Clone,
+               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH, NS>> + 'static + Send + Sync + Clone,
                CMH: Deref + 'static + Send + Sync,
                RMH: Deref + 'static + Send + Sync,
                OMH: Deref + 'static + Send + Sync,
                L: Deref + 'static + Send + Sync,
                UMH: Deref + 'static + Send + Sync,
+               NS: Deref + 'static + Send + Sync,
                CMH::Target: ChannelMessageHandler + Send + Sync,
                RMH::Target: RoutingMessageHandler + Send + Sync,
                OMH::Target: OnionMessageHandler + Send + Sync,
                L::Target: Logger + Send + Sync,
                UMH::Target: CustomMessageHandler + Send + Sync,
+               NS::Target: NodeSigner + Send + Sync,
 {
        let remote_addr = get_addr_from_stream(&stream);
        let (reader, write_receiver, read_receiver, us) = Connection::new(stream);
-       #[cfg(debug_assertions)]
+       #[cfg(test)]
        let last_us = Arc::clone(&us);
 
        let handle_opt = if let Ok(_) = peer_manager.new_inbound_connection(SocketDescriptor::new(us.clone()), remote_addr) {
@@ -322,8 +330,8 @@ pub fn setup_inbound<PM, CMH, RMH, OMH, L, UMH>(
                                // socket shutdown(). Still, as a check during testing, to make sure tokio doesn't
                                // keep too many wakers around, this makes sense. The race should be rare (we do
                                // some work after shutdown()) and an error would be a major memory leak.
-                               #[cfg(debug_assertions)]
-                               assert!(Arc::try_unwrap(last_us).is_ok());
+                               #[cfg(test)]
+                               debug_assert!(Arc::try_unwrap(last_us).is_ok());
                        }
                }
        }
@@ -336,26 +344,28 @@ pub fn setup_inbound<PM, CMH, RMH, OMH, L, UMH>(
 /// The returned future will complete when the peer is disconnected and associated handling
 /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do
 /// not need to poll the provided future in order to make progress.
-pub fn setup_outbound<PM, CMH, RMH, OMH, L, UMH>(
+pub fn setup_outbound<PM, CMH, RMH, OMH, L, UMH, NS>(
        peer_manager: PM,
        their_node_id: PublicKey,
        stream: StdTcpStream,
 ) -> impl std::future::Future<Output=()> where
-               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH>> + 'static + Send + Sync + Clone,
+               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH, NS>> + 'static + Send + Sync + Clone,
                CMH: Deref + 'static + Send + Sync,
                RMH: Deref + 'static + Send + Sync,
                OMH: Deref + 'static + Send + Sync,
                L: Deref + 'static + Send + Sync,
                UMH: Deref + 'static + Send + Sync,
+               NS: Deref + 'static + Send + Sync,
                CMH::Target: ChannelMessageHandler + Send + Sync,
                RMH::Target: RoutingMessageHandler + Send + Sync,
                OMH::Target: OnionMessageHandler + Send + Sync,
                L::Target: Logger + Send + Sync,
                UMH::Target: CustomMessageHandler + Send + Sync,
+               NS::Target: NodeSigner + Send + Sync,
 {
        let remote_addr = get_addr_from_stream(&stream);
        let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream);
-       #[cfg(debug_assertions)]
+       #[cfg(test)]
        let last_us = Arc::clone(&us);
        let handle_opt = if let Ok(initial_send) = peer_manager.new_outbound_connection(their_node_id, SocketDescriptor::new(us.clone()), remote_addr) {
                Some(tokio::spawn(async move {
@@ -401,8 +411,8 @@ pub fn setup_outbound<PM, CMH, RMH, OMH, L, UMH>(
                                // socket shutdown(). Still, as a check during testing, to make sure tokio doesn't
                                // keep too many wakers around, this makes sense. The race should be rare (we do
                                // some work after shutdown()) and an error would be a major memory leak.
-                               #[cfg(debug_assertions)]
-                               assert!(Arc::try_unwrap(last_us).is_ok());
+                               #[cfg(test)]
+                               debug_assert!(Arc::try_unwrap(last_us).is_ok());
                        }
                }
        }
@@ -419,22 +429,24 @@ pub fn setup_outbound<PM, CMH, RMH, OMH, L, UMH>(
 /// disconnected and associated handling futures are freed, though, because all processing in said
 /// futures are spawned with tokio::spawn, you do not need to poll the second future in order to
 /// make progress.
-pub async fn connect_outbound<PM, CMH, RMH, OMH, L, UMH>(
+pub async fn connect_outbound<PM, CMH, RMH, OMH, L, UMH, NS>(
        peer_manager: PM,
        their_node_id: PublicKey,
        addr: SocketAddr,
 ) -> Option<impl std::future::Future<Output=()>> where
-               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH>> + 'static + Send + Sync + Clone,
+               PM: Deref<Target = peer_handler::PeerManager<SocketDescriptor, CMH, RMH, OMH, L, UMH, NS>> + 'static + Send + Sync + Clone,
                CMH: Deref + 'static + Send + Sync,
                RMH: Deref + 'static + Send + Sync,
                OMH: Deref + 'static + Send + Sync,
                L: Deref + 'static + Send + Sync,
                UMH: Deref + 'static + Send + Sync,
+               NS: Deref + 'static + Send + Sync,
                CMH::Target: ChannelMessageHandler + Send + Sync,
                RMH::Target: RoutingMessageHandler + Send + Sync,
                OMH::Target: OnionMessageHandler + Send + Sync,
                L::Target: Logger + Send + Sync,
                UMH::Target: CustomMessageHandler + Send + Sync,
+               NS::Target: NodeSigner + Send + Sync,
 {
        if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) }).await {
                Some(setup_outbound(peer_manager, their_node_id, stream))
@@ -573,6 +585,7 @@ mod tests {
        use lightning::ln::peer_handler::{MessageHandler, PeerManager};
        use lightning::ln::features::NodeFeatures;
        use lightning::util::events::*;
+       use lightning::util::test_utils::TestNodeSigner;
        use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
 
        use tokio::sync::mpsc;
@@ -688,7 +701,7 @@ mod tests {
                        chan_handler: Arc::clone(&a_handler),
                        route_handler: Arc::clone(&a_handler),
                        onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
-               }, a_key.clone(), 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+               }, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(a_key))));
 
                let (b_connected_sender, mut b_connected) = mpsc::channel(1);
                let (b_disconnected_sender, mut b_disconnected) = mpsc::channel(1);
@@ -703,7 +716,7 @@ mod tests {
                        chan_handler: Arc::clone(&b_handler),
                        route_handler: Arc::clone(&b_handler),
                        onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
-               }, b_key.clone(), 0, &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+               }, 0, &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(b_key))));
 
                // We bind on localhost, hoping the environment is properly configured with a local
                // address. This may not always be the case in containers and the like, so if this test is
@@ -756,7 +769,7 @@ mod tests {
                        chan_handler: Arc::new(lightning::ln::peer_handler::ErroringMessageHandler::new()),
                        onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
                        route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
-               }, a_key, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+               }, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(a_key))));
 
                // Make two connections, one for an inbound and one for an outbound connection
                let conn_a = {
index 430f6bbac1d2244b7d49c37d10a51153484a5c28..3a2077209c4ea36ebf3b412a048f845e1b344c1f 100644 (file)
@@ -31,7 +31,7 @@ use crate::chain::{ChannelMonitorUpdateStatus, Filter, WatchedOutput};
 use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs, LATENCY_GRACE_PERIOD_BLOCKS};
 use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::Sign;
+use crate::chain::keysinterface::WriteableEcdsaChannelSigner;
 use crate::util::atomic_counter::AtomicCounter;
 use crate::util::logger::Logger;
 use crate::util::errors::APIError;
@@ -68,7 +68,7 @@ impl MonitorUpdateId {
        pub(crate) fn from_monitor_update(update: &ChannelMonitorUpdate) -> Self {
                Self { contents: UpdateOrigin::OffChain(update.update_id) }
        }
-       pub(crate) fn from_new_monitor<ChannelSigner: Sign>(monitor: &ChannelMonitor<ChannelSigner>) -> Self {
+       pub(crate) fn from_new_monitor<ChannelSigner: WriteableEcdsaChannelSigner>(monitor: &ChannelMonitor<ChannelSigner>) -> Self {
                Self { contents: UpdateOrigin::OffChain(monitor.get_latest_update_id()) }
        }
 }
@@ -93,7 +93,7 @@ impl MonitorUpdateId {
 ///    [`ChannelMonitorUpdateStatus::PermanentFailure`], in which case the channel will likely be
 ///    closed without broadcasting the latest state. See
 ///    [`ChannelMonitorUpdateStatus::PermanentFailure`] for more details.
-pub trait Persist<ChannelSigner: Sign> {
+pub trait Persist<ChannelSigner: WriteableEcdsaChannelSigner> {
        /// Persist a new channel's data in response to a [`chain::Watch::watch_channel`] call. This is
        /// called by [`ChannelManager`] for new channels, or may be called directly, e.g. on startup.
        ///
@@ -147,7 +147,7 @@ pub trait Persist<ChannelSigner: Sign> {
        fn update_persisted_channel(&self, channel_id: OutPoint, update: Option<&ChannelMonitorUpdate>, data: &ChannelMonitor<ChannelSigner>, update_id: MonitorUpdateId) -> ChannelMonitorUpdateStatus;
 }
 
-struct MonitorHolder<ChannelSigner: Sign> {
+struct MonitorHolder<ChannelSigner: WriteableEcdsaChannelSigner> {
        monitor: ChannelMonitor<ChannelSigner>,
        /// The full set of pending monitor updates for this Channel.
        ///
@@ -182,7 +182,7 @@ struct MonitorHolder<ChannelSigner: Sign> {
        last_chain_persist_height: AtomicUsize,
 }
 
-impl<ChannelSigner: Sign> MonitorHolder<ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> MonitorHolder<ChannelSigner> {
        fn has_pending_offchain_updates(&self, pending_monitor_updates_lock: &MutexGuard<Vec<MonitorUpdateId>>) -> bool {
                pending_monitor_updates_lock.iter().any(|update_id|
                        if let UpdateOrigin::OffChain(_) = update_id.contents { true } else { false })
@@ -197,12 +197,12 @@ impl<ChannelSigner: Sign> MonitorHolder<ChannelSigner> {
 ///
 /// Note that this holds a mutex in [`ChainMonitor`] and may block other events until it is
 /// released.
-pub struct LockedChannelMonitor<'a, ChannelSigner: Sign> {
+pub struct LockedChannelMonitor<'a, ChannelSigner: WriteableEcdsaChannelSigner> {
        lock: RwLockReadGuard<'a, HashMap<OutPoint, MonitorHolder<ChannelSigner>>>,
        funding_txo: OutPoint,
 }
 
-impl<ChannelSigner: Sign> Deref for LockedChannelMonitor<'_, ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> Deref for LockedChannelMonitor<'_, ChannelSigner> {
        type Target = ChannelMonitor<ChannelSigner>;
        fn deref(&self) -> &ChannelMonitor<ChannelSigner> {
                &self.lock.get(&self.funding_txo).expect("Checked at construction").monitor
@@ -218,7 +218,7 @@ impl<ChannelSigner: Sign> Deref for LockedChannelMonitor<'_, ChannelSigner> {
 ///
 /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
 /// [module-level documentation]: crate::chain::chainmonitor
-pub struct ChainMonitor<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
+pub struct ChainMonitor<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
        where C::Target: chain::Filter,
         T::Target: BroadcasterInterface,
         F::Target: FeeEstimator,
@@ -242,7 +242,7 @@ pub struct ChainMonitor<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: De
        highest_chain_height: AtomicUsize,
 }
 
-impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref> ChainMonitor<ChannelSigner, C, T, F, L, P>
+impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref> ChainMonitor<ChannelSigner, C, T, F, L, P>
 where C::Target: chain::Filter,
            T::Target: BroadcasterInterface,
            F::Target: FeeEstimator,
@@ -516,7 +516,7 @@ where C::Target: chain::Filter,
        }
 }
 
-impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
+impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
 chain::Listen for ChainMonitor<ChannelSigner, C, T, F, L, P>
 where
        C::Target: chain::Filter,
@@ -543,7 +543,7 @@ where
        }
 }
 
-impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
+impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
 chain::Confirm for ChainMonitor<ChannelSigner, C, T, F, L, P>
 where
        C::Target: chain::Filter,
@@ -592,7 +592,7 @@ where
        }
 }
 
-impl<ChannelSigner: Sign, C: Deref , T: Deref , F: Deref , L: Deref , P: Deref >
+impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref , T: Deref , F: Deref , L: Deref , P: Deref >
 chain::Watch<ChannelSigner> for ChainMonitor<ChannelSigner, C, T, F, L, P>
 where C::Target: chain::Filter,
            T::Target: BroadcasterInterface,
@@ -735,7 +735,7 @@ where C::Target: chain::Filter,
        }
 }
 
-impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref> events::EventsProvider for ChainMonitor<ChannelSigner, C, T, F, L, P>
+impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref> events::EventsProvider for ChainMonitor<ChannelSigner, C, T, F, L, P>
        where C::Target: chain::Filter,
              T::Target: BroadcasterInterface,
              F::Target: FeeEstimator,
index 36c1eac1ab0e5a1db91618fb46b65e1e255e052b..509ebed6fbad3a6bc597838ec01b7dcb367c33f4 100644 (file)
@@ -42,7 +42,7 @@ use crate::chain;
 use crate::chain::{BestBlock, WatchedOutput};
 use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
 use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, SignerProvider, EntropySource};
+use crate::chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, WriteableEcdsaChannelSigner, SignerProvider, EntropySource};
 #[cfg(anchors)]
 use crate::chain::onchaintx::ClaimEvent;
 use crate::chain::onchaintx::OnchainTxHandler;
@@ -706,14 +706,15 @@ impl Readable for IrrevocablyResolvedHTLC {
 /// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the
 /// returned block hash and the the current chain and then reconnecting blocks to get to the
 /// best chain) upon deserializing the object!
-pub struct ChannelMonitor<Signer: Sign> {
+pub struct ChannelMonitor<Signer: WriteableEcdsaChannelSigner> {
        #[cfg(test)]
        pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
        #[cfg(not(test))]
        inner: Mutex<ChannelMonitorImpl<Signer>>,
 }
 
-pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
+#[derive(PartialEq)]
+pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
        latest_update_id: u64,
        commitment_transaction_number_obscure_factor: u64,
 
@@ -847,17 +848,12 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
 
        /// The node_id of our counterparty
        counterparty_node_id: Option<PublicKey>,
-
-       secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
 }
 
 /// Transaction outputs to watch for on-chain spends.
 pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>);
 
-#[cfg(any(test, fuzzing, feature = "_test_utils"))]
-/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying
-/// object
-impl<Signer: Sign> PartialEq for ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> PartialEq for ChannelMonitor<Signer> where Signer: PartialEq {
        fn eq(&self, other: &Self) -> bool {
                let inner = self.inner.lock().unwrap();
                let other = other.inner.lock().unwrap();
@@ -865,54 +861,7 @@ impl<Signer: Sign> PartialEq for ChannelMonitor<Signer> {
        }
 }
 
-#[cfg(any(test, fuzzing, feature = "_test_utils"))]
-/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying
-/// object
-impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
-       fn eq(&self, other: &Self) -> bool {
-               if self.latest_update_id != other.latest_update_id ||
-                       self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor ||
-                       self.destination_script != other.destination_script ||
-                       self.broadcasted_holder_revokable_script != other.broadcasted_holder_revokable_script ||
-                       self.counterparty_payment_script != other.counterparty_payment_script ||
-                       self.channel_keys_id != other.channel_keys_id ||
-                       self.holder_revocation_basepoint != other.holder_revocation_basepoint ||
-                       self.funding_info != other.funding_info ||
-                       self.current_counterparty_commitment_txid != other.current_counterparty_commitment_txid ||
-                       self.prev_counterparty_commitment_txid != other.prev_counterparty_commitment_txid ||
-                       self.counterparty_commitment_params != other.counterparty_commitment_params ||
-                       self.funding_redeemscript != other.funding_redeemscript ||
-                       self.channel_value_satoshis != other.channel_value_satoshis ||
-                       self.their_cur_per_commitment_points != other.their_cur_per_commitment_points ||
-                       self.on_holder_tx_csv != other.on_holder_tx_csv ||
-                       self.commitment_secrets != other.commitment_secrets ||
-                       self.counterparty_claimable_outpoints != other.counterparty_claimable_outpoints ||
-                       self.counterparty_commitment_txn_on_chain != other.counterparty_commitment_txn_on_chain ||
-                       self.counterparty_hash_commitment_number != other.counterparty_hash_commitment_number ||
-                       self.prev_holder_signed_commitment_tx != other.prev_holder_signed_commitment_tx ||
-                       self.current_counterparty_commitment_number != other.current_counterparty_commitment_number ||
-                       self.current_holder_commitment_number != other.current_holder_commitment_number ||
-                       self.current_holder_commitment_tx != other.current_holder_commitment_tx ||
-                       self.payment_preimages != other.payment_preimages ||
-                       self.pending_monitor_events != other.pending_monitor_events ||
-                       self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly
-                       self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf ||
-                       self.outputs_to_watch != other.outputs_to_watch ||
-                       self.lockdown_from_offchain != other.lockdown_from_offchain ||
-                       self.holder_tx_signed != other.holder_tx_signed ||
-                       self.funding_spend_seen != other.funding_spend_seen ||
-                       self.funding_spend_confirmed != other.funding_spend_confirmed ||
-                       self.confirmed_commitment_tx_counterparty_output != other.confirmed_commitment_tx_counterparty_output ||
-                       self.htlcs_resolved_on_chain != other.htlcs_resolved_on_chain
-               {
-                       false
-               } else {
-                       true
-               }
-       }
-}
-
-impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitor<Signer> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
                self.inner.lock().unwrap().write(writer)
        }
@@ -922,7 +871,7 @@ impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
                write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
 
@@ -1090,7 +1039,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
        }
 }
 
-impl<Signer: Sign> ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
        /// For lockorder enforcement purposes, we need to have a single site which constructs the
        /// `inner` mutex, otherwise cases where we lock two monitors at the same time (eg in our
        /// PartialEq implementation) we may decide a lockorder violation has occurred.
@@ -1140,7 +1089,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
 
                let onchain_tx_handler =
                        OnchainTxHandler::new(destination_script.clone(), keys,
-                       channel_parameters.clone(), initial_holder_commitment_tx, secp_ctx.clone());
+                       channel_parameters.clone(), initial_holder_commitment_tx, secp_ctx);
 
                let mut outputs_to_watch = HashMap::new();
                outputs_to_watch.insert(funding_info.0.txid, vec![(funding_info.0.index as u32, funding_info.1.clone())]);
@@ -1196,8 +1145,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
 
                        best_block,
                        counterparty_node_id: Some(counterparty_node_id),
-
-                       secp_ctx,
                })
        }
 
@@ -1521,7 +1468,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
        }
 }
 
-impl<Signer: Sign> ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
        /// Helper for get_claimable_balances which does the work for an individual HTLC, generating up
        /// to one `Balance` for the HTLC.
        fn get_htlc_balance(&self, htlc: &HTLCOutputInCommitment, holder_commitment: bool,
@@ -1684,7 +1631,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        }
 }
 
-impl<Signer: Sign> ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
        /// Gets the balances in this channel which are either claimable by us if we were to
        /// force-close the channel now or which are claimable on-chain (possibly awaiting
        /// confirmation).
@@ -2082,7 +2029,7 @@ pub fn deliberately_bogus_accepted_htlc_witness() -> Vec<Vec<u8>> {
        vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into()
 }
 
-impl<Signer: Sign> ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
        /// Inserts a revocation secret into this channel monitor. Prunes old preimages if neither
        /// needed by holder commitment transactions HTCLs nor by counterparty ones. Unless we haven't already seen
        /// counterparty commitment transaction's secret, they are de facto pruned (we can use revocation key).
@@ -2512,9 +2459,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                if commitment_number >= self.get_min_seen_secret() {
                        let secret = self.get_secret(commitment_number).unwrap();
                        let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
-                       let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
-                       let revocation_pubkey = chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
-                       let delayed_key = chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+                       let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
+                       let revocation_pubkey = chan_utils::derive_public_revocation_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
+                       let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
 
                        let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
                        let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
@@ -2627,8 +2574,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 
                if let Some(transaction) = tx {
                        let revocation_pubkey = chan_utils::derive_public_revocation_key(
-                               &self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
-                       let delayed_key = chan_utils::derive_public_key(&self.secp_ctx,
+                               &self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
+                       let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
                                &per_commitment_point,
                                &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
                        let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
@@ -2685,7 +2632,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                        Ok(key) => key,
                        Err(_) => return (Vec::new(), None)
                };
-               let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
+               let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
 
                let htlc_txid = tx.txid();
                let mut claimable_outpoints = vec![];
@@ -3664,7 +3611,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        }
 }
 
-impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Listen for (ChannelMonitor<Signer>, T, F, L)
+impl<Signer: WriteableEcdsaChannelSigner, T: Deref, F: Deref, L: Deref> chain::Listen for (ChannelMonitor<Signer>, T, F, L)
 where
        T::Target: BroadcasterInterface,
        F::Target: FeeEstimator,
@@ -3679,7 +3626,7 @@ where
        }
 }
 
-impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Confirm for (ChannelMonitor<Signer>, T, F, L)
+impl<Signer: WriteableEcdsaChannelSigner, T: Deref, F: Deref, L: Deref> chain::Confirm for (ChannelMonitor<Signer>, T, F, L)
 where
        T::Target: BroadcasterInterface,
        F::Target: FeeEstimator,
@@ -3931,9 +3878,6 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
                        (13, spendable_txids_confirmed, vec_type),
                });
 
-               let mut secp_ctx = Secp256k1::new();
-               secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
-
                Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
                        latest_update_id,
                        commitment_transaction_number_obscure_factor,
@@ -3985,8 +3929,6 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
 
                        best_block,
                        counterparty_node_id,
-
-                       secp_ctx,
                })))
        }
 }
@@ -4185,7 +4127,6 @@ mod tests {
                        SecretKey::from_slice(&[41; 32]).unwrap(),
                        SecretKey::from_slice(&[41; 32]).unwrap(),
                        SecretKey::from_slice(&[41; 32]).unwrap(),
-                       SecretKey::from_slice(&[41; 32]).unwrap(),
                        [41; 32],
                        0,
                        [0; 32],
index 9fc00e25238dc8b375d247aec5c8114ce508f109..a2611e7df87f79fefad954aa3b9133addaeb650e 100644 (file)
@@ -21,7 +21,6 @@ use bitcoin::util::sighash;
 
 use bitcoin::bech32::u5;
 use bitcoin::hashes::{Hash, HashEngine};
-use bitcoin::hashes::sha256::HashEngine as Sha256State;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::WPubkeyHash;
@@ -34,14 +33,14 @@ use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
 
 use crate::util::transaction_utils;
 use crate::util::crypto::{hkdf_extract_expand_twice, sign};
-use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
+use crate::util::ser::{Writeable, Writer, Readable};
 #[cfg(anchors)]
 use crate::util::events::HTLCDescriptor;
 use crate::chain::transaction::OutPoint;
 use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
 use crate::ln::{chan_utils, PaymentPreimage};
 use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction};
-use crate::ln::msgs::UnsignedChannelAnnouncement;
+use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
 use crate::ln::script::ShutdownScript;
 
 use crate::prelude::*;
@@ -49,6 +48,8 @@ use core::convert::TryInto;
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::io::{self, Error};
 use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
+use crate::util::atomic_counter::AtomicCounter;
+use crate::util::chacha20::ChaCha20;
 use crate::util::invoice::construct_invoice_preimage;
 
 /// Used as initial key material, to be expanded into multiple secret keys (but not to be used
@@ -75,7 +76,7 @@ pub struct DelayedPaymentOutputDescriptor {
        /// The revocation point specific to the commitment transaction which was broadcast. Used to
        /// derive the witnessScript for this output.
        pub revocation_pubkey: PublicKey,
-       /// Arbitrary identification information returned by a call to [`BaseSign::channel_keys_id`].
+       /// Arbitrary identification information returned by a call to [`ChannelSigner::channel_keys_id`].
        /// This may be useful in re-deriving keys used in the channel to spend the output.
        pub channel_keys_id: [u8; 32],
        /// The value of the channel which this output originated from, possibly indirectly.
@@ -107,7 +108,7 @@ pub struct StaticPaymentOutputDescriptor {
        pub outpoint: OutPoint,
        /// The output which is referenced by the given outpoint.
        pub output: TxOut,
-       /// Arbitrary identification information returned by a call to [`BaseSign::channel_keys_id`].
+       /// Arbitrary identification information returned by a call to [`ChannelSigner::channel_keys_id`].
        /// This may be useful in re-deriving keys used in the channel to spend the output.
        pub channel_keys_id: [u8; 32],
        /// The value of the channel which this transactions spends.
@@ -172,15 +173,15 @@ pub enum SpendableOutputDescriptor {
        ///
        /// To derive the delayed payment key which is used to sign this input, you must pass the
        /// holder [`InMemorySigner::delayed_payment_base_key`] (i.e., the private key which corresponds to the
-       /// [`ChannelPublicKeys::delayed_payment_basepoint`] in [`BaseSign::pubkeys`]) and the provided
+       /// [`ChannelPublicKeys::delayed_payment_basepoint`] in [`ChannelSigner::pubkeys`]) and the provided
        /// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to [`chan_utils::derive_private_key`]. The public key can be
        /// generated without the secret key using [`chan_utils::derive_public_key`] and only the
-       /// [`ChannelPublicKeys::delayed_payment_basepoint`] which appears in [`BaseSign::pubkeys`].
+       /// [`ChannelPublicKeys::delayed_payment_basepoint`] which appears in [`ChannelSigner::pubkeys`].
        ///
        /// To derive the [`DelayedPaymentOutputDescriptor::revocation_pubkey`] provided here (which is
        /// used in the witness script generation), you must pass the counterparty
        /// [`ChannelPublicKeys::revocation_basepoint`] (which appears in the call to
-       /// [`BaseSign::provide_channel_parameters`]) and the provided
+       /// [`ChannelSigner::provide_channel_parameters`]) and the provided
        /// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to
        /// [`chan_utils::derive_public_revocation_key`].
        ///
@@ -191,7 +192,7 @@ pub enum SpendableOutputDescriptor {
        /// [`chan_utils::get_revokeable_redeemscript`].
        DelayedPaymentOutput(DelayedPaymentOutputDescriptor),
        /// An output to a P2WPKH, spendable exclusively by our payment key (i.e., the private key
-       /// which corresponds to the `payment_point` in [`BaseSign::pubkeys`]). The witness
+       /// which corresponds to the `payment_point` in [`ChannelSigner::pubkeys`]). The witness
        /// in the spending input is, thus, simply:
        /// ```bitcoin
        /// <BIP 143 signature> <payment key>
@@ -212,18 +213,14 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
        (2, StaticPaymentOutput),
 );
 
-/// A trait to sign Lightning channel transactions as described in
-/// [BOLT 3](https://github.com/lightning/bolts/blob/master/03-transactions.md).
-///
-/// Signing services could be implemented on a hardware wallet and should implement signing
-/// policies in order to be secure. Please refer to the [VLS Policy
-/// Controls](https://gitlab.com/lightning-signer/validating-lightning-signer/-/blob/main/docs/policy-controls.md)
-/// for an example of such policies.
-pub trait BaseSign {
+/// A trait to handle Lightning channel key material without concretizing the channel type or
+/// the signature mechanism.
+pub trait ChannelSigner {
        /// Gets the per-commitment point for a specific commitment number
        ///
        /// Note that the commitment number starts at `(1 << 48) - 1` and counts backwards.
        fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1<secp256k1::All>) -> PublicKey;
+
        /// Gets the commitment secret for a specific commitment number as part of the revocation process
        ///
        /// An external signer implementation should error here if the commitment was already signed
@@ -234,6 +231,7 @@ pub trait BaseSign {
        /// Note that the commitment number starts at `(1 << 48) - 1` and counts backwards.
        // TODO: return a Result so we can signal a validation error
        fn release_commitment_secret(&self, idx: u64) -> [u8; 32];
+
        /// Validate the counterparty's signatures on the holder commitment transaction and HTLCs.
        ///
        /// This is required in order for the signer to make sure that releasing a commitment
@@ -249,12 +247,35 @@ pub trait BaseSign {
        /// irrelevant or duplicate preimages.
        fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction,
                preimages: Vec<PaymentPreimage>) -> Result<(), ()>;
+
        /// Returns the holder's channel public keys and basepoints.
        fn pubkeys(&self) -> &ChannelPublicKeys;
+
        /// Returns an arbitrary identifier describing the set of keys which are provided back to you in
        /// some [`SpendableOutputDescriptor`] types. This should be sufficient to identify this
-       /// [`BaseSign`] object uniquely and lookup or re-derive its keys.
+       /// [`EcdsaChannelSigner`] object uniquely and lookup or re-derive its keys.
        fn channel_keys_id(&self) -> [u8; 32];
+
+       /// Set the counterparty static channel data, including basepoints,
+       /// `counterparty_selected`/`holder_selected_contest_delay` and funding outpoint.
+       ///
+       /// This data is static, and will never change for a channel once set. For a given [`ChannelSigner`]
+       /// instance, LDK will call this method exactly once - either immediately after construction
+       /// (not including if done via [`SignerProvider::read_chan_signer`]) or when the funding
+       /// information has been generated.
+       ///
+       /// channel_parameters.is_populated() MUST be true.
+       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters);
+}
+
+/// A trait to sign Lightning channel transactions as described in
+/// [BOLT 3](https://github.com/lightning/bolts/blob/master/03-transactions.md).
+///
+/// Signing services could be implemented on a hardware wallet and should implement signing
+/// policies in order to be secure. Please refer to the [VLS Policy
+/// Controls](https://gitlab.com/lightning-signer/validating-lightning-signer/-/blob/main/docs/policy-controls.md)
+/// for an example of such policies.
+pub trait EcdsaChannelSigner: ChannelSigner {
        /// Create a signature for a counterparty's commitment transaction and associated HTLC transactions.
        ///
        /// Note that if signing fails or is rejected, the channel will be force-closed.
@@ -383,27 +404,18 @@ pub trait BaseSign {
        fn sign_holder_anchor_input(
                &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1<secp256k1::All>,
        ) -> Result<Signature, ()>;
-       /// Signs a channel announcement message with our funding key and our node secret key (aka
-       /// node_id or network_key), proving it comes from one of the channel participants.
+       /// Signs a channel announcement message with our funding key proving it comes from one of the
+       /// channel participants.
        ///
-       /// The first returned signature should be from our node secret key, the second from our
-       /// funding key.
+       /// Channel announcements also require a signature from each node's network key. Our node
+       /// signature is computed through [`NodeSigner::sign_gossip_message`].
        ///
        /// Note that if this fails or is rejected, the channel will not be publicly announced and
        /// our counterparty may (though likely will not) close the channel on us for violating the
        /// protocol.
-       fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>)
-               -> Result<(Signature, Signature), ()>;
-       /// Set the counterparty static channel data, including basepoints,
-       /// `counterparty_selected`/`holder_selected_contest_delay` and funding outpoint.
-       ///
-       /// This data is static, and will never change for a channel once set. For a given [`BaseSign`]
-       /// instance, LDK will call this method exactly once - either immediately after construction
-       /// (not including if done via [`SignerProvider::read_chan_signer`]) or when the funding
-       /// information has been generated.
-       ///
-       /// channel_parameters.is_populated() MUST be true.
-       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters);
+       fn sign_channel_announcement_with_funding_key(
+               &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>
+       ) -> Result<Signature, ()>;
 }
 
 /// A writeable signer.
@@ -413,7 +425,7 @@ pub trait BaseSign {
 ///
 /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
 /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
-pub trait Sign: BaseSign + Writeable {}
+pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable {}
 
 /// Specifies the recipient of an invoice.
 ///
@@ -438,16 +450,6 @@ pub trait EntropySource {
 
 /// A trait that can handle cryptographic operations at the scope level of a node.
 pub trait NodeSigner {
-       /// Get node secret key based on the provided [`Recipient`].
-       ///
-       /// The `node_id`/`network_key` is the public key that corresponds to this secret key.
-       ///
-       /// This method must return the same value each time it is called with a given [`Recipient`]
-       /// parameter.
-       ///
-       /// Errors if the [`Recipient`] variant is not supported by the implementation.
-       fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()>;
-
        /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
        ///
        /// If the implementor of this trait supports [phantom node payments], then every node that is
@@ -462,24 +464,22 @@ pub trait NodeSigner {
        /// [phantom node payments]: PhantomKeysManager
        fn get_inbound_payment_key_material(&self) -> KeyMaterial;
 
-       /// Get node id based on the provided [`Recipient`]. This public key corresponds to the secret in
-       /// [`get_node_secret`].
+       /// Get node id based on the provided [`Recipient`].
        ///
        /// This method must return the same value each time it is called with a given [`Recipient`]
        /// parameter.
        ///
        /// Errors if the [`Recipient`] variant is not supported by the implementation.
-       ///
-       /// [`get_node_secret`]: Self::get_node_secret
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()>;
 
-       /// Gets the ECDH shared secret of our [`node secret`] and `other_key`, multiplying by `tweak` if
+       /// Gets the ECDH shared secret of our node secret and `other_key`, multiplying by `tweak` if
        /// one is provided. Note that this tweak can be applied to `other_key` instead of our node
        /// secret, though this is less efficient.
        ///
-       /// Errors if the [`Recipient`] variant is not supported by the implementation.
+       /// Note that if this fails while attempting to forward an HTLC, LDK will panic. The error
+       /// should be resolved to allow LDK to resume forwarding HTLCs.
        ///
-       /// [`node secret`]: Self::get_node_secret
+       /// Errors if the [`Recipient`] variant is not supported by the implementation.
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>;
 
        /// Sign an invoice.
@@ -494,12 +494,20 @@ pub trait NodeSigner {
        ///
        /// Errors if the [`Recipient`] variant is not supported by the implementation.
        fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()>;
+
+       /// Sign a gossip message.
+       ///
+       /// Note that if this fails, LDK may panic and the message will not be broadcast to the network
+       /// or a possible channel counterparty. If LDK panics, the error should be resolved to allow the
+       /// message to be broadcast, as otherwise it may prevent one from receiving funds over the
+       /// corresponding channel.
+       fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()>;
 }
 
 /// A trait that can return signer instances for individual channels.
 pub trait SignerProvider {
-       /// A type which implements [`Sign`] which will be returned by [`Self::derive_channel_signer`].
-       type Signer : Sign;
+       /// A type which implements [`WriteableEcdsaChannelSigner`] which will be returned by [`Self::derive_channel_signer`].
+       type Signer : WriteableEcdsaChannelSigner;
 
        /// Generates a unique `channel_keys_id` that can be used to obtain a [`Self::Signer`] through
        /// [`SignerProvider::derive_channel_signer`]. The `user_channel_id` is provided to allow
@@ -514,12 +522,12 @@ pub trait SignerProvider {
        /// To derive a new `Signer`, a fresh `channel_keys_id` should be obtained through
        /// [`SignerProvider::generate_channel_keys_id`]. Otherwise, an existing `Signer` can be
        /// re-derived from its `channel_keys_id`, which can be obtained through its trait method
-       /// [`BaseSign::channel_keys_id`].
+       /// [`ChannelSigner::channel_keys_id`].
        fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::Signer;
 
        /// Reads a [`Signer`] for this [`SignerProvider`] from the given input stream.
        /// This is only called during deserialization of other objects which contain
-       /// [`Sign`]-implementing objects (i.e., [`ChannelMonitor`]s and [`ChannelManager`]s).
+       /// [`WriteableEcdsaChannelSigner`]-implementing objects (i.e., [`ChannelMonitor`]s and [`ChannelManager`]s).
        /// The bytes are exactly those which `<Self::Signer as Writeable>::write()` writes, and
        /// contain no versioning scheme. You may wish to include your own version prefix and ensure
        /// you've read all of the provided bytes to ensure no corruption occurred.
@@ -546,7 +554,7 @@ pub trait SignerProvider {
 }
 
 #[derive(Clone)]
-/// A simple implementation of [`Sign`] that just keeps the private keys in memory.
+/// A simple implementation of [`WriteableEcdsaChannelSigner`] that just keeps the private keys in memory.
 ///
 /// This implementation performs no policy checks and is insufficient by itself as
 /// a secure external signer.
@@ -566,8 +574,6 @@ pub struct InMemorySigner {
        pub commitment_seed: [u8; 32],
        /// Holder public keys and basepoints.
        pub(crate) holder_channel_pubkeys: ChannelPublicKeys,
-       /// Private key of our node secret, used for signing channel announcements.
-       node_secret: SecretKey,
        /// Counterparty public keys and counterparty/holder `selected_contest_delay`, populated on channel acceptance.
        channel_parameters: Option<ChannelTransactionParameters>,
        /// The total value of this channel.
@@ -580,7 +586,6 @@ impl InMemorySigner {
        /// Creates a new [`InMemorySigner`].
        pub fn new<C: Signing>(
                secp_ctx: &Secp256k1<C>,
-               node_secret: SecretKey,
                funding_key: SecretKey,
                revocation_base_key: SecretKey,
                payment_key: SecretKey,
@@ -601,7 +606,6 @@ impl InMemorySigner {
                        delayed_payment_base_key,
                        htlc_base_key,
                        commitment_seed,
-                       node_secret,
                        channel_value_satoshis,
                        holder_channel_pubkeys,
                        channel_parameters: None,
@@ -627,38 +631,38 @@ impl InMemorySigner {
 
        /// Returns the counterparty's pubkeys.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn counterparty_pubkeys(&self) -> &ChannelPublicKeys { &self.get_channel_parameters().counterparty_parameters.as_ref().unwrap().pubkeys }
        /// Returns the `contest_delay` value specified by our counterparty and applied on holder-broadcastable
        /// transactions, i.e., the amount of time that we have to wait to recover our funds if we
        /// broadcast a transaction.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn counterparty_selected_contest_delay(&self) -> u16 { self.get_channel_parameters().counterparty_parameters.as_ref().unwrap().selected_contest_delay }
        /// Returns the `contest_delay` value specified by us and applied on transactions broadcastable
        /// by our counterparty, i.e., the amount of time that they have to wait to recover their funds
        /// if they broadcast a transaction.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn holder_selected_contest_delay(&self) -> u16 { self.get_channel_parameters().holder_selected_contest_delay }
        /// Returns whether the holder is the initiator.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn is_outbound(&self) -> bool { self.get_channel_parameters().is_outbound_from_holder }
        /// Funding outpoint
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn funding_outpoint(&self) -> &OutPoint { self.get_channel_parameters().funding_outpoint.as_ref().unwrap() }
        /// Returns a [`ChannelTransactionParameters`] for this channel, to be used when verifying or
        /// building transactions.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn get_channel_parameters(&self) -> &ChannelTransactionParameters {
                self.channel_parameters.as_ref().unwrap()
        }
        /// Returns whether anchors should be used.
        ///
-       /// Will panic if [`BaseSign::provide_channel_parameters`] has not been called before.
+       /// Will panic if [`ChannelSigner::provide_channel_parameters`] has not been called before.
        pub fn opt_anchors(&self) -> bool {
                self.get_channel_parameters().opt_anchors.is_some()
        }
@@ -732,7 +736,7 @@ impl InMemorySigner {
        }
 }
 
-impl BaseSign for InMemorySigner {
+impl ChannelSigner for InMemorySigner {
        fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1<secp256k1::All>) -> PublicKey {
                let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap();
                PublicKey::from_secret_key(secp_ctx, &commitment_secret)
@@ -750,6 +754,18 @@ impl BaseSign for InMemorySigner {
 
        fn channel_keys_id(&self) -> [u8; 32] { self.channel_keys_id }
 
+       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) {
+               assert!(self.channel_parameters.is_none() || self.channel_parameters.as_ref().unwrap() == channel_parameters);
+               if self.channel_parameters.is_some() {
+                       // The channel parameters were already set and they match, return early.
+                       return;
+               }
+               assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
+               self.channel_parameters = Some(channel_parameters.clone());
+       }
+}
+
+impl EcdsaChannelSigner for InMemorySigner {
        fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
                let trusted_tx = commitment_tx.trust();
                let keys = trusted_tx.keys();
@@ -872,20 +888,11 @@ impl BaseSign for InMemorySigner {
                Ok(sign(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key))
        }
 
-       fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>)
-       -> Result<(Signature, Signature), ()> {
+       fn sign_channel_announcement_with_funding_key(
+               &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>
+       ) -> Result<Signature, ()> {
                let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
-               Ok((sign(secp_ctx, &msghash, &self.node_secret), sign(secp_ctx, &msghash, &self.funding_key)))
-       }
-
-       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) {
-               assert!(self.channel_parameters.is_none() || self.channel_parameters.as_ref().unwrap() == channel_parameters);
-               if self.channel_parameters.is_some() {
-                       // The channel parameters were already set and they match, return early.
-                       return;
-               }
-               assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
-               self.channel_parameters = Some(channel_parameters.clone());
+               Ok(sign(secp_ctx, &msghash, &self.funding_key))
        }
 }
 
@@ -893,7 +900,7 @@ const SERIALIZATION_VERSION: u8 = 1;
 
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl Sign for InMemorySigner {}
+impl WriteableEcdsaChannelSigner for InMemorySigner {}
 
 impl Writeable for InMemorySigner {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
@@ -915,8 +922,8 @@ impl Writeable for InMemorySigner {
        }
 }
 
-impl ReadableArgs<SecretKey> for InMemorySigner {
-       fn read<R: io::Read>(reader: &mut R, node_secret: SecretKey) -> Result<Self, DecodeError> {
+impl Readable for InMemorySigner {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
                let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
 
                let funding_key = Readable::read(reader)?;
@@ -941,7 +948,6 @@ impl ReadableArgs<SecretKey> for InMemorySigner {
                        payment_key,
                        delayed_payment_base_key,
                        htlc_base_key,
-                       node_secret,
                        commitment_seed,
                        channel_value_satoshis,
                        holder_channel_pubkeys,
@@ -974,9 +980,8 @@ pub struct KeysManager {
        channel_master_key: ExtendedPrivKey,
        channel_child_index: AtomicUsize,
 
-       rand_bytes_master_key: ExtendedPrivKey,
-       rand_bytes_child_index: AtomicUsize,
-       rand_bytes_unique_start: Sha256State,
+       rand_bytes_unique_start: [u8; 32],
+       rand_bytes_index: AtomicCounter,
 
        seed: [u8; 32],
        starting_time_secs: u64,
@@ -1022,15 +1027,16 @@ impl KeysManager {
                                        Err(_) => panic!("Your RNG is busted"),
                                };
                                let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()).expect("Your RNG is busted");
-                               let rand_bytes_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4).unwrap()).expect("Your RNG is busted");
                                let inbound_payment_key: SecretKey = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted").private_key;
                                let mut inbound_pmt_key_bytes = [0; 32];
                                inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]);
 
-                               let mut rand_bytes_unique_start = Sha256::engine();
-                               rand_bytes_unique_start.input(&starting_time_secs.to_be_bytes());
-                               rand_bytes_unique_start.input(&starting_time_nanos.to_be_bytes());
-                               rand_bytes_unique_start.input(seed);
+                               let mut rand_bytes_engine = Sha256::engine();
+                               rand_bytes_engine.input(&starting_time_secs.to_be_bytes());
+                               rand_bytes_engine.input(&starting_time_nanos.to_be_bytes());
+                               rand_bytes_engine.input(seed);
+                               rand_bytes_engine.input(b"LDK PRNG Seed");
+                               let rand_bytes_unique_start = Sha256::from_engine(rand_bytes_engine).into_inner();
 
                                let mut res = KeysManager {
                                        secp_ctx,
@@ -1044,9 +1050,8 @@ impl KeysManager {
                                        channel_master_key,
                                        channel_child_index: AtomicUsize::new(0),
 
-                                       rand_bytes_master_key,
-                                       rand_bytes_child_index: AtomicUsize::new(0),
                                        rand_bytes_unique_start,
+                                       rand_bytes_index: AtomicCounter::new(),
 
                                        seed: *seed,
                                        starting_time_secs,
@@ -1059,7 +1064,7 @@ impl KeysManager {
                        Err(_) => panic!("Your rng is busted"),
                }
        }
-       /// Derive an old [`Sign`] containing per-channel secrets based on a key derivation parameters.
+       /// Derive an old [`WriteableEcdsaChannelSigner`] containing per-channel secrets based on a key derivation parameters.
        pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner {
                let chan_id = u64::from_be_bytes(params[0..8].try_into().unwrap());
                let mut unique_start = Sha256::engine();
@@ -1099,7 +1104,6 @@ impl KeysManager {
 
                InMemorySigner::new(
                        &self.secp_ctx,
-                       self.node_secret,
                        funding_key,
                        revocation_base_key,
                        payment_key,
@@ -1244,25 +1248,14 @@ impl KeysManager {
 
 impl EntropySource for KeysManager {
        fn get_secure_random_bytes(&self) -> [u8; 32] {
-               let mut sha = self.rand_bytes_unique_start.clone();
-
-               let child_ix = self.rand_bytes_child_index.fetch_add(1, Ordering::AcqRel);
-               let child_privkey = self.rand_bytes_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
-               sha.input(&child_privkey.private_key[..]);
-
-               sha.input(b"Unique Secure Random Bytes Salt");
-               Sha256::from_engine(sha).into_inner()
+               let index = self.rand_bytes_index.get_increment();
+               let mut nonce = [0u8; 16];
+               nonce[..8].copy_from_slice(&index.to_be_bytes());
+               ChaCha20::get_single_block(&self.rand_bytes_unique_start, &nonce)
        }
 }
 
 impl NodeSigner for KeysManager {
-       fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
-               match recipient {
-                       Recipient::Node => Ok(self.node_secret.clone()),
-                       Recipient::PhantomNode => Err(())
-               }
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
                match recipient {
                        Recipient::Node => Ok(self.node_id.clone()),
@@ -1271,7 +1264,10 @@ impl NodeSigner for KeysManager {
        }
 
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
-               let mut node_secret = self.get_node_secret(recipient)?;
+               let mut node_secret = match recipient {
+                       Recipient::Node => Ok(self.node_secret.clone()),
+                       Recipient::PhantomNode => Err(())
+               }?;
                if let Some(tweak) = tweak {
                        node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
                }
@@ -1285,10 +1281,15 @@ impl NodeSigner for KeysManager {
        fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
                let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
                let secret = match recipient {
-                       Recipient::Node => self.get_node_secret(Recipient::Node)?,
-                       Recipient::PhantomNode => return Err(()),
-               };
-               Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
+                       Recipient::Node => Ok(&self.node_secret),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
+       }
+
+       fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
+               let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
+               Ok(sign(&self.secp_ctx, &msg_hash, &self.node_secret))
        }
 }
 
@@ -1316,7 +1317,7 @@ impl SignerProvider for KeysManager {
        }
 
        fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
-               InMemorySigner::read(&mut io::Cursor::new(reader), self.node_secret.clone())
+               InMemorySigner::read(&mut io::Cursor::new(reader))
        }
 
        fn get_destination_script(&self) -> Script {
@@ -1363,13 +1364,6 @@ impl EntropySource for PhantomKeysManager {
 }
 
 impl NodeSigner for PhantomKeysManager {
-       fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
-               match recipient {
-                       Recipient::Node => self.inner.get_node_secret(Recipient::Node),
-                       Recipient::PhantomNode => Ok(self.phantom_secret.clone()),
-               }
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
                match recipient {
                        Recipient::Node => self.inner.get_node_id(Recipient::Node),
@@ -1378,7 +1372,10 @@ impl NodeSigner for PhantomKeysManager {
        }
 
        fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
-               let mut node_secret = self.get_node_secret(recipient)?;
+               let mut node_secret = match recipient {
+                       Recipient::Node => self.inner.node_secret.clone(),
+                       Recipient::PhantomNode => self.phantom_secret.clone(),
+               };
                if let Some(tweak) = tweak {
                        node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
                }
@@ -1391,8 +1388,15 @@ impl NodeSigner for PhantomKeysManager {
 
        fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
                let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
-               let secret = self.get_node_secret(recipient)?;
-               Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
+               let secret = match recipient {
+                       Recipient::Node => &self.inner.node_secret,
+                       Recipient::PhantomNode => &self.phantom_secret,
+               };
+               Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
+       }
+
+       fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
+               self.inner.sign_gossip_message(msg)
        }
 }
 
@@ -1456,8 +1460,63 @@ impl PhantomKeysManager {
        }
 }
 
-// Ensure that BaseSign can have a vtable
+// Ensure that EcdsaChannelSigner can have a vtable
 #[test]
 pub fn dyn_sign() {
-       let _signer: Box<dyn BaseSign>;
+       let _signer: Box<dyn EcdsaChannelSigner>;
+}
+
+#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
+mod benches {
+       use std::sync::{Arc, mpsc};
+       use std::sync::mpsc::TryRecvError;
+       use std::thread;
+       use std::time::Duration;
+       use bitcoin::blockdata::constants::genesis_block;
+       use bitcoin::Network;
+       use crate::chain::keysinterface::{EntropySource, KeysManager};
+
+       use test::Bencher;
+
+       #[bench]
+       fn bench_get_secure_random_bytes(bench: &mut Bencher) {
+               let seed = [0u8; 32];
+               let now = Duration::from_secs(genesis_block(Network::Testnet).header.time as u64);
+               let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_micros()));
+
+               let mut handles = Vec::new();
+               let mut stops = Vec::new();
+               for _ in 1..5 {
+                       let keys_manager_clone = Arc::clone(&keys_manager);
+                       let (stop_sender, stop_receiver) = mpsc::channel();
+                       let handle = thread::spawn(move || {
+                               loop {
+                                       keys_manager_clone.get_secure_random_bytes();
+                                       match stop_receiver.try_recv() {
+                                               Ok(_) | Err(TryRecvError::Disconnected) => {
+                                                       println!("Terminating.");
+                                                       break;
+                                               }
+                                               Err(TryRecvError::Empty) => {}
+                                       }
+                               }
+                       });
+                       handles.push(handle);
+                       stops.push(stop_sender);
+               }
+
+               bench.iter(|| {
+                       for _ in 1..100 {
+                               keys_manager.get_secure_random_bytes();
+                       }
+               });
+
+               for stop in stops {
+                       let _ = stop.send(());
+               }
+               for handle in handles {
+                       handle.join().unwrap();
+               }
+       }
+
 }
index 19218ed23274998b9702f74f9cc73e26ddde28a8..01eae488700605b2f23c50d5fdfdc0c2319859bc 100644 (file)
@@ -18,7 +18,7 @@ use bitcoin::network::constants::Network;
 use bitcoin::secp256k1::PublicKey;
 
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, MonitorEvent};
-use crate::chain::keysinterface::Sign;
+use crate::chain::keysinterface::WriteableEcdsaChannelSigner;
 use crate::chain::transaction::{OutPoint, TransactionData};
 
 use crate::prelude::*;
@@ -291,7 +291,7 @@ pub enum ChannelMonitorUpdateStatus {
 /// multiple instances.
 ///
 /// [`PermanentFailure`]: ChannelMonitorUpdateStatus::PermanentFailure
-pub trait Watch<ChannelSigner: Sign> {
+pub trait Watch<ChannelSigner: WriteableEcdsaChannelSigner> {
        /// Watches a channel identified by `funding_txo` using `monitor`.
        ///
        /// Implementations are responsible for watching the chain for the funding transaction along
index f526cc8aaa4aa85b2b720dd5f8de3b74c00ae06e..039fb5ff13a04eb1fd843d061bbd992a0f394935 100644 (file)
@@ -21,7 +21,7 @@ use bitcoin::hash_types::{Txid, BlockHash};
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1;
 
-use crate::chain::keysinterface::{BaseSign, EntropySource, SignerProvider};
+use crate::chain::keysinterface::{ChannelSigner, EntropySource, SignerProvider};
 use crate::ln::msgs::DecodeError;
 use crate::ln::PaymentPreimage;
 #[cfg(anchors)]
@@ -31,7 +31,7 @@ use crate::ln::chan_utils::{ChannelTransactionParameters, HolderCommitmentTransa
 use crate::chain::chaininterface::ConfirmationTarget;
 use crate::chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator};
 use crate::chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER};
-use crate::chain::keysinterface::Sign;
+use crate::chain::keysinterface::WriteableEcdsaChannelSigner;
 #[cfg(anchors)]
 use crate::chain::package::PackageSolvingData;
 use crate::chain::package::PackageTemplate;
@@ -219,7 +219,8 @@ type PackageID = [u8; 32];
 
 /// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
 /// do RBF bumping if possible.
-pub struct OnchainTxHandler<ChannelSigner: Sign> {
+#[derive(PartialEq)]
+pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
        destination_script: Script,
        holder_commitment: HolderCommitmentTransaction,
        // holder_htlc_sigs and prev_holder_htlc_sigs are in the order as they appear in the commitment
@@ -271,7 +272,7 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
 
@@ -415,7 +416,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
        }
 }
 
-impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn new(destination_script: Script, signer: ChannelSigner, channel_parameters: ChannelTransactionParameters, holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1<secp256k1::All>) -> Self {
                OnchainTxHandler {
                        destination_script,
index 227e5ccd119188204b6f374300b0e5dceb777f46..5537a56f2f3898bcee470ae1fae87cbf44c5767c 100644 (file)
@@ -25,7 +25,7 @@ use crate::ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment};
 use crate::ln::chan_utils;
 use crate::ln::msgs::DecodeError;
 use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
-use crate::chain::keysinterface::Sign;
+use crate::chain::keysinterface::WriteableEcdsaChannelSigner;
 #[cfg(anchors)]
 use crate::chain::onchaintx::ExternalHTLCClaim;
 use crate::chain::onchaintx::OnchainTxHandler;
@@ -392,7 +392,7 @@ impl PackageSolvingData {
                        _ => { mem::discriminant(self) == mem::discriminant(&input) }
                }
        }
-       fn finalize_input<Signer: Sign>(&self, bumped_tx: &mut Transaction, i: usize, onchain_handler: &mut OnchainTxHandler<Signer>) -> bool {
+       fn finalize_input<Signer: WriteableEcdsaChannelSigner>(&self, bumped_tx: &mut Transaction, i: usize, onchain_handler: &mut OnchainTxHandler<Signer>) -> bool {
                match self {
                        PackageSolvingData::RevokedOutput(ref outp) => {
                                let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
@@ -448,7 +448,7 @@ impl PackageSolvingData {
                }
                true
        }
-       fn get_finalized_tx<Signer: Sign>(&self, outpoint: &BitcoinOutPoint, onchain_handler: &mut OnchainTxHandler<Signer>) -> Option<Transaction> {
+       fn get_finalized_tx<Signer: WriteableEcdsaChannelSigner>(&self, outpoint: &BitcoinOutPoint, onchain_handler: &mut OnchainTxHandler<Signer>) -> Option<Transaction> {
                match self {
                        PackageSolvingData::HolderHTLCOutput(ref outp) => {
                                debug_assert!(!outp.opt_anchors());
@@ -657,7 +657,7 @@ impl PackageTemplate {
                inputs_weight + witnesses_weight + transaction_weight + output_weight
        }
        #[cfg(anchors)]
-       pub(crate) fn construct_malleable_package_with_external_funding<Signer: Sign>(
+       pub(crate) fn construct_malleable_package_with_external_funding<Signer: WriteableEcdsaChannelSigner>(
                &self, onchain_handler: &mut OnchainTxHandler<Signer>,
        ) -> Option<Vec<ExternalHTLCClaim>> {
                debug_assert!(self.requires_external_funding());
@@ -675,7 +675,7 @@ impl PackageTemplate {
                }
                htlcs
        }
-       pub(crate) fn finalize_malleable_package<L: Deref, Signer: Sign>(
+       pub(crate) fn finalize_malleable_package<L: Deref, Signer: WriteableEcdsaChannelSigner>(
                &self, onchain_handler: &mut OnchainTxHandler<Signer>, value: u64, destination_script: Script, logger: &L
        ) -> Option<Transaction> where L::Target: Logger {
                debug_assert!(self.is_malleable());
@@ -703,7 +703,7 @@ impl PackageTemplate {
                log_debug!(logger, "Finalized transaction {} ready to broadcast", bumped_tx.txid());
                Some(bumped_tx)
        }
-       pub(crate) fn finalize_untractable_package<L: Deref, Signer: Sign>(
+       pub(crate) fn finalize_untractable_package<L: Deref, Signer: WriteableEcdsaChannelSigner>(
                &self, onchain_handler: &mut OnchainTxHandler<Signer>, logger: &L,
        ) -> Option<Transaction> where L::Target: Logger {
                debug_assert!(!self.is_malleable());
index cd9f261b2283b40fb2efd5db45ef4a0fa2f255b7..31881d05dfa1c1883e066f526d76dca20037df99 100644 (file)
@@ -1635,7 +1635,7 @@ mod tests {
        use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
        use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
        use crate::util::test_utils;
-       use crate::chain::keysinterface::{BaseSign, SignerProvider};
+       use crate::chain::keysinterface::{ChannelSigner, SignerProvider};
        use bitcoin::{Network, Txid};
        use bitcoin::hashes::Hash;
        use crate::ln::PaymentHash;
index 5dbae1bbbb6924119a4a56c648362e31f99dc6d6..d9ec57d5a7e773c410640c8be4e47b1d96a9a482 100644 (file)
@@ -35,7 +35,7 @@ use crate::chain::BestBlock;
 use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
 use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::{Sign, EntropySource, BaseSign, SignerProvider};
+use crate::chain::keysinterface::{WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
 use crate::util::events::ClosureReason;
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
 use crate::util::logger::Logger;
@@ -498,7 +498,7 @@ pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;
 //
 // Holder designates channel data owned for the benefice of the user client.
 // Counterparty designates channel data owned by the another channel participant entity.
-pub(super) struct Channel<Signer: Sign> {
+pub(super) struct Channel<Signer: ChannelSigner> {
        config: LegacyChannelConfig,
 
        // Track the previous `ChannelConfig` so that we can continue forwarding HTLCs that were
@@ -832,7 +832,7 @@ macro_rules! secp_check {
        };
 }
 
-impl<Signer: Sign> Channel<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
        /// Returns the value to use for `holder_max_htlc_value_in_flight_msat` as a percentage of the
        /// `channel_value_satoshis` in msat, set through
        /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`]
@@ -877,15 +877,29 @@ impl<Signer: Sign> Channel<Signer> {
                self.channel_transaction_parameters.opt_anchors.is_some()
        }
 
-       fn get_initial_channel_type(config: &UserConfig) -> ChannelTypeFeatures {
+       fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
                // The default channel type (ie the first one we try) depends on whether the channel is
                // public - if it is, we just go with `only_static_remotekey` as it's the only option
                // available. If it's private, we first try `scid_privacy` as it provides better privacy
-               // with no other changes, and fall back to `only_static_remotekey`
+               // with no other changes, and fall back to `only_static_remotekey`.
                let mut ret = ChannelTypeFeatures::only_static_remote_key();
-               if !config.channel_handshake_config.announced_channel && config.channel_handshake_config.negotiate_scid_privacy {
+               if !config.channel_handshake_config.announced_channel &&
+                       config.channel_handshake_config.negotiate_scid_privacy &&
+                       their_features.supports_scid_privacy() {
                        ret.set_scid_privacy_required();
                }
+
+               // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
+               // set it now. If they don't understand it, we'll fall back to our default of
+               // `only_static_remotekey`.
+               #[cfg(anchors)]
+               { // Attributes are not allowed on if expressions on our current MSRV of 1.41.
+                       if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
+                               their_features.supports_anchors_zero_fee_htlc_tx() {
+                               ret.set_anchors_zero_fee_htlc_tx_required();
+                       }
+               }
+
                ret
        }
 
@@ -898,7 +912,24 @@ impl<Signer: Sign> Channel<Signer> {
                        // We've exhausted our options
                        return Err(());
                }
-               self.channel_type = ChannelTypeFeatures::only_static_remote_key(); // We only currently support two types
+               // We support opening a few different types of channels. Try removing our additional
+               // features one by one until we've either arrived at our default or the counterparty has
+               // accepted one.
+               //
+               // Due to the order below, we may not negotiate `option_anchors_zero_fee_htlc_tx` if the
+               // counterparty doesn't support `option_scid_privacy`. Since `get_initial_channel_type`
+               // checks whether the counterparty supports every feature, this would only happen if the
+               // counterparty is advertising the feature, but rejecting channels proposing the feature for
+               // whatever reason.
+               if self.channel_type.supports_anchors_zero_fee_htlc_tx() {
+                       self.channel_type.clear_anchors_zero_fee_htlc_tx();
+                       assert!(self.channel_transaction_parameters.opt_non_zero_fee_anchors.is_none());
+                       self.channel_transaction_parameters.opt_anchors = None;
+               } else if self.channel_type.supports_scid_privacy() {
+                       self.channel_type.clear_scid_privacy();
+               } else {
+                       self.channel_type = ChannelTypeFeatures::only_static_remote_key();
+               }
                Ok(self.get_open_channel(chain_hash))
        }
 
@@ -912,8 +943,6 @@ impl<Signer: Sign> Channel<Signer> {
              SP::Target: SignerProvider<Signer = Signer>,
              F::Target: FeeEstimator,
        {
-               let opt_anchors = false; // TODO - should be based on features
-
                let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
                let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
                let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
@@ -939,10 +968,13 @@ impl<Signer: Sign> Channel<Signer> {
                        return Err(APIError::APIMisuseError { err: format!("Holder selected channel  reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
                }
 
+               let channel_type = Self::get_initial_channel_type(&config, their_features);
+               debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
+
                let feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
 
                let value_to_self_msat = channel_value_satoshis * 1000 - push_msat;
-               let commitment_tx_fee = Self::commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, opt_anchors);
+               let commitment_tx_fee = Self::commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, channel_type.requires_anchors_zero_fee_htlc_tx());
                if value_to_self_msat < commitment_tx_fee {
                        return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) });
                }
@@ -1044,7 +1076,7 @@ impl<Signer: Sign> Channel<Signer> {
                                is_outbound_from_holder: true,
                                counterparty_parameters: None,
                                funding_outpoint: None,
-                               opt_anchors: if opt_anchors { Some(()) } else { None },
+                               opt_anchors: if channel_type.requires_anchors_zero_fee_htlc_tx() { Some(()) } else { None },
                                opt_non_zero_fee_anchors: None
                        },
                        funding_transaction: None,
@@ -1077,7 +1109,7 @@ impl<Signer: Sign> Channel<Signer> {
                        #[cfg(any(test, fuzzing))]
                        historical_inbound_htlc_fulfills: HashSet::new(),
 
-                       channel_type: Self::get_initial_channel_type(&config),
+                       channel_type,
                        channel_keys_id,
                })
        }
@@ -1117,16 +1149,16 @@ impl<Signer: Sign> Channel<Signer> {
        /// Creates a new channel from a remote sides' request for one.
        /// Assumes chain_hash has already been checked and corresponds with what we expect!
        pub fn new_from_req<ES: Deref, SP: Deref, F: Deref, L: Deref>(
-               fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures,
-               msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L,
-               outbound_scid_alias: u64
+               fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
+               counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
+               their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig,
+               current_chain_height: u32, logger: &L, outbound_scid_alias: u64
        ) -> Result<Channel<Signer>, ChannelError>
                where ES::Target: EntropySource,
                          SP::Target: SignerProvider<Signer = Signer>,
                          F::Target: FeeEstimator,
                          L::Target: Logger,
        {
-               let opt_anchors = false; // TODO - should be based on features
                let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
 
                // First check the channel type is known, failing before we do anything else if we don't
@@ -1136,31 +1168,28 @@ impl<Signer: Sign> Channel<Signer> {
                                return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
                        }
 
-                       if channel_type.requires_unknown_bits() {
-                               return Err(ChannelError::Close("Channel Type field contains unknown bits".to_owned()));
+                       // We only support the channel types defined by the `ChannelManager` in
+                       // `provided_channel_type_features`. The channel type must always support
+                       // `static_remote_key`.
+                       if !channel_type.requires_static_remote_key() {
+                               return Err(ChannelError::Close("Channel Type was not understood - we require static remote key".to_owned()));
                        }
-
-                       // We currently only allow four channel types, so write it all out here - we allow
-                       // `only_static_remote_key` or `static_remote_key | zero_conf` in all contexts, and
-                       // further allow `static_remote_key | scid_privacy` or
-                       // `static_remote_key | scid_privacy | zero_conf`, if the channel is not
-                       // publicly announced.
-                       if *channel_type != ChannelTypeFeatures::only_static_remote_key() {
-                               if !channel_type.requires_scid_privacy() && !channel_type.requires_zero_conf() {
-                                       return Err(ChannelError::Close("Channel Type was not understood".to_owned()));
-                               }
-
-                               if channel_type.requires_scid_privacy() && announced_channel {
-                                       return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
-                               }
+                       // Make sure we support all of the features behind the channel type.
+                       if !channel_type.is_subset(our_supported_features) {
+                               return Err(ChannelError::Close("Channel Type contains unsupported features".to_owned()));
+                       }
+                       if channel_type.requires_scid_privacy() && announced_channel {
+                               return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
                        }
                        channel_type.clone()
                } else {
-                       ChannelTypeFeatures::from_counterparty_init(&their_features)
+                       let channel_type = ChannelTypeFeatures::from_init(&their_features);
+                       if channel_type != ChannelTypeFeatures::only_static_remote_key() {
+                               return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
+                       }
+                       channel_type
                };
-               if !channel_type.supports_static_remote_key() {
-                       return Err(ChannelError::Close("Channel Type was not understood - we require static remote key".to_owned()));
-               }
+               let opt_anchors = channel_type.supports_anchors_zero_fee_htlc_tx();
 
                let channel_keys_id = signer_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id);
                let holder_signer = signer_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id);
@@ -2130,7 +2159,11 @@ impl<Signer: Sign> Channel<Signer> {
                } else if their_features.supports_channel_type() {
                        // Assume they've accepted the channel type as they said they understand it.
                } else {
-                       self.channel_type = ChannelTypeFeatures::from_counterparty_init(&their_features)
+                       let channel_type = ChannelTypeFeatures::from_init(&their_features);
+                       if channel_type != ChannelTypeFeatures::only_static_remote_key() {
+                               return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
+                       }
+                       self.channel_type = channel_type;
                }
 
                let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
@@ -2394,7 +2427,14 @@ impl<Signer: Sign> Channel<Signer> {
        /// Handles a channel_ready message from our peer. If we've already sent our channel_ready
        /// and the channel is now usable (and public), this may generate an announcement_signatures to
        /// reply with.
-       pub fn channel_ready<L: Deref>(&mut self, msg: &msgs::ChannelReady, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock, logger: &L) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError> where L::Target: Logger {
+       pub fn channel_ready<NS: Deref, L: Deref>(
+               &mut self, msg: &msgs::ChannelReady, node_signer: &NS, genesis_block_hash: BlockHash,
+               user_config: &UserConfig, best_block: &BestBlock, logger: &L
+       ) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError>
+       where
+               NS::Target: NodeSigner,
+               L::Target: Logger
+       {
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
                        self.workaround_lnd_bug_4006 = Some(msg.clone());
                        return Err(ChannelError::Ignore("Peer sent channel_ready when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned()));
@@ -2448,7 +2488,7 @@ impl<Signer: Sign> Channel<Signer> {
 
                log_info!(logger, "Received channel_ready from peer for channel {}", log_bytes!(self.channel_id()));
 
-               Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block.height(), logger))
+               Ok(self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger))
        }
 
        /// Returns transaction if there is pending funding transaction that is yet to broadcast
@@ -3752,7 +3792,14 @@ impl<Signer: Sign> Channel<Signer> {
        /// Indicates that the latest ChannelMonitor update has been committed by the client
        /// successfully and we should restore normal operation. Returns messages which should be sent
        /// to the remote side.
-       pub fn monitor_updating_restored<L: Deref>(&mut self, logger: &L, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block_height: u32) -> MonitorRestoreUpdates where L::Target: Logger {
+       pub fn monitor_updating_restored<L: Deref, NS: Deref>(
+               &mut self, logger: &L, node_signer: &NS, genesis_block_hash: BlockHash,
+               user_config: &UserConfig, best_block_height: u32
+       ) -> MonitorRestoreUpdates
+       where
+               L::Target: Logger,
+               NS::Target: NodeSigner
+       {
                assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
                self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
 
@@ -3787,7 +3834,7 @@ impl<Signer: Sign> Channel<Signer> {
                        })
                } else { None };
 
-               let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block_height, logger);
+               let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block_height, logger);
 
                let mut accepted_htlcs = Vec::new();
                mem::swap(&mut accepted_htlcs, &mut self.monitor_pending_forwards);
@@ -3939,9 +3986,14 @@ impl<Signer: Sign> Channel<Signer> {
        /// `cargo doc --document-private-items`):
        /// [`super::channelmanager::ChannelManager::force_close_without_broadcasting_txn`] and
        /// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`].
-       pub fn channel_reestablish<L: Deref>(&mut self, msg: &msgs::ChannelReestablish, logger: &L,
-               node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock)
-       -> Result<ReestablishResponses, ChannelError> where L::Target: Logger {
+       pub fn channel_reestablish<L: Deref, NS: Deref>(
+               &mut self, msg: &msgs::ChannelReestablish, logger: &L, node_signer: &NS,
+               genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock
+       ) -> Result<ReestablishResponses, ChannelError>
+       where
+               L::Target: Logger,
+               NS::Target: NodeSigner
+       {
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
                        // While BOLT 2 doesn't indicate explicitly we should error this channel here, it
                        // almost certainly indicates we are going to end up out-of-sync in some way, so we
@@ -4005,7 +4057,7 @@ impl<Signer: Sign> Channel<Signer> {
                        })
                } else { None };
 
-               let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block.height(), logger);
+               let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger);
 
                if self.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 {
                        // If we're waiting on a monitor update, we shouldn't re-send any channel_ready's.
@@ -4977,9 +5029,14 @@ impl<Signer: Sign> Channel<Signer> {
        /// When a transaction is confirmed, we check whether it is or spends the funding transaction
        /// In the first case, we store the confirmation height and calculating the short channel id.
        /// In the second, we simply return an Err indicating we need to be force-closed now.
-       pub fn transactions_confirmed<L: Deref>(&mut self, block_hash: &BlockHash, height: u32,
-               txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, user_config: &UserConfig, logger: &L)
-       -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
+       pub fn transactions_confirmed<NS: Deref, L: Deref>(
+               &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData,
+               genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L
+       ) -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+       where
+               NS::Target: NodeSigner,
+               L::Target: Logger
+       {
                if let Some(funding_txo) = self.get_funding_txo() {
                        for &(index_in_block, tx) in txdata.iter() {
                                // Check if the transaction is the expected funding transaction, and if it is,
@@ -5025,7 +5082,7 @@ impl<Signer: Sign> Channel<Signer> {
                                        // may have already happened for this block).
                                        if let Some(channel_ready) = self.check_get_channel_ready(height) {
                                                log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id));
-                                               let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, height, logger);
+                                               let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger);
                                                return Ok((Some(channel_ready), announcement_sigs));
                                        }
                                }
@@ -5051,13 +5108,25 @@ impl<Signer: Sign> Channel<Signer> {
        ///
        /// May return some HTLCs (and their payment_hash) which have timed out and should be failed
        /// back.
-       pub fn best_block_updated<L: Deref>(&mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, node_pk: PublicKey, user_config: UserConfig, logger: &L)
-       -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
-               self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_pk, user_config)), logger)
+       pub fn best_block_updated<NS: Deref, L: Deref>(
+               &mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash,
+               node_signer: &NS, user_config: &UserConfig, logger: &L
+       ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+       where
+               NS::Target: NodeSigner,
+               L::Target: Logger
+       {
+               self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_signer, user_config)), logger)
        }
 
-       fn do_best_block_updated<L: Deref>(&mut self, height: u32, highest_header_time: u32, genesis_node_pk: Option<(BlockHash, PublicKey, UserConfig)>, logger: &L)
-       -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
+       fn do_best_block_updated<NS: Deref, L: Deref>(
+               &mut self, height: u32, highest_header_time: u32,
+               genesis_node_signer: Option<(BlockHash, &NS, &UserConfig)>, logger: &L
+       ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+       where
+               NS::Target: NodeSigner,
+               L::Target: Logger
+       {
                let mut timed_out_htlcs = Vec::new();
                // This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to
                // forward an HTLC when our counterparty should almost certainly just fail it for expiring
@@ -5078,8 +5147,8 @@ impl<Signer: Sign> Channel<Signer> {
                self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time);
 
                if let Some(channel_ready) = self.check_get_channel_ready(height) {
-                       let announcement_sigs = if let Some((genesis_block_hash, node_pk, user_config)) = genesis_node_pk {
-                               self.get_announcement_sigs(node_pk, genesis_block_hash, &user_config, height, logger)
+                       let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+                               self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
                        } else { None };
                        log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id));
                        return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs));
@@ -5119,8 +5188,8 @@ impl<Signer: Sign> Channel<Signer> {
                        return Err(ClosureReason::FundingTimedOut);
                }
 
-               let announcement_sigs = if let Some((genesis_block_hash, node_pk, user_config)) = genesis_node_pk {
-                       self.get_announcement_sigs(node_pk, genesis_block_hash, &user_config, height, logger)
+               let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+                       self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
                } else { None };
                Ok((None, timed_out_htlcs, announcement_sigs))
        }
@@ -5137,7 +5206,7 @@ impl<Signer: Sign> Channel<Signer> {
                        // larger. If we don't know that time has moved forward, we can just set it to the last
                        // time we saw and it will be ignored.
                        let best_time = self.update_time_counter;
-                       match self.do_best_block_updated(reorg_height, best_time, None, logger) {
+                       match self.do_best_block_updated(reorg_height, best_time, None::<(BlockHash, &&NodeSigner, &UserConfig)>, logger) {
                                Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => {
                                        assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?");
                                        assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?");
@@ -5337,7 +5406,9 @@ impl<Signer: Sign> Channel<Signer> {
        /// closing).
        ///
        /// This will only return ChannelError::Ignore upon failure.
-       fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash, user_config: &UserConfig) -> Result<msgs::UnsignedChannelAnnouncement, ChannelError> {
+       fn get_channel_announcement<NS: Deref>(
+               &self, node_signer: &NS, chain_hash: BlockHash, user_config: &UserConfig,
+       ) -> Result<msgs::UnsignedChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
                if !self.config.announced_channel {
                        return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned()));
                }
@@ -5345,6 +5416,8 @@ impl<Signer: Sign> Channel<Signer> {
                        return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned()));
                }
 
+               let node_id = node_signer.get_node_id(Recipient::Node)
+                       .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?;
                let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..];
 
                let msg = msgs::UnsignedChannelAnnouncement {
@@ -5361,8 +5434,14 @@ impl<Signer: Sign> Channel<Signer> {
                Ok(msg)
        }
 
-       fn get_announcement_sigs<L: Deref>(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block_height: u32, logger: &L)
-       -> Option<msgs::AnnouncementSignatures> where L::Target: Logger {
+       fn get_announcement_sigs<NS: Deref, L: Deref>(
+               &mut self, node_signer: &NS, genesis_block_hash: BlockHash, user_config: &UserConfig,
+               best_block_height: u32, logger: &L
+       ) -> Option<msgs::AnnouncementSignatures>
+       where
+               NS::Target: NodeSigner,
+               L::Target: Logger
+       {
                if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height {
                        return None;
                }
@@ -5381,14 +5460,21 @@ impl<Signer: Sign> Channel<Signer> {
                }
 
                log_trace!(logger, "Creating an announcement_signatures message for channel {}", log_bytes!(self.channel_id()));
-               let announcement = match self.get_channel_announcement(node_pk, genesis_block_hash, user_config) {
+               let announcement = match self.get_channel_announcement(node_signer, genesis_block_hash, user_config) {
                        Ok(a) => a,
-                       Err(_) => {
-                               log_trace!(logger, "Cannot create an announcement_signatures as channel is not public.");
+                       Err(e) => {
+                               log_trace!(logger, "{:?}", e);
                                return None;
                        }
                };
-               let (our_node_sig, our_bitcoin_sig) = match self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) {
+               let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) {
+                       Err(_) => {
+                               log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!");
+                               return None;
+                       },
+                       Ok(v) => v
+               };
+               let our_bitcoin_sig = match self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx) {
                        Err(_) => {
                                log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!");
                                return None;
@@ -5407,11 +5493,17 @@ impl<Signer: Sign> Channel<Signer> {
 
        /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are
        /// available.
-       fn sign_channel_announcement(&self, our_node_id: PublicKey, announcement: msgs::UnsignedChannelAnnouncement) -> Result<msgs::ChannelAnnouncement, ChannelError> {
+       fn sign_channel_announcement<NS: Deref>(
+               &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement
+       ) -> Result<msgs::ChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
                if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs {
-                       let were_node_one = announcement.node_id_1 == our_node_id;
+                       let our_node_key = node_signer.get_node_id(Recipient::Node)
+                               .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?;
+                       let were_node_one = announcement.node_id_1 == our_node_key;
 
-                       let (our_node_sig, our_bitcoin_sig) = self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx)
+                       let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement))
+                               .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?;
+                       let our_bitcoin_sig = self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx)
                                .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?;
                        Ok(msgs::ChannelAnnouncement {
                                node_signature_1: if were_node_one { our_node_sig } else { their_node_sig },
@@ -5428,8 +5520,11 @@ impl<Signer: Sign> Channel<Signer> {
        /// Processes an incoming announcement_signatures message, providing a fully-signed
        /// channel_announcement message which we can broadcast and storing our counterparty's
        /// signatures for later reconstruction/rebroadcast of the channel_announcement.
-       pub fn announcement_signatures(&mut self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, msg: &msgs::AnnouncementSignatures, user_config: &UserConfig) -> Result<msgs::ChannelAnnouncement, ChannelError> {
-               let announcement = self.get_channel_announcement(our_node_id.clone(), chain_hash, user_config)?;
+       pub fn announcement_signatures<NS: Deref>(
+               &mut self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32,
+               msg: &msgs::AnnouncementSignatures, user_config: &UserConfig
+       ) -> Result<msgs::ChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
+               let announcement = self.get_channel_announcement(node_signer, chain_hash, user_config)?;
 
                let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]);
 
@@ -5450,20 +5545,22 @@ impl<Signer: Sign> Channel<Signer> {
                                "Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned()));
                }
 
-               self.sign_channel_announcement(our_node_id, announcement)
+               self.sign_channel_announcement(node_signer, announcement)
        }
 
        /// Gets a signed channel_announcement for this channel, if we previously received an
        /// announcement_signatures from our counterparty.
-       pub fn get_signed_channel_announcement(&self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig) -> Option<msgs::ChannelAnnouncement> {
+       pub fn get_signed_channel_announcement<NS: Deref>(
+               &self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig
+       ) -> Option<msgs::ChannelAnnouncement> where NS::Target: NodeSigner {
                if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height {
                        return None;
                }
-               let announcement = match self.get_channel_announcement(our_node_id.clone(), chain_hash, user_config) {
+               let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) {
                        Ok(res) => res,
                        Err(_) => return None,
                };
-               match self.sign_channel_announcement(our_node_id, announcement) {
+               match self.sign_channel_announcement(node_signer, announcement) {
                        Ok(res) => Some(res),
                        Err(_) => None,
                }
@@ -6036,7 +6133,7 @@ impl Readable for AnnouncementSigsState {
        }
 }
 
-impl<Signer: Sign> Writeable for Channel<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been
                // called.
@@ -6331,13 +6428,13 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
 }
 
 const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<'a, 'b, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32)> for Channel<<SP::Target as SignerProvider>::Signer>
+impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> for Channel<<SP::Target as SignerProvider>::Signer>
                where
                        ES::Target: EntropySource,
                        SP::Target: SignerProvider
 {
-       fn read<R : io::Read>(reader: &mut R, args: (&'a ES, &'b SP, u32)) -> Result<Self, DecodeError> {
-               let (entropy_source, signer_provider, serialized_height) = args;
+       fn read<R : io::Read>(reader: &mut R, args: (&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)) -> Result<Self, DecodeError> {
+               let (entropy_source, signer_provider, serialized_height, our_supported_features) = args;
                let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
 
                // `user_id` used to be a single u64 value. In order to remain backwards compatible with
@@ -6653,17 +6750,12 @@ impl<'a, 'b, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32)> for Chann
                }
 
                let chan_features = channel_type.as_ref().unwrap();
-               if chan_features.supports_unknown_bits() || chan_features.requires_unknown_bits() {
+               if !chan_features.is_subset(our_supported_features) {
                        // If the channel was written by a new version and negotiated with features we don't
                        // understand yet, refuse to read it.
                        return Err(DecodeError::UnknownRequiredFeature);
                }
 
-               if channel_parameters.opt_anchors.is_some() {
-                       // Relax this check when ChannelTypeFeatures supports anchors.
-                       return Err(DecodeError::InvalidValue);
-               }
-
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
 
@@ -6798,6 +6890,8 @@ mod tests {
        use hex;
        use crate::ln::PaymentHash;
        use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
+       #[cfg(anchors)]
+       use crate::ln::channel::InitFeatures;
        use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
        use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
        use crate::ln::features::ChannelTypeFeatures;
@@ -6807,22 +6901,19 @@ mod tests {
        use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
        use crate::chain::BestBlock;
        use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
-       use crate::chain::keysinterface::{BaseSign, InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
+       use crate::chain::keysinterface::{ChannelSigner, InMemorySigner, EntropySource, SignerProvider};
        use crate::chain::transaction::OutPoint;
        use crate::util::config::UserConfig;
        use crate::util::enforcing_trait_impls::EnforcingSigner;
        use crate::util::errors::APIError;
        use crate::util::test_utils;
        use crate::util::test_utils::OnGetShutdownScriptpubkey;
-       use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Scalar};
+       use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
        use bitcoin::secp256k1::ffi::Signature as FFISignature;
        use bitcoin::secp256k1::{SecretKey,PublicKey};
-       use bitcoin::secp256k1::ecdh::SharedSecret;
-       use bitcoin::secp256k1::ecdsa::RecoverableSignature;
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
        use bitcoin::hash_types::WPubkeyHash;
-       use bitcoin::bech32::u5;
        use bitcoin::PackedLockTime;
        use bitcoin::util::address::WitnessVersion;
        use crate::prelude::*;
@@ -6861,21 +6952,6 @@ mod tests {
                fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
        }
 
-       impl NodeSigner for Keys {
-               fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { panic!(); }
-
-               fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
-                       let secp_ctx = Secp256k1::signing_only();
-                       Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
-               }
-
-               fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result<SharedSecret, ()> { panic!(); }
-
-               fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); }
-
-               fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
-       }
-
        impl SignerProvider for Keys {
                type Signer = InMemorySigner;
 
@@ -6979,7 +7055,7 @@ mod tests {
                // Make sure A's dust limit is as we expect.
                let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
-               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
 
                // Node B --> Node A: accept channel, explicitly setting B's dust limit.
                let mut accept_channel_msg = node_b_chan.accept_inbound_channel(0);
@@ -7097,7 +7173,7 @@ mod tests {
                // Create Node B's channel by receiving Node A's open_channel message
                let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
-               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
 
                // Node B --> Node A: accept channel
                let accept_channel_msg = node_b_chan.accept_inbound_channel(0);
@@ -7179,12 +7255,12 @@ mod tests {
                // Test that `new_from_req` creates a channel with the correct value for
                // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
                // which is set to the lower bound - 1 (2%) of the `channel_value`.
-               let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
+               let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_2_percent), &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
                let chan_3_value_msat = chan_3.channel_value_satoshis * 1000;
                assert_eq!(chan_3.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64);
 
                // Test with the upper bound - 1 of valid values (99%).
-               let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
+               let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_99_percent), &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
                let chan_4_value_msat = chan_4.channel_value_satoshis * 1000;
                assert_eq!(chan_4.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64);
 
@@ -7203,14 +7279,14 @@ mod tests {
 
                // Test that `new_from_req` uses the lower bound of the configurable percentage values (1%)
                // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
-               let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
+               let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_0_percent), &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
                let chan_7_value_msat = chan_7.channel_value_satoshis * 1000;
                assert_eq!(chan_7.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64);
 
                // Test that `new_from_req` uses the upper bound of the configurable percentage values
                // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
                // than 100.
-               let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
+               let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_101_percent), &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
                let chan_8_value_msat = chan_8.channel_value_satoshis * 1000;
                assert_eq!(chan_8.holder_max_htlc_value_in_flight_msat, chan_8_value_msat);
        }
@@ -7260,7 +7336,7 @@ mod tests {
                inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32;
 
                if outbound_selected_channel_reserve_perc + inbound_selected_channel_reserve_perc < 1.0 {
-                       let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
+                       let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
 
                        let expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) as u64);
 
@@ -7268,7 +7344,7 @@ mod tests {
                        assert_eq!(chan_inbound_node.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve);
                } else {
                        // Channel Negotiations failed
-                       let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
+                       let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
                        assert!(result.is_err());
                }
        }
@@ -7330,7 +7406,7 @@ mod tests {
                use bitcoin::hashes::hex::FromHex;
                use bitcoin::hash_types::Txid;
                use bitcoin::secp256k1::Message;
-               use crate::chain::keysinterface::BaseSign;
+               use crate::chain::keysinterface::EcdsaChannelSigner;
                use crate::ln::PaymentPreimage;
                use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys};
                use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
@@ -7344,7 +7420,6 @@ mod tests {
 
                let mut signer = InMemorySigner::new(
                        &secp_ctx,
-                       SecretKey::from_slice(&hex::decode("4242424242424242424242424242424242424242424242424242424242424242").unwrap()[..]).unwrap(),
                        SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(),
                        SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
                        SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
@@ -8088,7 +8163,164 @@ mod tests {
                open_channel_msg.channel_type = Some(channel_type_features);
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
                let res = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider,
-                       node_b_node_id, &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42);
+                       node_b_node_id, &channelmanager::provided_channel_type_features(&config),
+                       &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42);
                assert!(res.is_ok());
        }
+
+       #[cfg(anchors)]
+       #[test]
+       fn test_supports_anchors_zero_htlc_tx_fee() {
+               // Tests that if both sides support and negotiate `anchors_zero_fee_htlc_tx`, it is the
+               // resulting `channel_type`.
+               let secp_ctx = Secp256k1::new();
+               let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+               let logger = test_utils::TestLogger::new();
+
+               let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+               let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+               let mut config = UserConfig::default();
+               config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+
+               // It is not enough for just the initiator to signal `option_anchors_zero_fee_htlc_tx`, both
+               // need to signal it.
+               let channel_a = Channel::<EnforcingSigner>::new_outbound(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+                       &channelmanager::provided_init_features(&UserConfig::default()), 10000000, 100000, 42,
+                       &config, 0, 42
+               ).unwrap();
+               assert!(!channel_a.channel_type.supports_anchors_zero_fee_htlc_tx());
+
+               let mut expected_channel_type = ChannelTypeFeatures::empty();
+               expected_channel_type.set_static_remote_key_required();
+               expected_channel_type.set_anchors_zero_fee_htlc_tx_required();
+
+               let channel_a = Channel::<EnforcingSigner>::new_outbound(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+                       &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+               ).unwrap();
+
+               let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+               let channel_b = Channel::<EnforcingSigner>::new_from_req(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+                       &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config),
+                       &open_channel_msg, 7, &config, 0, &&logger, 42
+               ).unwrap();
+
+               assert_eq!(channel_a.channel_type, expected_channel_type);
+               assert_eq!(channel_b.channel_type, expected_channel_type);
+       }
+
+       #[cfg(anchors)]
+       #[test]
+       fn test_rejects_implicit_simple_anchors() {
+               // Tests that if `option_anchors` is being negotiated implicitly through the intersection of
+               // each side's `InitFeatures`, it is rejected.
+               let secp_ctx = Secp256k1::new();
+               let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+               let logger = test_utils::TestLogger::new();
+
+               let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+               let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+               let config = UserConfig::default();
+
+               // See feature bit assignments: https://github.com/lightning/bolts/blob/master/09-features.md
+               let static_remote_key_required: u64 = 1 << 12;
+               let simple_anchors_required: u64 = 1 << 20;
+               let raw_init_features = static_remote_key_required | simple_anchors_required;
+               let init_features_with_simple_anchors = InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec());
+
+               let channel_a = Channel::<EnforcingSigner>::new_outbound(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+                       &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+               ).unwrap();
+
+               // Set `channel_type` to `None` to force the implicit feature negotiation.
+               let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+               open_channel_msg.channel_type = None;
+
+               // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts
+               // `static_remote_key`, it will fail the channel.
+               let channel_b = Channel::<EnforcingSigner>::new_from_req(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+                       &channelmanager::provided_channel_type_features(&config), &init_features_with_simple_anchors,
+                       &open_channel_msg, 7, &config, 0, &&logger, 42
+               );
+               assert!(channel_b.is_err());
+       }
+
+       #[cfg(anchors)]
+       #[test]
+       fn test_rejects_simple_anchors_channel_type() {
+               // Tests that if `option_anchors` is being negotiated through the `channel_type` feature,
+               // it is rejected.
+               let secp_ctx = Secp256k1::new();
+               let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+               let logger = test_utils::TestLogger::new();
+
+               let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+               let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+               let config = UserConfig::default();
+
+               // See feature bit assignments: https://github.com/lightning/bolts/blob/master/09-features.md
+               let static_remote_key_required: u64 = 1 << 12;
+               let simple_anchors_required: u64 = 1 << 20;
+               let simple_anchors_raw_features = static_remote_key_required | simple_anchors_required;
+               let simple_anchors_init = InitFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec());
+               let simple_anchors_channel_type = ChannelTypeFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec());
+               assert!(simple_anchors_init.requires_unknown_bits());
+               assert!(simple_anchors_channel_type.requires_unknown_bits());
+
+               // First, we'll try to open a channel between A and B where A requests a channel type for
+               // the original `option_anchors` feature (non zero fee htlc tx). This should be rejected by
+               // B as it's not supported by LDK.
+               let channel_a = Channel::<EnforcingSigner>::new_outbound(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+                       &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+               ).unwrap();
+
+               let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+               open_channel_msg.channel_type = Some(simple_anchors_channel_type.clone());
+
+               let res = Channel::<EnforcingSigner>::new_from_req(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+                       &channelmanager::provided_channel_type_features(&config), &simple_anchors_init,
+                       &open_channel_msg, 7, &config, 0, &&logger, 42
+               );
+               assert!(res.is_err());
+
+               // Then, we'll try to open another channel where A requests a channel type for
+               // `anchors_zero_fee_htlc_tx`. B is malicious and tries to downgrade the channel type to the
+               // original `option_anchors` feature, which should be rejected by A as it's not supported by
+               // LDK.
+               let mut channel_a = Channel::<EnforcingSigner>::new_outbound(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &simple_anchors_init,
+                       10000000, 100000, 42, &config, 0, 42
+               ).unwrap();
+
+               let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+
+               let channel_b = Channel::<EnforcingSigner>::new_from_req(
+                       &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+                       &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config),
+                       &open_channel_msg, 7, &config, 0, &&logger, 42
+               ).unwrap();
+
+               let mut accept_channel_msg = channel_b.get_accept_channel_message();
+               accept_channel_msg.channel_type = Some(simple_anchors_channel_type.clone());
+
+               let res = channel_a.accept_channel(
+                       &accept_channel_msg, &config.channel_handshake_limits, &simple_anchors_init
+               );
+               assert!(res.is_err());
+       }
 }
index 5b312f04e4a13ba987539a8bde2481f42cd20550..b2a23c7c1d44cbdf03137263c663acaa285774c1 100644 (file)
@@ -26,12 +26,10 @@ use bitcoin::network::constants::Network;
 
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::{BlockHash, Txid};
 
 use bitcoin::secp256k1::{SecretKey,PublicKey};
 use bitcoin::secp256k1::Secp256k1;
-use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::{LockTime, secp256k1, Sequence};
 
 use crate::chain;
@@ -47,7 +45,7 @@ use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, No
 #[cfg(any(feature = "_test_utils", test))]
 use crate::ln::features::InvoiceFeatures;
 use crate::routing::gossip::NetworkGraph;
-use crate::routing::router::{DefaultRouter, InFlightHtlcs, PaymentParameters, Route, RouteHop, RoutePath, Router};
+use crate::routing::router::{DefaultRouter, InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, RoutePath, Router};
 use crate::routing::scoring::ProbabilisticScorer;
 use crate::ln::msgs;
 use crate::ln::onion_utils;
@@ -55,9 +53,9 @@ use crate::ln::onion_utils::HTLCFailReason;
 use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
 #[cfg(test)]
 use crate::ln::outbound_payment;
-use crate::ln::outbound_payment::{OutboundPayments, PendingOutboundPayment};
+use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, Retry};
 use crate::ln::wire::Encode;
-use crate::chain::keysinterface::{EntropySource, KeysManager, NodeSigner, Recipient, Sign, SignerProvider};
+use crate::chain::keysinterface::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, ChannelSigner};
 use crate::util::config::{UserConfig, ChannelConfig};
 use crate::util::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
 use crate::util::events;
@@ -291,6 +289,25 @@ struct ReceiveError {
        msg: &'static str,
 }
 
+/// This enum is used to specify which error data to send to peers when failing back an HTLC
+/// using [`ChannelManager::fail_htlc_backwards_with_reason`].
+///
+/// For more info on failure codes, see <https://github.com/lightning/bolts/blob/master/04-onion-routing.md#failure-messages>.
+#[derive(Clone, Copy)]
+pub enum FailureCode {
+       /// We had a temporary error processing the payment. Useful if no other error codes fit
+       /// and you want to indicate that the payer may want to retry.
+       TemporaryNodeFailure             = 0x2000 | 2,
+       /// We have a required feature which was not in this onion. For example, you may require
+       /// some additional metadata that was not provided with this payment.
+       RequiredNodeFeatureMissing       = 0x4000 | 0x2000 | 3,
+       /// You may wish to use this when a `payment_preimage` is unknown, or the CLTV expiry of
+       /// the HTLC is too close to the current block height for safe handling.
+       /// Using this failure code in [`ChannelManager::fail_htlc_backwards_with_reason`] is
+       /// equivalent to calling [`ChannelManager::fail_htlc_backwards`].
+       IncorrectOrUnknownPaymentDetails = 0x4000 | 15,
+}
+
 type ShutdownResult = (Option<(OutPoint, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash, PublicKey, [u8; 32])>);
 
 /// Error type returned across the peer_state mutex boundary. When an Err is generated for a
@@ -390,7 +407,7 @@ impl MsgHandleErrInternal {
 /// Event::PendingHTLCsForwardable for the API guidelines indicating how long should be waited).
 /// This provides some limited amount of privacy. Ideally this would range from somewhere like one
 /// second to 30 seconds, but people expect lightning to be, you know, kinda fast, sadly.
-const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u64 = 100;
+pub(super) const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u64 = 100;
 
 /// For events which result in both a RevokeAndACK and a CommitmentUpdate, by default they should
 /// be sent in the order they appear in the return value, however sometimes the order needs to be
@@ -454,7 +471,7 @@ pub(crate) enum MonitorUpdateCompletionAction {
 }
 
 /// State we hold per-peer.
-pub(super) struct PeerState<Signer: Sign> {
+pub(super) struct PeerState<Signer: ChannelSigner> {
        /// `temporary_channel_id` or `channel_id` -> `channel`.
        ///
        /// Holds all channels where the peer is the counterparty. Once a channel has been assigned a
@@ -721,7 +738,6 @@ where
        #[cfg(not(test))]
        short_to_chan_info: FairRwLock<HashMap<u64, (PublicKey, [u8; 32])>>,
 
-       our_network_key: SecretKey,
        our_network_pubkey: PublicKey,
 
        inbound_payment_key: inbound_payment::ExpandedKey,
@@ -877,12 +893,12 @@ pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*7;
 pub(super) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6;
 
 /// Minimum CLTV difference between the current block height and received inbound payments.
-/// Invoices generated for payment to us must set their `min_final_cltv_expiry` field to at least
+/// Invoices generated for payment to us must set their `min_final_cltv_expiry_delta` field to at least
 /// this value.
 // Note that we fail if exactly HTLC_FAIL_BACK_BUFFER + 1 was used, so we need to add one for
 // any payments to succeed. Further, we don't want payments to fail if a block was found while
 // a payment was being routed, so we add an extra block to be safe.
-pub const MIN_FINAL_CLTV_EXPIRY: u32 = HTLC_FAIL_BACK_BUFFER + 3;
+pub const MIN_FINAL_CLTV_EXPIRY_DELTA: u16 = HTLC_FAIL_BACK_BUFFER as u16 + 3;
 
 // Check that our CLTV_EXPIRY is at least CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY + LATENCY_GRACE_PERIOD_BLOCKS,
 // ie that if the next-hop peer fails the HTLC within
@@ -1153,12 +1169,12 @@ macro_rules! handle_error {
                match $internal {
                        Ok(msg) => Ok(msg),
                        Err(MsgHandleErrInternal { err, chan_id, shutdown_finish }) => {
-                               #[cfg(debug_assertions)]
+                               #[cfg(any(feature = "_test_utils", test))]
                                {
                                        // In testing, ensure there are no deadlocks where the lock is already held upon
                                        // entering the macro.
-                                       assert!($self.pending_events.try_lock().is_ok());
-                                       assert!($self.per_peer_state.try_write().is_ok());
+                                       debug_assert!($self.pending_events.try_lock().is_ok());
+                                       debug_assert!($self.per_peer_state.try_write().is_ok());
                                }
 
                                let mut msg_events = Vec::with_capacity(2);
@@ -1193,7 +1209,7 @@ macro_rules! handle_error {
                                                let mut peer_state = peer_state_mutex.lock().unwrap();
                                                peer_state.pending_msg_events.append(&mut msg_events);
                                        }
-                                       #[cfg(debug_assertions)]
+                                       #[cfg(any(feature = "_test_utils", test))]
                                        {
                                                if let None = per_peer_state.get(&$counterparty_node_id) {
                                                        // This shouldn't occour in tests unless an unkown counterparty_node_id
@@ -1206,10 +1222,10 @@ macro_rules! handle_error {
                                                                => {
                                                                        assert_eq!(*data, expected_error_str);
                                                                        if let Some((err_channel_id, _user_channel_id)) = chan_id {
-                                                                               assert_eq!(*channel_id, err_channel_id);
+                                                                               debug_assert_eq!(*channel_id, err_channel_id);
                                                                        }
                                                                }
-                                                               _ => panic!("Unexpected event"),
+                                                               _ => debug_assert!(false, "Unexpected event"),
                                                        }
                                                }
                                        }
@@ -1457,8 +1473,7 @@ where
                        id_to_peer: Mutex::new(HashMap::new()),
                        short_to_chan_info: FairRwLock::new(HashMap::new()),
 
-                       our_network_key: node_signer.get_node_secret(Recipient::Node).unwrap(),
-                       our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &node_signer.get_node_secret(Recipient::Node).unwrap()),
+                       our_network_pubkey: node_signer.get_node_id(Recipient::Node).unwrap(),
                        secp_ctx,
 
                        inbound_payment_key: expanded_inbound_key,
@@ -1918,6 +1933,7 @@ where
                // final_expiry_too_soon
                // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
                // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
+               //
                // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
                // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
                // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
@@ -2017,7 +2033,9 @@ where
                        return_malformed_err!("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6);
                }
 
-               let shared_secret = SharedSecret::new(&msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key).secret_bytes();
+               let shared_secret = self.node_signer.ecdh(
+                       Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), None
+               ).unwrap().secret_bytes();
 
                if msg.onion_routing_packet.version != 0 {
                        //TODO: Spec doesn't indicate if we should only hash hop_data here (and in other
@@ -2266,7 +2284,7 @@ where
        }
        fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<<SP::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
                log_trace!(self.logger, "Generating channel update for channel {}", log_bytes!(chan.channel_id()));
-               let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).serialize()[..] < chan.get_counterparty_node_id().serialize()[..];
+               let were_node_one = self.our_network_pubkey.serialize()[..] < chan.get_counterparty_node_id().serialize()[..];
 
                let unsigned = msgs::UnsignedChannelUpdate {
                        chain_hash: self.genesis_hash,
@@ -2280,9 +2298,11 @@ where
                        fee_proportional_millionths: chan.get_fee_proportional_millionths(),
                        excess_data: Vec::new(),
                };
-
-               let msg_hash = Sha256dHash::hash(&unsigned.encode()[..]);
-               let sig = self.secp_ctx.sign_ecdsa(&hash_to_message!(&msg_hash[..]), &self.our_network_key);
+               // Panic on failure to signal LDK should be restarted to retry signing the `ChannelUpdate`.
+               // If we returned an error and the `node_signer` cannot provide a signature for whatever
+               // reason`, we wouldn't be able to receive inbound payments through the corresponding
+               // channel.
+               let sig = self.node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&unsigned)).unwrap();
 
                Ok(msgs::ChannelUpdate {
                        signature: sig,
@@ -2446,6 +2466,18 @@ where
                                self.send_payment_along_path(path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv))
        }
 
+       /// Similar to [`ChannelManager::send_payment`], but will automatically find a route based on
+       /// `route_params` and retry failed payment paths based on `retry_strategy`.
+       pub fn send_payment_with_retry(&self, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<(), PaymentSendFailure> {
+               let best_block_height = self.best_block.read().unwrap().height();
+               self.pending_outbound_payments
+                       .send_payment(payment_hash, payment_secret, payment_id, retry_strategy, route_params,
+                               &self.router, self.list_usable_channels(), self.compute_inflight_htlcs(),
+                               &self.entropy_source, &self.node_signer, best_block_height,
+                               |path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv|
+                               self.send_payment_along_path(path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv))
+       }
+
        #[cfg(test)]
        fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
@@ -2457,7 +2489,7 @@ where
        #[cfg(test)]
        pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, payment_secret: Option<PaymentSecret>, payment_id: PaymentId, route: &Route) -> Result<Vec<[u8; 32]>, PaymentSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
-               self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, payment_secret, payment_id, route, &self.entropy_source, best_block_height)
+               self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, payment_secret, payment_id, route, Retry::Attempts(0), &self.entropy_source, best_block_height)
        }
 
 
@@ -2923,9 +2955,9 @@ where
                                                                                        }
                                                                                }
                                                                                if let PendingHTLCRouting::Forward { onion_packet, .. } = routing {
-                                                                                       let phantom_secret_res = self.node_signer.get_node_secret(Recipient::PhantomNode);
-                                                                                       if phantom_secret_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.genesis_hash) {
-                                                                                               let phantom_shared_secret = SharedSecret::new(&onion_packet.public_key.unwrap(), &phantom_secret_res.unwrap()).secret_bytes();
+                                                                                       let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode);
+                                                                                       if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.genesis_hash) {
+                                                                                               let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
                                                                                                let next_hop = match onion_utils::decode_next_payment_hop(phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac, payment_hash) {
                                                                                                        Ok(res) => res,
                                                                                                        Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
@@ -3181,13 +3213,23 @@ where
                                                                                match claimable_htlc.onion_payload {
                                                                                        OnionPayload::Invoice { .. } => {
                                                                                                let payment_data = payment_data.unwrap();
-                                                                                               let payment_preimage = match inbound_payment::verify(payment_hash, &payment_data, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, &self.inbound_payment_key, &self.logger) {
-                                                                                                       Ok(payment_preimage) => payment_preimage,
+                                                                                               let (payment_preimage, min_final_cltv_expiry_delta) = match inbound_payment::verify(payment_hash, &payment_data, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, &self.inbound_payment_key, &self.logger) {
+                                                                                                       Ok(result) => result,
                                                                                                        Err(()) => {
+                                                                                                               log_trace!(self.logger, "Failing new HTLC with payment_hash {} as payment verification failed", log_bytes!(payment_hash.0));
                                                                                                                fail_htlc!(claimable_htlc, payment_hash);
                                                                                                                continue
                                                                                                        }
                                                                                                };
+                                                                                               if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta {
+                                                                                                       let expected_min_expiry_height = (self.current_best_block().height() + min_final_cltv_expiry_delta as u32) as u64;
+                                                                                                       if (cltv_expiry as u64) < expected_min_expiry_height {
+                                                                                                               log_trace!(self.logger, "Failing new HTLC with payment_hash {} as its CLTV expiry was too soon (had {}, earliest expected {})",
+                                                                                                                       log_bytes!(payment_hash.0), cltv_expiry, expected_min_expiry_height);
+                                                                                                               fail_htlc!(claimable_htlc, payment_hash);
+                                                                                                               continue;
+                                                                                                       }
+                                                                                               }
                                                                                                check_total_value!(payment_data, payment_preimage);
                                                                                        },
                                                                                        OnionPayload::Spontaneous(preimage) => {
@@ -3250,6 +3292,12 @@ where
                        }
                }
 
+               let best_block_height = self.best_block.read().unwrap().height();
+               self.pending_outbound_payments.check_retry_payments(&self.router, || self.list_usable_channels(),
+                       || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.logger,
+                       |path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv|
+                       self.send_payment_along_path(path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv));
+
                for (htlc_source, payment_hash, failure_reason, destination) in failed_forwards.drain(..) {
                        self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination);
                }
@@ -3472,21 +3520,40 @@ where
        /// [`events::Event::PaymentClaimed`] events even for payments you intend to fail, especially on
        /// startup during which time claims that were in-progress at shutdown may be replayed.
        pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) {
+               self.fail_htlc_backwards_with_reason(payment_hash, &FailureCode::IncorrectOrUnknownPaymentDetails);
+       }
+
+       /// This is a variant of [`ChannelManager::fail_htlc_backwards`] that allows you to specify the
+       /// reason for the failure.
+       ///
+       /// See [`FailureCode`] for valid failure codes.
+       pub fn fail_htlc_backwards_with_reason(&self, payment_hash: &PaymentHash, failure_code: &FailureCode) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
 
                let removed_source = self.claimable_payments.lock().unwrap().claimable_htlcs.remove(payment_hash);
                if let Some((_, mut sources)) = removed_source {
                        for htlc in sources.drain(..) {
-                               let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec();
-                               htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height().to_be_bytes());
+                               let reason = self.get_htlc_fail_reason_from_failure_code(failure_code, &htlc);
                                let source = HTLCSource::PreviousHopData(htlc.prev_hop);
-                               let reason = HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data);
                                let receiver = HTLCDestination::FailedPayment { payment_hash: *payment_hash };
                                self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver);
                        }
                }
        }
 
+       /// Gets error data to form an [`HTLCFailReason`] given a [`FailureCode`] and [`ClaimableHTLC`].
+       fn get_htlc_fail_reason_from_failure_code(&self, failure_code: &FailureCode, htlc: &ClaimableHTLC) -> HTLCFailReason {
+               match failure_code {
+                       FailureCode::TemporaryNodeFailure => HTLCFailReason::from_failure_code(*failure_code as u16),
+                       FailureCode::RequiredNodeFeatureMissing => HTLCFailReason::from_failure_code(*failure_code as u16),
+                       FailureCode::IncorrectOrUnknownPaymentDetails => {
+                               let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec();
+                               htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height().to_be_bytes());
+                               HTLCFailReason::reason(*failure_code as u16, htlc_msat_height_data)
+                       }
+               }
+       }
+
        /// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code
        /// that we want to return and a channel.
        ///
@@ -3565,7 +3632,7 @@ where
        /// Fails an HTLC backwards to the sender of it to us.
        /// Note that we do not assume that channels corresponding to failed HTLCs are still available.
        fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) {
-               #[cfg(debug_assertions)]
+               #[cfg(any(feature = "_test_utils", test))]
                {
                        // Ensure that no peer state channel storage lock is not held when calling this
                        // function.
@@ -3574,7 +3641,7 @@ where
                        // this function with any `per_peer_state` peer lock aquired would.
                        let per_peer_state = self.per_peer_state.read().unwrap();
                        for (_, peer) in per_peer_state.iter() {
-                               assert!(peer.try_lock().is_ok());
+                               debug_assert!(peer.try_lock().is_ok());
                        }
                }
 
@@ -4060,7 +4127,7 @@ where
                                return;
                        }
 
-                       let updates = channel.get_mut().monitor_updating_restored(&self.logger, self.get_our_node_id(), self.genesis_hash, &self.default_configuration, self.best_block.read().unwrap().height());
+                       let updates = channel.get_mut().monitor_updating_restored(&self.logger, &self.node_signer, self.genesis_hash, &self.default_configuration, self.best_block.read().unwrap().height());
                        let channel_update = if updates.channel_ready.is_some() && channel.get().is_usable() {
                                // We only send a channel_update in the case where we are just now sending a
                                // channel_ready and the channel is in a usable state. We may re-send a
@@ -4196,7 +4263,7 @@ where
                let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                let mut channel = match Channel::new_from_req(&self.fee_estimator, &self.entropy_source, &self.signer_provider,
-                       counterparty_node_id.clone(), &peer_state.latest_features, msg, user_channel_id, &self.default_configuration,
+                       counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id, &self.default_configuration,
                        self.best_block.read().unwrap().height(), &self.logger, outbound_scid_alias)
                {
                        Err(e) => {
@@ -4397,7 +4464,7 @@ where
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
-                               let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().channel_ready(&msg, self.get_our_node_id(),
+                               let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().channel_ready(&msg, &self.node_signer,
                                        self.genesis_hash.clone(), &self.default_configuration, &self.best_block.read().unwrap(), &self.logger), chan);
                                if let Some(announcement_sigs) = announcement_sigs_opt {
                                        log_trace!(self.logger, "Sending announcement_signatures for channel {}", log_bytes!(chan.get().channel_id()));
@@ -4879,8 +4946,8 @@ where
 
                                peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement {
                                        msg: try_chan_entry!(self, chan.get_mut().announcement_signatures(
-                                               self.get_our_node_id(), self.genesis_hash.clone(),
-                                               self.best_block.read().unwrap().height(), msg, &self.default_configuration
+                                               &self.node_signer, self.genesis_hash.clone(), self.best_block.read().unwrap().height(),
+                                               msg, &self.default_configuration
                                        ), chan),
                                        // Note that announcement_signatures fails if the channel cannot be announced,
                                        // so get_channel_update_for_broadcast will never fail by the time we get here.
@@ -4951,7 +5018,7 @@ where
                                        // freed HTLCs to fail backwards. If in the future we no longer drop pending
                                        // add-HTLCs on disconnect, we may be handed HTLCs to fail backwards here.
                                        let responses = try_chan_entry!(self, chan.get_mut().channel_reestablish(
-                                               msg, &self.logger, self.our_network_pubkey.clone(), self.genesis_hash,
+                                               msg, &self.logger, &self.node_signer, self.genesis_hash,
                                                &self.default_configuration, &*self.best_block.read().unwrap()), chan);
                                        let mut channel_update = None;
                                        if let Some(msg) = responses.shutdown_msg {
@@ -5273,12 +5340,18 @@ where
        ///
        /// Errors if `min_value_msat` is greater than total bitcoin supply.
        ///
+       /// If `min_final_cltv_expiry_delta` is set to some value, then the payment will not be receivable
+       /// on versions of LDK prior to 0.0.114.
+       ///
        /// [`claim_funds`]: Self::claim_funds
        /// [`PaymentClaimable`]: events::Event::PaymentClaimable
        /// [`PaymentClaimable::payment_preimage`]: events::Event::PaymentClaimable::payment_preimage
        /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
-       pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<(PaymentHash, PaymentSecret), ()> {
-               inbound_payment::create(&self.inbound_payment_key, min_value_msat, invoice_expiry_delta_secs, &self.entropy_source, self.highest_seen_timestamp.load(Ordering::Acquire) as u64)
+       pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
+               min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()> {
+               inbound_payment::create(&self.inbound_payment_key, min_value_msat, invoice_expiry_delta_secs,
+                       &self.entropy_source, self.highest_seen_timestamp.load(Ordering::Acquire) as u64,
+                       min_final_cltv_expiry_delta)
        }
 
        /// Legacy version of [`create_inbound_payment`]. Use this method if you wish to share
@@ -5326,8 +5399,8 @@ where
        /// If you need exact expiry semantics, you should enforce them upon receipt of
        /// [`PaymentClaimable`].
        ///
-       /// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry`
-       /// set to at least [`MIN_FINAL_CLTV_EXPIRY`].
+       /// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry_delta`
+       /// set to at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
        ///
        /// Note that a malicious eavesdropper can intuit whether an inbound payment was created by
        /// `create_inbound_payment` or `create_inbound_payment_for_hash` based on runtime.
@@ -5339,10 +5412,16 @@ where
        ///
        /// Errors if `min_value_msat` is greater than total bitcoin supply.
        ///
+       /// If `min_final_cltv_expiry_delta` is set to some value, then the payment will not be receivable
+       /// on versions of LDK prior to 0.0.114.
+       ///
        /// [`create_inbound_payment`]: Self::create_inbound_payment
        /// [`PaymentClaimable`]: events::Event::PaymentClaimable
-       pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, ()> {
-               inbound_payment::create_from_hash(&self.inbound_payment_key, min_value_msat, payment_hash, invoice_expiry_delta_secs, self.highest_seen_timestamp.load(Ordering::Acquire) as u64)
+       pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>,
+               invoice_expiry_delta_secs: u32, min_final_cltv_expiry: Option<u16>) -> Result<PaymentSecret, ()> {
+               inbound_payment::create_from_hash(&self.inbound_payment_key, min_value_msat, payment_hash,
+                       invoice_expiry_delta_secs, self.highest_seen_timestamp.load(Ordering::Acquire) as u64,
+                       min_final_cltv_expiry)
        }
 
        /// Legacy version of [`create_inbound_payment_for_hash`]. Use this method if you wish to share
@@ -5630,7 +5709,7 @@ where
                        *best_block = BestBlock::new(header.prev_blockhash, new_height)
                }
 
-               self.do_chain_event(Some(new_height), |channel| channel.best_block_updated(new_height, header.time, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger));
+               self.do_chain_event(Some(new_height), |channel| channel.best_block_updated(new_height, header.time, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger));
        }
 }
 
@@ -5654,13 +5733,13 @@ where
                log_trace!(self.logger, "{} transactions included in block {} at height {} provided", txdata.len(), block_hash, height);
 
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
-               self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.genesis_hash.clone(), self.get_our_node_id(), &self.default_configuration, &self.logger)
+               self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger)
                        .map(|(a, b)| (a, Vec::new(), b)));
 
                let last_best_block_height = self.best_block.read().unwrap().height();
                if height < last_best_block_height {
                        let timestamp = self.highest_seen_timestamp.load(Ordering::Acquire);
-                       self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger));
+                       self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger));
                }
        }
 
@@ -5676,7 +5755,7 @@ where
 
                *self.best_block.write().unwrap() = BestBlock::new(block_hash, height);
 
-               self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger));
+               self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger));
 
                macro_rules! max_time {
                        ($timestamp: expr) => {
@@ -5787,7 +5866,7 @@ where
                                                                msg: announcement_sigs,
                                                        });
                                                        if let Some(height) = height_opt {
-                                                               if let Some(announcement) = channel.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash, height, &self.default_configuration) {
+                                                               if let Some(announcement) = channel.get_signed_channel_announcement(&self.node_signer, self.genesis_hash, height, &self.default_configuration) {
                                                                        pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement {
                                                                                msg: announcement,
                                                                                // Note that announcement_signatures fails if the channel cannot be announced,
@@ -6177,7 +6256,7 @@ where
                                        }
                                } else { true };
                                if retain && chan.get_counterparty_node_id() != *counterparty_node_id {
-                                       if let Some(msg) = chan.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone(), self.best_block.read().unwrap().height(), &self.default_configuration) {
+                                       if let Some(msg) = chan.get_signed_channel_announcement(&self.node_signer, self.genesis_hash.clone(), self.best_block.read().unwrap().height(), &self.default_configuration) {
                                                if let Ok(update_msg) = self.get_channel_update_for_broadcast(chan) {
                                                        pending_msg_events.push(events::MessageSendEvent::SendChannelAnnouncement {
                                                                node_id: *counterparty_node_id,
@@ -6267,7 +6346,7 @@ pub(crate) fn provided_channel_features(config: &UserConfig) -> ChannelFeatures
 /// Fetches the set of [`ChannelTypeFeatures`] flags which are provided by or required by
 /// [`ChannelManager`].
 pub(crate) fn provided_channel_type_features(config: &UserConfig) -> ChannelTypeFeatures {
-       ChannelTypeFeatures::from_counterparty_init(&provided_init_features(config))
+       ChannelTypeFeatures::from_init(&provided_init_features(config))
 }
 
 /// Fetches the set of [`InitFeatures`] flags which are provided by or required by
@@ -6288,6 +6367,12 @@ pub fn provided_init_features(_config: &UserConfig) -> InitFeatures {
        features.set_channel_type_optional();
        features.set_scid_privacy_optional();
        features.set_zero_conf_optional();
+       #[cfg(anchors)]
+       { // Attributes are not allowed on if expressions on our current MSRV of 1.41.
+               if _config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx {
+                       features.set_anchors_zero_fee_htlc_tx_optional();
+               }
+       }
        features
 }
 
@@ -7027,7 +7112,9 @@ where
                let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
                let mut channel_closures = Vec::new();
                for _ in 0..channel_count {
-                       let mut channel: Channel<<SP::Target as SignerProvider>::Signer> = Channel::read(reader, (&args.entropy_source, &args.signer_provider, best_block_height))?;
+                       let mut channel: Channel<<SP::Target as SignerProvider>::Signer> = Channel::read(reader, (
+                               &args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config)
+                       ))?;
                        let funding_txo = channel.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
                        funding_txo_set.insert(funding_txo.clone());
                        if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
@@ -7270,6 +7357,9 @@ where
                                                                hash_map::Entry::Vacant(entry) => {
                                                                        let path_fee = path.get_path_fees();
                                                                        entry.insert(PendingOutboundPayment::Retryable {
+                                                                               retry_strategy: Retry::Attempts(0),
+                                                                               attempts: PaymentAttempts::new(),
+                                                                               route_params: None,
                                                                                session_privs: [session_priv_bytes].iter().map(|a| *a).collect(),
                                                                                payment_hash: htlc.payment_hash,
                                                                                payment_secret,
@@ -7361,7 +7451,7 @@ where
                                                                payment_preimage: match pending_inbound_payments.get(&payment_hash) {
                                                                        Some(inbound_payment) => inbound_payment.payment_preimage,
                                                                        None => match inbound_payment::verify(payment_hash, &hop_data, 0, &expanded_inbound_key, &args.logger) {
-                                                                               Ok(payment_preimage) => payment_preimage,
+                                                                               Ok((payment_preimage, _)) => payment_preimage,
                                                                                Err(()) => {
                                                                                        log_error!(args.logger, "Failed to read claimable payment data for HTLC with payment hash {} - was not a pending inbound payment and didn't match our payment key", log_bytes!(payment_hash.0));
                                                                                        return Err(DecodeError::InvalidValue);
@@ -7386,11 +7476,10 @@ where
                        pending_events_read.append(&mut channel_closures);
                }
 
-               let our_network_key = match args.node_signer.get_node_secret(Recipient::Node) {
+               let our_network_pubkey = match args.node_signer.get_node_id(Recipient::Node) {
                        Ok(key) => key,
                        Err(()) => return Err(DecodeError::InvalidValue)
                };
-               let our_network_pubkey = PublicKey::from_secret_key(&secp_ctx, &our_network_key);
                if let Some(network_pubkey) = received_network_pubkey {
                        if network_pubkey != our_network_pubkey {
                                log_error!(args.logger, "Key that was generated does not match the existing key.");
@@ -7506,7 +7595,6 @@ where
 
                        probing_cookie_secret: probing_cookie_secret.unwrap(),
 
-                       our_network_key,
                        our_network_pubkey,
                        secp_ctx,
 
@@ -8311,6 +8399,42 @@ mod tests {
 
                nodes[1].node.handle_update_fee(&unkown_public_key, &update_fee_msg);
        }
+
+       #[cfg(anchors)]
+       #[test]
+       fn test_anchors_zero_fee_htlc_tx_fallback() {
+               // Tests that if both nodes support anchors, but the remote node does not want to accept
+               // anchor channels at the moment, an error it sent to the local node such that it can retry
+               // the channel without the anchors feature.
+               let chanmon_cfgs = create_chanmon_cfgs(2);
+               let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+               let mut anchors_config = test_default_channel_config();
+               anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+               anchors_config.manually_accept_inbound_channels = true;
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]);
+               let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+               nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None).unwrap();
+               let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+               assert!(open_channel_msg.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx());
+
+               nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+               let events = nodes[1].node.get_and_clear_pending_events();
+               match events[0] {
+                       Event::OpenChannelRequest { temporary_channel_id, .. } => {
+                               nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id()).unwrap();
+                       }
+                       _ => panic!("Unexpected event"),
+               }
+
+               let error_msg = get_err_msg!(nodes[1], nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &error_msg);
+
+               let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+               assert!(!open_channel_msg.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx());
+
+               check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed);
+       }
 }
 
 #[cfg(all(any(test, feature = "_test_utils"), feature = "_bench_unstable"))]
@@ -8463,7 +8587,7 @@ pub mod bench {
                                payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes());
                                payment_count += 1;
                                let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
-                               let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200).unwrap();
+                               let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap();
 
                                $node_a.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
                                let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap());
index a3c1b7f623d1f2a355516638e75432e61a04fa71..fe879a5688fedc806a137231899327ffaa5620fd 100644 (file)
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
 //! - `Keysend` - send funds to a node without an invoice
 //!     (see the [`Keysend` feature assignment proposal](https://github.com/lightning/bolts/issues/605#issuecomment-606679798) for more information).
+//! - `AnchorsZeroFeeHtlcTx` - requires/supports that commitment transactions include anchor outputs
+//!   and HTLC transactions are pre-signed with zero fee (see
+//!   [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md) for more
+//!   information).
 //!
 //! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md
 //! [messages]: crate::ln::msgs
@@ -122,7 +126,7 @@ mod sealed {
                // Byte 1
                VariableLengthOnion | StaticRemoteKey | PaymentSecret,
                // Byte 2
-               BasicMPP | Wumbo,
+               BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
                // Byte 3
                ShutdownAnySegwit,
                // Byte 4
@@ -138,7 +142,7 @@ mod sealed {
                // Byte 1
                VariableLengthOnion | StaticRemoteKey | PaymentSecret,
                // Byte 2
-               BasicMPP | Wumbo,
+               BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
                // Byte 3
                ShutdownAnySegwit,
                // Byte 4
@@ -176,7 +180,7 @@ mod sealed {
                // Byte 1
                StaticRemoteKey,
                // Byte 2
-               ,
+               AnchorsZeroFeeHtlcTx,
                // Byte 3
                ,
                // Byte 4
@@ -357,6 +361,9 @@ mod sealed {
        define_feature!(19, Wumbo, [InitContext, NodeContext],
                "Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required,
                supports_wumbo, requires_wumbo);
+       define_feature!(23, AnchorsZeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext],
+               "Feature flags for `option_anchors_zero_fee_htlc_tx`.", set_anchors_zero_fee_htlc_tx_optional,
+               set_anchors_zero_fee_htlc_tx_required, supports_anchors_zero_fee_htlc_tx, requires_anchors_zero_fee_htlc_tx);
        define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
                "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
                set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
@@ -505,10 +512,10 @@ impl InvoiceFeatures {
 }
 
 impl ChannelTypeFeatures {
-       /// Constructs the implicit channel type based on the common supported types between us and our
-       /// counterparty
-       pub(crate) fn from_counterparty_init(counterparty_init: &InitFeatures) -> Self {
-               let mut ret = counterparty_init.to_context_internal();
+       // Maps the relevant `InitFeatures` to `ChannelTypeFeatures`. Any unknown features to
+       // `ChannelTypeFeatures` are not included in the result.
+       pub(crate) fn from_init(init: &InitFeatures) -> Self {
+               let mut ret = init.to_context_internal();
                // ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
                // optional bits and then AND out the optional ones.
                for byte in ret.flags.iter_mut() {
@@ -678,6 +685,24 @@ impl<T: sealed::Context> Features<T> {
                        (byte & unknown_features) != 0
                })
        }
+
+       // Returns true if the features within `self` are a subset of the features within `other`.
+       pub(crate) fn is_subset(&self, other: &Self) -> bool {
+               for (idx, byte) in self.flags.iter().enumerate() {
+                       if let Some(other_byte) = other.flags.get(idx) {
+                               if byte & other_byte != *byte {
+                                       // `self` has bits set that `other` doesn't.
+                                       return false;
+                               }
+                       } else {
+                               if *byte > 0 {
+                                       // `self` has a non-zero byte that `other` doesn't.
+                                       return false;
+                               }
+                       }
+               }
+               true
+       }
 }
 
 impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -704,6 +729,18 @@ impl<T: sealed::Wumbo> Features<T> {
        }
 }
 
+impl<T: sealed::SCIDPrivacy> Features<T> {
+       pub(crate) fn clear_scid_privacy(&mut self) {
+               <T as sealed::SCIDPrivacy>::clear_bits(&mut self.flags);
+       }
+}
+
+impl<T: sealed::AnchorsZeroFeeHtlcTx> Features<T> {
+       pub(crate) fn clear_anchors_zero_fee_htlc_tx(&mut self) {
+               <T as sealed::AnchorsZeroFeeHtlcTx>::clear_bits(&mut self.flags);
+       }
+}
+
 #[cfg(test)]
 impl<T: sealed::UnknownFeature> Features<T> {
        pub(crate) fn unknown() -> Self {
@@ -808,6 +845,7 @@ mod tests {
                init_features.set_channel_type_optional();
                init_features.set_scid_privacy_optional();
                init_features.set_zero_conf_optional();
+               init_features.set_anchors_zero_fee_htlc_tx_optional();
 
                assert!(init_features.initial_routing_sync());
                assert!(!init_features.supports_upfront_shutdown_script());
@@ -826,7 +864,7 @@ mod tests {
                        assert_eq!(node_features.flags.len(), 7);
                        assert_eq!(node_features.flags[0], 0b00000010);
                        assert_eq!(node_features.flags[1], 0b01010001);
-                       assert_eq!(node_features.flags[2], 0b00001010);
+                       assert_eq!(node_features.flags[2], 0b10001010);
                        assert_eq!(node_features.flags[3], 0b00001000);
                        assert_eq!(node_features.flags[4], 0b10000000);
                        assert_eq!(node_features.flags[5], 0b10100000);
@@ -917,7 +955,7 @@ mod tests {
                // required-StaticRemoteKey ChannelTypeFeatures.
                let mut init_features = InitFeatures::empty();
                init_features.set_static_remote_key_optional();
-               let converted_features = ChannelTypeFeatures::from_counterparty_init(&init_features);
+               let converted_features = ChannelTypeFeatures::from_init(&init_features);
                assert_eq!(converted_features, ChannelTypeFeatures::only_static_remote_key());
                assert!(!converted_features.supports_any_optional_bits());
                assert!(converted_features.requires_static_remote_key());
index 3fbf1bb5f86d1cd8a2852c13936e57c9333031f2..868b38e3fdaf30d44b766286ca280208a4d36d9d 100644 (file)
@@ -61,17 +61,22 @@ pub fn confirm_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Tran
        connect_blocks(node, CHAN_CONFIRM_DEPTH - 1);
        scid
 }
-/// Mine a signle block containing the given transaction
+/// Mine a single block containing the given transaction
 pub fn mine_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
        let height = node.best_block_info().1 + 1;
        confirm_transaction_at(node, tx, height);
 }
+/// Mine a single block containing the given transactions
+pub fn mine_transactions<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction]) {
+       let height = node.best_block_info().1 + 1;
+       confirm_transactions_at(node, txn, height);
+}
 /// Mine the given transaction at the given height, mining blocks as required to build to that
 /// height
 ///
 /// Returns the SCID a channel confirmed in the given transaction will have, assuming the funding
 /// output is the 1st output in the transaction.
-pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) -> u64 {
+pub fn confirm_transactions_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction], conf_height: u32) -> u64 {
        let first_connect_height = node.best_block_info().1 + 1;
        assert!(first_connect_height <= conf_height);
        if conf_height > first_connect_height {
@@ -84,10 +89,15 @@ pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &T
        for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
                block.txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() });
        }
-       block.txdata.push(tx.clone());
+       for tx in txn {
+               block.txdata.push((*tx).clone());
+       }
        connect_block(node, &block);
        scid_utils::scid_from_parts(conf_height as u64, block.txdata.len() as u64 - 1, 0).unwrap()
 }
+pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) -> u64 {
+       confirm_transactions_at(node, &[tx], conf_height)
+}
 
 /// The possible ways we may notify a ChannelManager of a new block
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -1437,6 +1447,11 @@ macro_rules! get_payment_preimage_hash {
                }
        };
        ($dest_node: expr, $min_value_msat: expr) => {
+               {
+                       crate::get_payment_preimage_hash!($dest_node, $min_value_msat, None)
+               }
+       };
+       ($dest_node: expr, $min_value_msat: expr, $min_final_cltv_expiry_delta: expr) => {
                {
                        use bitcoin::hashes::Hash as _;
                        let mut payment_count = $dest_node.network_payment_count.borrow_mut();
@@ -1444,10 +1459,10 @@ macro_rules! get_payment_preimage_hash {
                        *payment_count += 1;
                        let payment_hash = $crate::ln::PaymentHash(
                                bitcoin::hashes::sha256::Hash::hash(&payment_preimage.0[..]).into_inner());
-                       let payment_secret = $dest_node.node.create_inbound_payment_for_hash(payment_hash, $min_value_msat, 7200).unwrap();
+                       let payment_secret = $dest_node.node.create_inbound_payment_for_hash(payment_hash, $min_value_msat, 7200, $min_final_cltv_expiry_delta).unwrap();
                        (payment_preimage, payment_hash, payment_secret)
                }
-       }
+       };
 }
 
 #[macro_export]
index fb95c122bf4a48d5d5008d18015480b60dae8b0b..371fcfa77642f0b55637733a649ab3f739f4b800 100644 (file)
@@ -17,7 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
 use crate::chain::channelmonitor;
 use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
 use crate::chain::transaction::OutPoint;
-use crate::chain::keysinterface::{BaseSign, EntropySource};
+use crate::chain::keysinterface::{ChannelSigner, EcdsaChannelSigner, EntropySource};
 use crate::ln::{PaymentPreimage, PaymentSecret, PaymentHash};
 use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT};
 use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
@@ -1246,7 +1246,7 @@ fn test_duplicate_htlc_different_direction_onchain() {
        let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 900_000);
 
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], 800_000);
-       let node_a_payment_secret = nodes[0].node.create_inbound_payment_for_hash(payment_hash, None, 7200).unwrap();
+       let node_a_payment_secret = nodes[0].node.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap();
        send_along_route_with_secret(&nodes[1], route, &[&[&nodes[0]]], 800_000, payment_hash, node_a_payment_secret);
 
        // Provide preimage to node 0 by claiming payment
@@ -4712,14 +4712,14 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
 
        let (our_payment_preimage, duplicate_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 900_000);
 
-       let payment_secret = nodes[3].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200).unwrap();
+       let payment_secret = nodes[3].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None).unwrap();
        // We reduce the final CLTV here by a somewhat arbitrary constant to keep it under the one-byte
        // script push size limit so that the below script length checks match
        // ACCEPTED_HTLC_SCRIPT_WEIGHT.
        let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
                .with_features(nodes[3].node.invoice_features());
-       let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 900000, TEST_FINAL_CLTV - 40);
-       send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 900000, duplicate_payment_hash, payment_secret);
+       let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 800_000, TEST_FINAL_CLTV - 40);
+       send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 800_000, duplicate_payment_hash, payment_secret);
 
        let commitment_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
        assert_eq!(commitment_txn[0].input.len(), 1);
@@ -4739,25 +4739,35 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
 
                check_spends!(node_txn[0], commitment_txn[0]);
                assert_eq!(node_txn[0].input.len(), 1);
+               assert_eq!(node_txn[0].output.len(), 1);
 
                if node_txn.len() > 2 {
                        check_spends!(node_txn[1], commitment_txn[0]);
                        assert_eq!(node_txn[1].input.len(), 1);
+                       assert_eq!(node_txn[1].output.len(), 1);
                        assert_eq!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
 
                        check_spends!(node_txn[2], commitment_txn[0]);
+                       assert_eq!(node_txn[2].input.len(), 1);
+                       assert_eq!(node_txn[2].output.len(), 1);
                        assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
                } else {
                        check_spends!(node_txn[1], commitment_txn[0]);
+                       assert_eq!(node_txn[1].input.len(), 1);
+                       assert_eq!(node_txn[1].output.len(), 1);
                        assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
                }
 
                assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
                assert_eq!(node_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
+               // Assign htlc_timeout_tx to the forwarded HTLC (with value ~800 sats). The received HTLC
+               // (with value 900 sats) will be claimed in the below `claim_funds` call.
                if node_txn.len() > 2 {
                        assert_eq!(node_txn[2].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
+                       htlc_timeout_tx = if node_txn[2].output[0].value < 900 { node_txn[2].clone() } else { node_txn[0].clone() };
+               } else {
+                       htlc_timeout_tx = if node_txn[0].output[0].value < 900 { node_txn[1].clone() } else { node_txn[0].clone() };
                }
-               htlc_timeout_tx = node_txn[0].clone();
        }
 
        nodes[2].node.claim_funds(our_payment_preimage);
@@ -4805,10 +4815,8 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        expect_payment_failed_with_update!(nodes[0], duplicate_payment_hash, false, chan_2.0.contents.short_channel_id, true);
 
        // Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C
-       // Note that the fee paid is effectively double as the HTLC value (including the nodes[1] fee
-       // and nodes[2] fee) is rounded down and then claimed in full.
        mine_transaction(&nodes[1], &htlc_success_txn[1]);
-       expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(196*2), true, true);
+       expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(196), true, true);
        let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        assert!(updates.update_add_htlcs.is_empty());
        assert!(updates.update_fail_htlcs.is_empty());
@@ -4925,30 +4933,30 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
        let (_, payment_hash_2, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit*1000);
        // 2nd HTLC:
-       send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_1, nodes[5].node.create_inbound_payment_for_hash(payment_hash_1, None, 7200).unwrap()); // not added < dust limit + HTLC tx fee
+       send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_1, nodes[5].node.create_inbound_payment_for_hash(payment_hash_1, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee
        // 3rd HTLC:
-       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_2, nodes[5].node.create_inbound_payment_for_hash(payment_hash_2, None, 7200).unwrap()); // not added < dust limit + HTLC tx fee
+       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_2, nodes[5].node.create_inbound_payment_for_hash(payment_hash_2, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee
        // 4th HTLC:
        let (_, payment_hash_3, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
        // 5th HTLC:
        let (_, payment_hash_4, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], 1000000);
        // 6th HTLC:
-       send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_3, nodes[5].node.create_inbound_payment_for_hash(payment_hash_3, None, 7200).unwrap());
+       send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_3, nodes[5].node.create_inbound_payment_for_hash(payment_hash_3, None, 7200, None).unwrap());
        // 7th HTLC:
-       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_4, nodes[5].node.create_inbound_payment_for_hash(payment_hash_4, None, 7200).unwrap());
+       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_4, nodes[5].node.create_inbound_payment_for_hash(payment_hash_4, None, 7200, None).unwrap());
 
        // 8th HTLC:
        let (_, payment_hash_5, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
        // 9th HTLC:
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit*1000);
-       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_5, nodes[5].node.create_inbound_payment_for_hash(payment_hash_5, None, 7200).unwrap()); // not added < dust limit + HTLC tx fee
+       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_5, nodes[5].node.create_inbound_payment_for_hash(payment_hash_5, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee
 
        // 10th HTLC:
        let (_, payment_hash_6, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
        // 11th HTLC:
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], 1000000);
-       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_6, nodes[5].node.create_inbound_payment_for_hash(payment_hash_6, None, 7200).unwrap());
+       send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_6, nodes[5].node.create_inbound_payment_for_hash(payment_hash_6, None, 7200, None).unwrap());
 
        // Double-check that six of the new HTLC were added
        // We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie,
@@ -6861,7 +6869,7 @@ fn test_user_configurable_csv_delay() {
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
        if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
-               &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), &open_channel, 0,
+               &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
                &low_our_to_self_config, 0, &nodes[0].logger, 42)
        {
                match error {
@@ -6893,7 +6901,7 @@ fn test_user_configurable_csv_delay() {
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
        if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
-               &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), &open_channel, 0,
+               &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
                &high_their_to_self_config, 0, &nodes[0].logger, 42)
        {
                match error {
@@ -6922,7 +6930,7 @@ fn test_check_htlc_underpaying() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(nodes[1].node.invoice_features());
        let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]);
-       let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200).unwrap();
+       let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None).unwrap();
        nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap();
        check_added_monitors!(nodes[0], 1);
 
@@ -7242,8 +7250,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
                assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
                assert_ne!(node_txn[1].input[0].previous_output, node_txn[2].input[0].previous_output);
 
-               assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
-               assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
+               assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
+               assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
 
                // node_txn[3] spends the revoked outputs from the revoked_htlc_txn (which only have one
                // output, checked above).
@@ -7917,7 +7925,7 @@ fn test_preimage_storage() {
        create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
 
        {
-               let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200).unwrap();
+               let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200, None).unwrap();
                let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
                nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
                check_added_monitors!(nodes[0], 1);
@@ -8023,7 +8031,7 @@ fn test_bad_secret_hash() {
 
        let random_payment_hash = PaymentHash([42; 32]);
        let random_payment_secret = PaymentSecret([43; 32]);
-       let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2).unwrap();
+       let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2, None).unwrap();
        let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
 
        // All the below cases should end up being handled exactly identically, so we macro the
@@ -9582,3 +9590,60 @@ fn accept_busted_but_better_fee() {
                _ => panic!("Unexpected event"),
        };
 }
+
+fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash: bool) {
+       let mut chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+       let min_final_cltv_expiry_delta = 120;
+       let final_cltv_expiry_delta = if valid_delta { min_final_cltv_expiry_delta + 2 } else {
+               min_final_cltv_expiry_delta - 2 };
+       let recv_value = 100_000;
+
+       create_chan_between_nodes(&nodes[0], &nodes[1]);
+
+       let payment_parameters = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id());
+       let (payment_hash, payment_preimage, payment_secret) = if use_user_hash {
+               let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1],
+                       Some(recv_value), Some(min_final_cltv_expiry_delta));
+               (payment_hash, payment_preimage, payment_secret)
+       } else {
+               let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(recv_value), 7200, Some(min_final_cltv_expiry_delta)).unwrap();
+               (payment_hash, nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(), payment_secret)
+       };
+       let route = get_route!(nodes[0], payment_parameters, recv_value, final_cltv_expiry_delta as u32).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
+       check_added_monitors!(nodes[0], 1);
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+       commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+       expect_pending_htlcs_forwardable!(nodes[1]);
+
+       if valid_delta {
+               expect_payment_claimable!(nodes[1], payment_hash, payment_secret, recv_value, if use_user_hash {
+                       None } else { Some(payment_preimage) }, nodes[1].node.get_our_node_id());
+
+               claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
+       } else {
+               expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]);
+
+               check_added_monitors!(nodes[1], 1);
+
+               let fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates.update_fail_htlcs[0]);
+               commitment_signed_dance!(nodes[0], nodes[1], fail_updates.commitment_signed, false, true);
+
+               expect_payment_failed!(nodes[0], payment_hash, true);
+       }
+}
+
+#[test]
+fn test_payment_with_custom_min_cltv_expiry_delta() {
+       do_payment_with_custom_min_final_cltv_expiry(false, false);
+       do_payment_with_custom_min_final_cltv_expiry(false, true);
+       do_payment_with_custom_min_final_cltv_expiry(true, false);
+       do_payment_with_custom_min_final_cltv_expiry(true, true);
+}
index 0c80ae7bb4ad32b55af832eb3f1e2911ec457fb6..0c6d6f2b804bccd8cfb651c24995bf4959998a91 100644 (file)
@@ -68,6 +68,8 @@ impl ExpandedKey {
 enum Method {
        LdkPaymentHash = 0,
        UserPaymentHash = 1,
+       LdkPaymentHashCustomFinalCltv = 2,
+       UserPaymentHashCustomFinalCltv = 3,
 }
 
 impl Method {
@@ -75,11 +77,18 @@ impl Method {
                match bits {
                        bits if bits == Method::LdkPaymentHash as u8 => Ok(Method::LdkPaymentHash),
                        bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash),
+                       bits if bits == Method::LdkPaymentHashCustomFinalCltv as u8 => Ok(Method::LdkPaymentHashCustomFinalCltv),
+                       bits if bits == Method::UserPaymentHashCustomFinalCltv as u8 => Ok(Method::UserPaymentHashCustomFinalCltv),
                        unknown => Err(unknown),
                }
        }
 }
 
+fn min_final_cltv_expiry_delta_from_metadata(bytes: [u8; METADATA_LEN]) -> u16 {
+       let expiry_bytes = &bytes[AMT_MSAT_LEN..];
+       u16::from_be_bytes([expiry_bytes[0], expiry_bytes[1]])
+}
+
 /// Equivalent to [`crate::ln::channelmanager::ChannelManager::create_inbound_payment`], but no
 /// `ChannelManager` is required. Useful for generating invoices for [phantom node payments] without
 /// a `ChannelManager`.
@@ -90,12 +99,21 @@ impl Method {
 ///
 /// `current_time` is a Unix timestamp representing the current time.
 ///
+/// Note that if `min_final_cltv_expiry_delta` is set to some value, then the payment will not be receivable
+/// on versions of LDK prior to 0.0.114.
+///
 /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
 /// [`NodeSigner::get_inbound_payment_key_material`]: crate::chain::keysinterface::NodeSigner::get_inbound_payment_key_material
-pub fn create<ES: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, entropy_source: &ES, current_time: u64) -> Result<(PaymentHash, PaymentSecret), ()>
+pub fn create<ES: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>,
+       invoice_expiry_delta_secs: u32, entropy_source: &ES, current_time: u64,
+       min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()>
        where ES::Target: EntropySource
 {
-       let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::LdkPaymentHash, invoice_expiry_delta_secs, current_time)?;
+       let metadata_bytes = construct_metadata_bytes(min_value_msat, if min_final_cltv_expiry_delta.is_some() {
+                       Method::LdkPaymentHashCustomFinalCltv
+               } else {
+                       Method::LdkPaymentHash
+               }, invoice_expiry_delta_secs, current_time, min_final_cltv_expiry_delta)?;
 
        let mut iv_bytes = [0 as u8; IV_LEN];
        let rand_bytes = entropy_source.get_secure_random_bytes();
@@ -117,9 +135,17 @@ pub fn create<ES: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>, invoic
 ///
 /// See [`create`] for information on the `keys` and `current_time` parameters.
 ///
+/// Note that if `min_final_cltv_expiry_delta` is set to some value, then the payment will not be receivable
+/// on versions of LDK prior to 0.0.114.
+///
 /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
-pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment_hash: PaymentHash, invoice_expiry_delta_secs: u32, current_time: u64) -> Result<PaymentSecret, ()> {
-       let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::UserPaymentHash, invoice_expiry_delta_secs, current_time)?;
+pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment_hash: PaymentHash,
+       invoice_expiry_delta_secs: u32, current_time: u64, min_final_cltv_expiry_delta: Option<u16>) -> Result<PaymentSecret, ()> {
+       let metadata_bytes = construct_metadata_bytes(min_value_msat, if min_final_cltv_expiry_delta.is_some() {
+                       Method::UserPaymentHashCustomFinalCltv
+               } else {
+                       Method::UserPaymentHash
+               }, invoice_expiry_delta_secs, current_time, min_final_cltv_expiry_delta)?;
 
        let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
        hmac.input(&metadata_bytes);
@@ -132,7 +158,8 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment
        Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
 }
 
-fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method, invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64) -> Result<[u8; METADATA_LEN], ()> {
+fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method,
+       invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option<u16>) -> Result<[u8; METADATA_LEN], ()> {
        if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
                return Err(());
        }
@@ -148,9 +175,27 @@ fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method, i
        // than two hours in the future.  Thus, we add two hours here as a buffer to ensure we
        // absolutely never fail a payment too early.
        // Note that we assume that received blocks have reasonably up-to-date timestamps.
-       let expiry_bytes = (highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200).to_be_bytes();
+       let expiry_timestamp = highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200;
+       let mut expiry_bytes = expiry_timestamp.to_be_bytes();
+
+       // `min_value_msat` should fit in (64 bits - 3 payment type bits =) 61 bits as an unsigned integer.
+       // This should leave us with a maximum value greater than the 21M BTC supply cap anyway.
+       if min_value_msat.is_some() && min_value_msat.unwrap() > ((1u64 << 61) - 1) { return Err(()); }
+
+       // `expiry_timestamp` should fit in (64 bits - 2 delta bytes =) 48 bits as an unsigned integer.
+       // Bitcoin's block header timestamps are actually `u32`s, so we're technically already limited to
+       // the much smaller maximum timestamp of `u32::MAX` for now, but we check the u64 `expiry_timestamp`
+       // for future-proofing.
+       if min_final_cltv_expiry_delta.is_some() && expiry_timestamp > ((1u64 << 48) - 1) { return Err(()); }
+
+       if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta {
+               let bytes = min_final_cltv_expiry_delta.to_be_bytes();
+               expiry_bytes[0] |= bytes[0];
+               expiry_bytes[1] |= bytes[1];
+       }
 
        let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN];
+
        metadata_bytes[..AMT_MSAT_LEN].copy_from_slice(&min_amt_msat_bytes);
        metadata_bytes[AMT_MSAT_LEN..].copy_from_slice(&expiry_bytes);
 
@@ -175,9 +220,13 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD
 /// secret (and, if supplied by LDK, our payment preimage) to include encrypted metadata about the
 /// payment.
 ///
-/// The metadata is constructed as:
+/// For payments without a custom `min_final_cltv_expiry_delta`, the metadata is constructed as:
 ///   payment method (3 bits) || payment amount (8 bytes - 3 bits) || expiry (8 bytes)
-/// and encrypted using a key derived from [`NodeSigner::get_inbound_payment_key_material`].
+///
+/// For payments including a custom `min_final_cltv_expiry_delta`, the metadata is constructed as:
+///   payment method (3 bits) || payment amount (8 bytes - 3 bits) || min_final_cltv_expiry_delta (2 bytes) || expiry (6 bytes)
+///
+/// In both cases the result is then encrypted using a key derived from [`NodeSigner::get_inbound_payment_key_material`].
 ///
 /// Then on payment receipt, we verify in this method that the payment preimage and payment secret
 /// match what was constructed.
@@ -201,24 +250,27 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD
 /// [`NodeSigner::get_inbound_payment_key_material`]: crate::chain::keysinterface::NodeSigner::get_inbound_payment_key_material
 /// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
 /// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData, highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result<Option<PaymentPreimage>, ()>
+pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData,
+       highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result<
+       (Option<PaymentPreimage>, Option<u16>), ()>
        where L::Target: Logger
 {
        let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_data.payment_secret, keys);
 
        let payment_type_res = Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET);
        let mut amt_msat_bytes = [0; AMT_MSAT_LEN];
+       let mut expiry_bytes = [0; METADATA_LEN - AMT_MSAT_LEN];
        amt_msat_bytes.copy_from_slice(&metadata_bytes[..AMT_MSAT_LEN]);
+       expiry_bytes.copy_from_slice(&metadata_bytes[AMT_MSAT_LEN..]);
        // Zero out the bits reserved to indicate the payment type.
        amt_msat_bytes[0] &= 0b00011111;
-       let min_amt_msat: u64 = u64::from_be_bytes(amt_msat_bytes.into());
-       let expiry = u64::from_be_bytes(metadata_bytes[AMT_MSAT_LEN..].try_into().unwrap());
+       let mut min_final_cltv_expiry_delta = None;
 
-       // Make sure to check to check the HMAC before doing the other checks below, to mitigate timing
-       // attacks.
+       // Make sure to check the HMAC before doing the other checks below, to mitigate timing attacks.
        let mut payment_preimage = None;
+
        match payment_type_res {
-               Ok(Method::UserPaymentHash) => {
+               Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => {
                        let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
                        hmac.input(&metadata_bytes[..]);
                        hmac.input(&payment_hash.0);
@@ -227,7 +279,7 @@ pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::F
                                return Err(())
                        }
                },
-               Ok(Method::LdkPaymentHash) => {
+               Ok(Method::LdkPaymentHash) | Ok(Method::LdkPaymentHashCustomFinalCltv) => {
                        match derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys) {
                                Ok(preimage) => payment_preimage = Some(preimage),
                                Err(bad_preimage_bytes) => {
@@ -242,6 +294,19 @@ pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::F
                }
        }
 
+       match payment_type_res {
+               Ok(Method::UserPaymentHashCustomFinalCltv) | Ok(Method::LdkPaymentHashCustomFinalCltv) => {
+                       min_final_cltv_expiry_delta = Some(min_final_cltv_expiry_delta_from_metadata(metadata_bytes));
+                       // Zero out first two bytes of expiry reserved for `min_final_cltv_expiry_delta`.
+                       expiry_bytes[0] &= 0;
+                       expiry_bytes[1] &= 0;
+               }
+               _ => {}
+       }
+
+       let min_amt_msat: u64 = u64::from_be_bytes(amt_msat_bytes.into());
+       let expiry = u64::from_be_bytes(expiry_bytes.try_into().unwrap());
+
        if payment_data.total_msat < min_amt_msat {
                log_trace!(logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
                return Err(())
@@ -252,20 +317,20 @@ pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::F
                return Err(())
        }
 
-       Ok(payment_preimage)
+       Ok((payment_preimage, min_final_cltv_expiry_delta))
 }
 
 pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: PaymentSecret, keys: &ExpandedKey) -> Result<PaymentPreimage, APIError> {
        let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_secret, keys);
 
        match Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET) {
-               Ok(Method::LdkPaymentHash) => {
+               Ok(Method::LdkPaymentHash) | Ok(Method::LdkPaymentHashCustomFinalCltv) => {
                        derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys)
                                .map_err(|bad_preimage_bytes| APIError::APIMisuseError {
                                        err: format!("Payment hash {} did not match decoded preimage {}", log_bytes!(payment_hash.0), log_bytes!(bad_preimage_bytes))
                                })
                },
-               Ok(Method::UserPaymentHash) => Err(APIError::APIMisuseError {
+               Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => Err(APIError::APIMisuseError {
                        err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string()
                }),
                Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }),
index c19ef72f84fdd2263436981d81fe32a9bf839a33..088cf8661f8487b577a2a71e2a4b68f77236f7ea 100644 (file)
@@ -9,17 +9,29 @@
 
 //! Further functional tests which test blockchain reorganizations.
 
+#[cfg(anchors)]
+use crate::chain::keysinterface::BaseSign;
+#[cfg(anchors)]
+use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
 use crate::chain::channelmonitor::{ANTI_REORG_DELAY, Balance};
 use crate::chain::transaction::OutPoint;
 use crate::chain::chaininterface::LowerBoundedFeeEstimator;
 use crate::ln::channel;
+#[cfg(anchors)]
+use crate::ln::chan_utils;
 use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId};
 use crate::ln::msgs::ChannelMessageHandler;
+#[cfg(anchors)]
+use crate::util::config::UserConfig;
+#[cfg(anchors)]
+use crate::util::events::BumpTransactionEvent;
 use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
 
 use bitcoin::blockdata::script::Builder;
 use bitcoin::blockdata::opcodes;
 use bitcoin::secp256k1::Secp256k1;
+#[cfg(anchors)]
+use bitcoin::{Amount, Script, TxIn, TxOut, PackedLockTime};
 use bitcoin::Transaction;
 
 use crate::prelude::*;
@@ -1666,3 +1678,141 @@ fn test_revoked_counterparty_aggregated_claims() {
        assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
        assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }
+
+#[cfg(anchors)]
+#[test]
+fn test_yield_anchors_events() {
+       // Tests that two parties supporting anchor outputs can open a channel, route payments over
+       // it, and finalize its resolution uncooperatively. Once the HTLCs are locked in, one side will
+       // force close once the HTLCs expire. The force close should stem from an event emitted by LDK,
+       // allowing the consumer to provide additional fees to the commitment transaction to be
+       // broadcast. Once the commitment transaction confirms, events for the HTLC resolution should be
+       // emitted by LDK, such that the consumer can attach fees to the zero fee HTLC transactions.
+       let secp = Secp256k1::new();
+       let mut chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let mut anchors_config = UserConfig::default();
+       anchors_config.channel_handshake_config.announced_channel = true;
+       anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       let chan_id = create_announced_chan_between_nodes_with_value(
+               &nodes, 0, 1, 1_000_000, 500_000_000
+       ).2;
+       route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       let (payment_preimage, payment_hash, _) = route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
+
+       assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+
+       connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
+       check_closed_broadcast!(&nodes[0], true);
+       assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
+
+       get_monitor!(nodes[0], chan_id).provide_payment_preimage(
+               &payment_hash, &payment_preimage, &node_cfgs[0].tx_broadcaster,
+               &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger
+       );
+
+       let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
+       assert_eq!(holder_events.len(), 1);
+       let (commitment_tx, anchor_tx) = match holder_events.pop().unwrap() {
+               Event::BumpTransaction(BumpTransactionEvent::ChannelClose { commitment_tx, anchor_descriptor, .. })  => {
+                       assert_eq!(commitment_tx.input.len(), 1);
+                       assert_eq!(commitment_tx.output.len(), 6);
+                       let mut anchor_tx = Transaction {
+                               version: 2,
+                               lock_time: PackedLockTime::ZERO,
+                               input: vec![
+                                       TxIn { previous_output: anchor_descriptor.outpoint, ..Default::default() },
+                                       TxIn { ..Default::default() },
+                               ],
+                               output: vec![TxOut {
+                                       value: Amount::ONE_BTC.to_sat(),
+                                       script_pubkey: Script::new_op_return(&[]),
+                               }],
+                       };
+                       let signer = nodes[0].keys_manager.derive_channel_keys(
+                               anchor_descriptor.channel_value_satoshis, &anchor_descriptor.channel_keys_id,
+                       );
+                       let funding_sig = signer.sign_holder_anchor_input(&mut anchor_tx, 0, &secp).unwrap();
+                       anchor_tx.input[0].witness = chan_utils::build_anchor_input_witness(
+                               &signer.pubkeys().funding_pubkey, &funding_sig
+                       );
+                       (commitment_tx, anchor_tx)
+               },
+               _ => panic!("Unexpected event"),
+       };
+
+       mine_transactions(&nodes[0], &[&commitment_tx, &anchor_tx]);
+       check_added_monitors!(nodes[0], 1);
+
+       let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
+       // Certain block `ConnectStyle`s cause an extra `ChannelClose` event to be emitted since the
+       // best block is being updated prior to the confirmed transactions.
+       match *nodes[0].connect_style.borrow() {
+               ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::BestBlockFirstSkippingBlocks => {
+                       assert_eq!(holder_events.len(), 3);
+                       if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = holder_events.remove(0) {}
+                       else { panic!("unexpected event"); }
+
+               },
+               _ => assert_eq!(holder_events.len(), 2),
+       };
+       let mut htlc_txs = Vec::with_capacity(2);
+       for event in holder_events {
+               match event {
+                       Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { htlc_descriptors, .. }) => {
+                               assert_eq!(htlc_descriptors.len(), 1);
+                               let htlc_descriptor = &htlc_descriptors[0];
+                               let signer = nodes[0].keys_manager.derive_channel_keys(
+                                       htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
+                               );
+                               let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
+                               let mut htlc_tx = Transaction {
+                                       version: 2,
+                                       lock_time: if htlc_descriptor.htlc.offered {
+                                               PackedLockTime(htlc_descriptor.htlc.cltv_expiry)
+                                       } else {
+                                               PackedLockTime::ZERO
+                                       },
+                                       input: vec![
+                                               htlc_descriptor.unsigned_tx_input(), // HTLC input
+                                               TxIn { ..Default::default() } // Fee input
+                                       ],
+                                       output: vec![
+                                               htlc_descriptor.tx_output(&per_commitment_point, &secp), // HTLC output
+                                               TxOut { // Fee input change
+                                                       value: Amount::ONE_BTC.to_sat(),
+                                                       script_pubkey: Script::new_op_return(&[]),
+                                               }
+                                       ]
+                               };
+                               let our_sig = signer.sign_holder_htlc_transaction(&mut htlc_tx, 0, htlc_descriptor, &secp).unwrap();
+                               let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &secp);
+                               htlc_tx.input[0].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script);
+                               htlc_txs.push(htlc_tx);
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+       }
+
+       mine_transactions(&nodes[0], &[&htlc_txs[0], &htlc_txs[1]]);
+       connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
+
+       assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+
+       connect_blocks(&nodes[0], BREAKDOWN_TIMEOUT as u32);
+
+       let holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
+       assert_eq!(holder_events.len(), 3);
+       for event in holder_events {
+               match event {
+                       Event::SpendableOutputs { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+       }
+
+       // Clear the remaining events as they're not relevant to what we're testing.
+       nodes[0].node.get_and_clear_pending_events();
+}
index 6cbcd9787008f30901ddbed5232ada6c93d0e71f..40817aa3c7d5494e6d4340427d666a5a4fe363ed 100644 (file)
@@ -632,6 +632,25 @@ impl Readable for NetAddress {
        }
 }
 
+/// Represents the set of gossip messages that require a signature from a node's identity key.
+pub enum UnsignedGossipMessage<'a> {
+       /// An unsigned channel announcement.
+       ChannelAnnouncement(&'a UnsignedChannelAnnouncement),
+       /// An unsigned channel update.
+       ChannelUpdate(&'a UnsignedChannelUpdate),
+       /// An unsigned node announcement.
+       NodeAnnouncement(&'a UnsignedNodeAnnouncement)
+}
+
+impl<'a> Writeable for UnsignedGossipMessage<'a> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               match self {
+                       UnsignedGossipMessage::ChannelAnnouncement(ref msg) => msg.write(writer),
+                       UnsignedGossipMessage::ChannelUpdate(ref msg) => msg.write(writer),
+                       UnsignedGossipMessage::NodeAnnouncement(ref msg) => msg.write(writer),
+               }
+       }
+}
 
 /// The unsigned part of a [`node_announcement`] message.
 ///
index 442dfc399857aef21d9cccca6f17caaaa6f81e6e..1ecdb5a87fc4ce746718db5a2c916e32e56c744e 100644 (file)
@@ -15,7 +15,7 @@ use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCK
 use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
 use crate::ln::{PaymentHash, PaymentSecret};
 use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
-use crate::ln::channelmanager::{HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingAddHTLCInfo, PendingHTLCInfo, PendingHTLCRouting, PaymentId};
+use crate::ln::channelmanager::{HTLCForwardInfo, FailureCode, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingAddHTLCInfo, PendingHTLCInfo, PendingHTLCRouting, PaymentId};
 use crate::ln::onion_utils;
 use crate::routing::gossip::{NetworkUpdate, RoutingFees};
 use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
@@ -35,8 +35,7 @@ use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
 
 use bitcoin::secp256k1;
-use bitcoin::secp256k1::Secp256k1;
-use bitcoin::secp256k1::{PublicKey, SecretKey};
+use bitcoin::secp256k1::{Secp256k1, SecretKey};
 
 use crate::io;
 use crate::prelude::*;
@@ -832,11 +831,76 @@ fn test_always_create_tlv_format_onion_payloads() {
        }
 }
 
+fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) {
+
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1);
+
+       let payment_amount = 100_000;
+       let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_amount);
+       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
+       check_added_monitors!(nodes[0], 1);
+
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+       commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+
+       expect_pending_htlcs_forwardable!(nodes[1]);
+       expect_payment_claimable!(nodes[1], payment_hash, payment_secret, payment_amount);
+       nodes[1].node.fail_htlc_backwards_with_reason(&payment_hash, &failure_code);
+
+       expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash }]);
+       check_added_monitors!(nodes[1], 1);
+
+       let events = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       let (update_fail_htlc, commitment_signed) = match events[0] {
+               MessageSendEvent::UpdateHTLCs { node_id: _ , updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
+                       assert!(update_add_htlcs.is_empty());
+                       assert!(update_fulfill_htlcs.is_empty());
+                       assert_eq!(update_fail_htlcs.len(), 1);
+                       assert!(update_fail_malformed_htlcs.is_empty());
+                       assert!(update_fee.is_none());
+                       (update_fail_htlcs[0].clone(), commitment_signed)
+               },
+               _ => panic!("Unexpected event"),
+       };
+
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &update_fail_htlc);
+       commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false, true);
+
+       let failure_data = match failure_code {
+               FailureCode::TemporaryNodeFailure => vec![],
+               FailureCode::RequiredNodeFeatureMissing => vec![],
+               FailureCode::IncorrectOrUnknownPaymentDetails => {
+                       let mut htlc_msat_height_data = (payment_amount as u64).to_be_bytes().to_vec();
+                       htlc_msat_height_data.extend_from_slice(&CHAN_CONFIRM_DEPTH.to_be_bytes());
+                       htlc_msat_height_data
+               }
+       };
+
+       let failure_code = failure_code as u16;
+       let permanent_flag = 0x4000;
+       let permanent_fail = (failure_code & permanent_flag) != 0;
+       expect_payment_failed!(nodes[0], payment_hash, permanent_fail, failure_code, failure_data);
+
+}
+
+#[test]
+fn test_fail_htlc_backwards_with_reason() {
+       do_test_fail_htlc_backwards_with_reason(FailureCode::TemporaryNodeFailure);
+       do_test_fail_htlc_backwards_with_reason(FailureCode::RequiredNodeFeatureMissing);
+       do_test_fail_htlc_backwards_with_reason(FailureCode::IncorrectOrUnknownPaymentDetails);
+}
+
 macro_rules! get_phantom_route {
        ($nodes: expr, $amt: expr, $channel: expr) => {{
-               let secp_ctx = Secp256k1::new();
-               let phantom_secret = $nodes[1].keys_manager.get_node_secret(Recipient::PhantomNode).unwrap();
-               let phantom_pubkey = PublicKey::from_secret_key(&secp_ctx, &phantom_secret);
+               let phantom_pubkey = $nodes[1].keys_manager.get_node_id(Recipient::PhantomNode).unwrap();
                let phantom_route_hint = $nodes[1].node.get_phantom_route_hints();
                let payment_params = PaymentParameters::from_node_id(phantom_pubkey)
                        .with_features($nodes[1].node.invoice_features())
index 161f6ecc14bebbe46317db4ad7fe058bd757ff41..8867b2e96ae14c3e75bb960d5dd9fa97ed10d746 100644 (file)
@@ -15,16 +15,22 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
 
 use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
 use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use crate::ln::channelmanager::{HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, PaymentId};
+use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, MIN_HTLC_RELAY_HOLDING_CELL_MILLIS, PaymentId};
 use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils::HTLCFailReason;
-use crate::routing::router::{PaymentParameters, Route, RouteHop, RouteParameters, RoutePath};
+use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, RoutePath, Router};
 use crate::util::errors::APIError;
 use crate::util::events;
 use crate::util::logger::Logger;
+use crate::util::time::Time;
+#[cfg(all(not(feature = "no-std"), test))]
+use crate::util::time::tests::SinceEpoch;
 
 use core::cmp;
+use core::fmt::{self, Display, Formatter};
 use core::ops::Deref;
+use core::time::Duration;
+
 use crate::prelude::*;
 use crate::sync::Mutex;
 
@@ -35,6 +41,9 @@ pub(crate) enum PendingOutboundPayment {
                session_privs: HashSet<[u8; 32]>,
        },
        Retryable {
+               retry_strategy: Retry,
+               attempts: PaymentAttempts,
+               route_params: Option<RouteParameters>,
                session_privs: HashSet<[u8; 32]>,
                payment_hash: PaymentHash,
                payment_secret: Option<PaymentSecret>,
@@ -68,6 +77,22 @@ pub(crate) enum PendingOutboundPayment {
 }
 
 impl PendingOutboundPayment {
+       fn increment_attempts(&mut self) {
+               if let PendingOutboundPayment::Retryable { attempts, .. } = self {
+                       attempts.count += 1;
+               }
+       }
+       fn is_retryable_now(&self) -> bool {
+               if let PendingOutboundPayment::Retryable { retry_strategy, attempts, .. } = self {
+                       return retry_strategy.is_retryable_now(&attempts)
+               }
+               false
+       }
+       pub fn insert_previously_failed_scid(&mut self, scid: u64) {
+               if let PendingOutboundPayment::Retryable { route_params: Some(params), .. } = self {
+                       params.payment_params.previously_failed_channels.push(scid);
+               }
+       }
        pub(super) fn is_fulfilled(&self) -> bool {
                match self {
                        PendingOutboundPayment::Fulfilled { .. } => true,
@@ -182,6 +207,88 @@ impl PendingOutboundPayment {
        }
 }
 
+/// Strategies available to retry payment path failures.
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub enum Retry {
+       /// Max number of attempts to retry payment.
+       ///
+       /// Note that this is the number of *path* failures, not full payment retries. For multi-path
+       /// payments, if this is less than the total number of paths, we will never even retry all of the
+       /// payment's paths.
+       Attempts(usize),
+       #[cfg(not(feature = "no-std"))]
+       /// Time elapsed before abandoning retries for a payment.
+       Timeout(core::time::Duration),
+}
+
+impl Retry {
+       pub(crate) fn is_retryable_now(&self, attempts: &PaymentAttempts) -> bool {
+               match (self, attempts) {
+                       (Retry::Attempts(max_retry_count), PaymentAttempts { count, .. }) => {
+                               max_retry_count > count
+                       },
+                       #[cfg(all(not(feature = "no-std"), not(test)))]
+                       (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) =>
+                               *max_duration >= std::time::Instant::now().duration_since(*first_attempted_at),
+                       #[cfg(all(not(feature = "no-std"), test))]
+                       (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) =>
+                               *max_duration >= SinceEpoch::now().duration_since(*first_attempted_at),
+               }
+       }
+}
+
+#[cfg(feature = "std")]
+pub(super) fn has_expired(route_params: &RouteParameters) -> bool {
+       if let Some(expiry_time) = route_params.payment_params.expiry_time {
+               if let Ok(elapsed) = std::time::SystemTime::UNIX_EPOCH.elapsed() {
+                       return elapsed > core::time::Duration::from_secs(expiry_time)
+               }
+       }
+       false
+}
+
+pub(crate) type PaymentAttempts = PaymentAttemptsUsingTime<ConfiguredTime>;
+
+/// Storing minimal payment attempts information required for determining if a outbound payment can
+/// be retried.
+pub(crate) struct PaymentAttemptsUsingTime<T: Time> {
+       /// This count will be incremented only after the result of the attempt is known. When it's 0,
+       /// it means the result of the first attempt is not known yet.
+       pub(crate) count: usize,
+       /// This field is only used when retry is `Retry::Timeout` which is only build with feature std
+       first_attempted_at: T
+}
+
+#[cfg(not(any(feature = "no-std", test)))]
+type ConfiguredTime = std::time::Instant;
+#[cfg(feature = "no-std")]
+type ConfiguredTime = crate::util::time::Eternity;
+#[cfg(all(not(feature = "no-std"), test))]
+type ConfiguredTime = SinceEpoch;
+
+impl<T: Time> PaymentAttemptsUsingTime<T> {
+       pub(crate) fn new() -> Self {
+               PaymentAttemptsUsingTime {
+                       count: 0,
+                       first_attempted_at: T::now()
+               }
+       }
+}
+
+impl<T: Time> Display for PaymentAttemptsUsingTime<T> {
+       fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+               #[cfg(feature = "no-std")]
+               return write!(f, "attempts: {}", self.count);
+               #[cfg(not(feature = "no-std"))]
+               return write!(
+                       f,
+                       "attempts: {}, duration: {}s",
+                       self.count,
+                       T::now().duration_since(self.first_attempted_at).as_secs()
+               );
+       }
+}
+
 /// If a payment fails to send, it can be in one of several states. This enum is returned as the
 /// Err() type describing which state the payment is in, see the description of individual enum
 /// states for more.
@@ -271,6 +378,25 @@ impl OutboundPayments {
                }
        }
 
+       pub(super) fn send_payment<R: Deref, ES: Deref, NS: Deref, F>(
+               &self, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, payment_id: PaymentId,
+               retry_strategy: Retry, route_params: RouteParameters, router: &R,
+               first_hops: Vec<ChannelDetails>, inflight_htlcs: InFlightHtlcs, entropy_source: &ES,
+               node_signer: &NS, best_block_height: u32, send_payment_along_path: F
+       ) -> Result<(), PaymentSendFailure>
+       where
+               R::Target: Router,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                        u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>,
+       {
+               self.pay_internal(payment_id, Some((payment_hash, payment_secret, retry_strategy)),
+                       route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer,
+                       best_block_height, &send_payment_along_path)
+                       .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
+       }
+
        pub(super) fn send_payment_with_route<ES: Deref, NS: Deref, F>(
                &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
                payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32,
@@ -282,8 +408,10 @@ impl OutboundPayments {
                F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
                   u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
        {
-               let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, route, entropy_source, best_block_height)?;
-               self.send_payment_internal(route, payment_hash, payment_secret, None, payment_id, None, onion_session_privs, node_signer, best_block_height, send_payment_along_path)
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, route, Retry::Attempts(0), None, entropy_source, best_block_height)?;
+               self.pay_route_internal(route, payment_hash, payment_secret, None, payment_id, None,
+                       onion_session_privs, node_signer, best_block_height, &send_payment_along_path)
+                       .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
        }
 
        pub(super) fn send_spontaneous_payment<ES: Deref, NS: Deref, F>(
@@ -301,11 +429,124 @@ impl OutboundPayments {
                        None => PaymentPreimage(entropy_source.get_secure_random_bytes()),
                };
                let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner());
-               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, entropy_source, best_block_height)?;
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, Retry::Attempts(0), None, entropy_source, best_block_height)?;
 
-               match self.send_payment_internal(route, payment_hash, &None, Some(preimage), payment_id, None, onion_session_privs, node_signer, best_block_height, send_payment_along_path) {
+               match self.pay_route_internal(route, payment_hash, &None, Some(preimage), payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) {
                        Ok(()) => Ok(payment_hash),
-                       Err(e) => Err(e)
+                       Err(e) => {
+                               self.remove_outbound_if_all_failed(payment_id, &e);
+                               Err(e)
+                       }
+               }
+       }
+
+       pub(super) fn check_retry_payments<R: Deref, ES: Deref, NS: Deref, SP, IH, FH, L: Deref>(
+               &self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
+               best_block_height: u32, logger: &L, send_payment_along_path: SP,
+       )
+       where
+               R::Target: Router,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                  u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>,
+               IH: Fn() -> InFlightHtlcs,
+               FH: Fn() -> Vec<ChannelDetails>,
+               L::Target: Logger,
+       {
+               loop {
+                       let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+                       let mut retry_id_route_params = None;
+                       for (pmt_id, pmt) in outbounds.iter_mut() {
+                               if pmt.is_retryable_now() {
+                                       if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, route_params: Some(params), .. } = pmt {
+                                               if pending_amt_msat < total_msat {
+                                                       retry_id_route_params = Some((*pmt_id, params.clone()));
+                                                       pmt.increment_attempts();
+                                                       break
+                                               }
+                                       }
+                               }
+                       }
+                       if let Some((payment_id, route_params)) = retry_id_route_params {
+                               core::mem::drop(outbounds);
+                               if let Err(e) = self.pay_internal(payment_id, None, route_params, router, first_hops(), inflight_htlcs(), entropy_source, node_signer, best_block_height, &send_payment_along_path) {
+                                       log_trace!(logger, "Errored retrying payment: {:?}", e);
+                               }
+                       } else { break }
+               }
+       }
+
+       fn pay_internal<R: Deref, NS: Deref, ES: Deref, F>(
+               &self, payment_id: PaymentId,
+               initial_send_info: Option<(PaymentHash, &Option<PaymentSecret>, Retry)>,
+               route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>,
+               inflight_htlcs: InFlightHtlcs, entropy_source: &ES, node_signer: &NS, best_block_height: u32,
+               send_payment_along_path: &F
+       ) -> Result<(), PaymentSendFailure>
+       where
+               R::Target: Router,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                  u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
+       {
+               #[cfg(feature = "std")] {
+                       if has_expired(&route_params) {
+                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                                       err: format!("Invoice expired for payment id {}", log_bytes!(payment_id.0)),
+                               }))
+                       }
+               }
+
+               let route = router.find_route(
+                       &node_signer.get_node_id(Recipient::Node).unwrap(), &route_params,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), &inflight_htlcs
+               ).map_err(|e| PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                       err: format!("Failed to find a route for payment {}: {:?}", log_bytes!(payment_id.0), e), // TODO: add APIError::RouteNotFound
+               }))?;
+
+               let res = if let Some((payment_hash, payment_secret, retry_strategy)) = initial_send_info {
+                       let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, &route, retry_strategy, Some(route_params.clone()), entropy_source, best_block_height)?;
+                       self.pay_route_internal(&route, payment_hash, payment_secret, None, payment_id, None, onion_session_privs, node_signer, best_block_height, send_payment_along_path)
+               } else {
+                       self.retry_payment_with_route(&route, payment_id, entropy_source, node_signer, best_block_height, send_payment_along_path)
+               };
+               match res {
+                       Err(PaymentSendFailure::AllFailedResendSafe(_)) => {
+                               let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+                               if let Some(payment) = outbounds.get_mut(&payment_id) {
+                                       let retryable = payment.is_retryable_now();
+                                       if retryable {
+                                               payment.increment_attempts();
+                                       } else { return res }
+                               } else { return res }
+                               core::mem::drop(outbounds);
+                               self.pay_internal(payment_id, None, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, send_payment_along_path)
+                       },
+                       Err(PaymentSendFailure::PartialFailure { failed_paths_retry: Some(retry), results, .. }) => {
+                               let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+                               if let Some(payment) = outbounds.get_mut(&payment_id) {
+                                       let retryable = payment.is_retryable_now();
+                                       if retryable {
+                                               payment.increment_attempts();
+                                       } else { return Err(PaymentSendFailure::PartialFailure { failed_paths_retry: Some(retry), results, payment_id }) }
+                               } else { return Err(PaymentSendFailure::PartialFailure { failed_paths_retry: Some(retry), results, payment_id }) }
+                               core::mem::drop(outbounds);
+
+                               // Some paths were sent, even if we failed to send the full MPP value our recipient may
+                               // misbehave and claim the funds, at which point we have to consider the payment sent, so
+                               // return `Ok()` here, ignoring any retry errors.
+                               let _ = self.pay_internal(payment_id, None, retry, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, send_payment_along_path);
+                               Ok(())
+                       },
+                       Err(PaymentSendFailure::PartialFailure { failed_paths_retry: None, .. }) => {
+                               // This may happen if we send a payment and some paths fail, but only due to a temporary
+                               // monitor failure or the like, implying they're really in-flight, but we haven't sent the
+                               // initial HTLC-Add messages yet.
+                               Ok(())
+                       },
+                       res => res,
                }
        }
 
@@ -376,7 +617,7 @@ impl OutboundPayments {
                                        })),
                        }
                };
-               self.send_payment_internal(route, payment_hash, &payment_secret, None, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height, send_payment_along_path)
+               self.pay_route_internal(route, payment_hash, &payment_secret, None, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height, &send_payment_along_path)
        }
 
        pub(super) fn send_probe<ES: Deref, NS: Deref, F>(
@@ -400,25 +641,29 @@ impl OutboundPayments {
                }
 
                let route = Route { paths: vec![hops], payment_params: None };
-               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, entropy_source, best_block_height)?;
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, Retry::Attempts(0), None, entropy_source, best_block_height)?;
 
-               match self.send_payment_internal(&route, payment_hash, &None, None, payment_id, None, onion_session_privs, node_signer, best_block_height, send_payment_along_path) {
+               match self.pay_route_internal(&route, payment_hash, &None, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) {
                        Ok(()) => Ok((payment_hash, payment_id)),
-                       Err(e) => Err(e)
+                       Err(e) => {
+                               self.remove_outbound_if_all_failed(payment_id, &e);
+                               Err(e)
+                       }
                }
        }
 
        #[cfg(test)]
        pub(super) fn test_add_new_pending_payment<ES: Deref>(
                &self, payment_hash: PaymentHash, payment_secret: Option<PaymentSecret>, payment_id: PaymentId,
-               route: &Route, entropy_source: &ES, best_block_height: u32
+               route: &Route, retry_strategy: Retry, entropy_source: &ES, best_block_height: u32
        ) -> Result<Vec<[u8; 32]>, PaymentSendFailure> where ES::Target: EntropySource {
-               self.add_new_pending_payment(payment_hash, payment_secret, payment_id, route, entropy_source, best_block_height)
+               self.add_new_pending_payment(payment_hash, payment_secret, payment_id, route, retry_strategy, None, entropy_source, best_block_height)
        }
 
        pub(super) fn add_new_pending_payment<ES: Deref>(
                &self, payment_hash: PaymentHash, payment_secret: Option<PaymentSecret>, payment_id: PaymentId,
-               route: &Route, entropy_source: &ES, best_block_height: u32
+               route: &Route, retry_strategy: Retry, route_params: Option<RouteParameters>,
+               entropy_source: &ES, best_block_height: u32
        ) -> Result<Vec<[u8; 32]>, PaymentSendFailure> where ES::Target: EntropySource {
                let mut onion_session_privs = Vec::with_capacity(route.paths.len());
                for _ in 0..route.paths.len() {
@@ -430,6 +675,9 @@ impl OutboundPayments {
                        hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment),
                        hash_map::Entry::Vacant(entry) => {
                                let payment = entry.insert(PendingOutboundPayment::Retryable {
+                                       retry_strategy,
+                                       attempts: PaymentAttempts::new(),
+                                       route_params,
                                        session_privs: HashSet::new(),
                                        pending_amt_msat: 0,
                                        pending_fee_msat: Some(0),
@@ -448,11 +696,11 @@ impl OutboundPayments {
                }
        }
 
-       fn send_payment_internal<NS: Deref, F>(
+       fn pay_route_internal<NS: Deref, F>(
                &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
                keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>,
                onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, best_block_height: u32,
-               send_payment_along_path: F
+               send_payment_along_path: &F
        ) -> Result<(), PaymentSendFailure>
        where
                NS::Target: NodeSigner,
@@ -547,10 +795,6 @@ impl OutboundPayments {
                                } else { None },
                        })
                } else if has_err {
-                       // If we failed to send any paths, we should remove the new PaymentId from the
-                       // `pending_outbound_payments` map, as the user isn't expected to `abandon_payment`.
-                       let removed = self.pending_outbound_payments.lock().unwrap().remove(&payment_id).is_some();
-                       debug_assert!(removed, "We should always have a pending payment to remove here");
                        Err(PaymentSendFailure::AllFailedResendSafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
                } else {
                        Ok(())
@@ -569,9 +813,19 @@ impl OutboundPayments {
                F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
                   u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
        {
-               self.send_payment_internal(route, payment_hash, payment_secret, keysend_preimage, payment_id,
+               self.pay_route_internal(route, payment_hash, payment_secret, keysend_preimage, payment_id,
                        recv_value_msat, onion_session_privs, node_signer, best_block_height,
-                       send_payment_along_path)
+                       &send_payment_along_path)
+                       .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
+       }
+
+       // If we failed to send any paths, we should remove the new PaymentId from the
+       // `pending_outbound_payments` map, as the user isn't expected to `abandon_payment`.
+       fn remove_outbound_if_all_failed(&self, payment_id: PaymentId, err: &PaymentSendFailure) {
+               if let &PaymentSendFailure::AllFailedResendSafe(_) = err {
+                       let removed = self.pending_outbound_payments.lock().unwrap().remove(&payment_id).is_some();
+                       debug_assert!(removed, "We should always have a pending payment to remove here");
+               }
        }
 
        pub(super) fn claim_htlc<L: Deref>(
@@ -688,12 +942,18 @@ impl OutboundPayments {
                payment_params: &Option<PaymentParameters>, probing_cookie_secret: [u8; 32],
                secp_ctx: &Secp256k1<secp256k1::All>, pending_events: &Mutex<Vec<events::Event>>, logger: &L
        ) where L::Target: Logger {
+               #[cfg(test)]
+               let (network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_error.decode_onion_failure(secp_ctx, logger, &source);
+               #[cfg(not(test))]
+               let (network_update, short_channel_id, payment_retryable, _, _) = onion_error.decode_onion_failure(secp_ctx, logger, &source);
+
                let mut session_priv_bytes = [0; 32];
                session_priv_bytes.copy_from_slice(&session_priv[..]);
                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
                let mut all_paths_failed = false;
                let mut full_failure_ev = None;
-               if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(*payment_id) {
+               let mut pending_retry_ev = None;
+               let attempts_remaining = if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(*payment_id) {
                        if !payment.get_mut().remove(&session_priv_bytes, Some(&path)) {
                                log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
                                return
@@ -702,6 +962,10 @@ impl OutboundPayments {
                                log_trace!(logger, "Received failure of HTLC with payment_hash {} after payment completion", log_bytes!(payment_hash.0));
                                return
                        }
+                       let is_retryable_now = payment.get().is_retryable_now();
+                       if let Some(scid) = short_channel_id {
+                               payment.get_mut().insert_previously_failed_scid(scid);
+                       }
                        if payment.get().remaining_parts() == 0 {
                                all_paths_failed = true;
                                if payment.get().abandoned() {
@@ -712,10 +976,12 @@ impl OutboundPayments {
                                        payment.remove();
                                }
                        }
+                       is_retryable_now
                } else {
                        log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
                        return
-               }
+               };
+               core::mem::drop(outbounds);
                let mut retry = if let Some(payment_params_data) = payment_params {
                        let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
                        Some(RouteParameters {
@@ -727,11 +993,6 @@ impl OutboundPayments {
                log_trace!(logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0));
 
                let path_failure = {
-                       #[cfg(test)]
-                       let (network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_error.decode_onion_failure(secp_ctx, logger, &source);
-                       #[cfg(not(test))]
-                       let (network_update, short_channel_id, payment_retryable, _, _) = onion_error.decode_onion_failure(secp_ctx, logger, &source);
-
                        if payment_is_probe(payment_hash, &payment_id, probing_cookie_secret) {
                                if !payment_retryable {
                                        events::Event::ProbeSuccessful {
@@ -754,6 +1015,12 @@ impl OutboundPayments {
                                if let Some(scid) = short_channel_id {
                                        retry.as_mut().map(|r| r.payment_params.previously_failed_channels.push(scid));
                                }
+                               if payment_retryable && attempts_remaining && retry.is_some() {
+                                       debug_assert!(full_failure_ev.is_none());
+                                       pending_retry_ev = Some(events::Event::PendingHTLCsForwardable {
+                                               time_forwardable: Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS),
+                                       });
+                               }
                                events::Event::PaymentPathFailed {
                                        payment_id: Some(*payment_id),
                                        payment_hash: payment_hash.clone(),
@@ -773,6 +1040,7 @@ impl OutboundPayments {
                let mut pending_events = pending_events.lock().unwrap();
                pending_events.push(path_failure);
                if let Some(ev) = full_failure_ev { pending_events.push(ev); }
+               if let Some(ev) = pending_retry_ev { pending_events.push(ev); }
        }
 
        pub(super) fn abandon_payment(&self, payment_id: PaymentId) -> Option<events::Event> {
@@ -833,8 +1101,11 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
                (0, session_privs, required),
                (1, pending_fee_msat, option),
                (2, payment_hash, required),
+               (not_written, retry_strategy, (static_value, Retry::Attempts(0))),
                (4, payment_secret, option),
+               (not_written, attempts, (static_value, PaymentAttempts::new())),
                (6, total_msat, required),
+               (not_written, route_params, (static_value, None)),
                (8, pending_amt_msat, required),
                (10, starting_block_height, required),
        },
@@ -843,3 +1114,99 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
                (2, payment_hash, required),
        },
 );
+
+#[cfg(test)]
+mod tests {
+       use bitcoin::blockdata::constants::genesis_block;
+       use bitcoin::network::constants::Network;
+       use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
+
+       use crate::ln::PaymentHash;
+       use crate::ln::channelmanager::{PaymentId, PaymentSendFailure};
+       use crate::ln::msgs::{ErrorAction, LightningError};
+       use crate::ln::outbound_payment::{OutboundPayments, Retry};
+       use crate::routing::gossip::NetworkGraph;
+       use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters};
+       use crate::sync::Arc;
+       use crate::util::errors::APIError;
+       use crate::util::test_utils;
+
+       #[test]
+       #[cfg(feature = "std")]
+       fn fails_paying_after_expiration() {
+               do_fails_paying_after_expiration(false);
+               do_fails_paying_after_expiration(true);
+       }
+       #[cfg(feature = "std")]
+       fn do_fails_paying_after_expiration(on_retry: bool) {
+               let outbound_payments = OutboundPayments::new();
+               let logger = test_utils::TestLogger::new();
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
+               let router = test_utils::TestRouter::new(network_graph);
+               let secp_ctx = Secp256k1::new();
+               let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
+
+               let past_expiry_time = std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() - 2;
+               let payment_params = PaymentParameters::from_node_id(
+                       PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()))
+                       .with_expiry_time(past_expiry_time);
+               let expired_route_params = RouteParameters {
+                       payment_params,
+                       final_value_msat: 0,
+                       final_cltv_expiry_delta: 0,
+               };
+               let err = if on_retry {
+                       outbound_payments.pay_internal(
+                               PaymentId([0; 32]), None, expired_route_params, &&router, vec![], InFlightHtlcs::new(),
+                               &&keys_manager, &&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
+               } else {
+                       outbound_payments.send_payment(
+                               PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), expired_route_params,
+                               &&router, vec![], InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
+               };
+               if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
+                       assert!(err.contains("Invoice expired"));
+               } else { panic!("Unexpected error"); }
+       }
+
+       #[test]
+       fn find_route_error() {
+               do_find_route_error(false);
+               do_find_route_error(true);
+       }
+       fn do_find_route_error(on_retry: bool) {
+               let outbound_payments = OutboundPayments::new();
+               let logger = test_utils::TestLogger::new();
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
+               let router = test_utils::TestRouter::new(network_graph);
+               let secp_ctx = Secp256k1::new();
+               let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
+
+               router.expect_find_route(Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }));
+
+               let payment_params = PaymentParameters::from_node_id(
+                       PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()));
+               let route_params = RouteParameters {
+                       payment_params,
+                       final_value_msat: 0,
+                       final_cltv_expiry_delta: 0,
+               };
+               let err = if on_retry {
+                       outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]),
+                       &Route { paths: vec![], payment_params: None }, Retry::Attempts(1), Some(route_params.clone()),
+                       &&keys_manager, 0).unwrap();
+                       outbound_payments.pay_internal(
+                               PaymentId([0; 32]), None, route_params, &&router, vec![], InFlightHtlcs::new(),
+                               &&keys_manager, &&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
+               } else {
+                       outbound_payments.send_payment(
+                               PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params,
+                               &&router, vec![], InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
+               };
+               if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
+                       assert!(err.contains("Failed to find a route"));
+               } else { panic!("Unexpected error"); }
+       }
+}
index 2a9a180f3a91f6104eb3c46c72ab16c7bbcc856c..726c5b89e5466ea544da5bbe160431170901d9bf 100644 (file)
@@ -17,10 +17,12 @@ use crate::chain::keysinterface::EntropySource;
 use crate::chain::transaction::OutPoint;
 use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
 use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS};
+use crate::ln::features::InvoiceFeatures;
 use crate::ln::msgs;
 use crate::ln::msgs::ChannelMessageHandler;
+use crate::ln::outbound_payment::Retry;
 use crate::routing::gossip::RoutingFees;
-use crate::routing::router::{get_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
+use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RouteParameters};
 use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
 use crate::util::test_utils;
 use crate::util::errors::APIError;
@@ -34,6 +36,11 @@ use crate::prelude::*;
 
 use crate::ln::functional_test_utils::*;
 use crate::routing::gossip::NodeId;
+#[cfg(feature = "std")]
+use {
+       crate::util::time::tests::SinceEpoch,
+       std::time::{SystemTime, Duration}
+};
 
 #[test]
 fn retry_single_path_payment() {
@@ -910,7 +917,7 @@ fn get_ldk_payment_preimage() {
 
        let amt_msat = 60_000;
        let expiry_secs = 60 * 60;
-       let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs).unwrap();
+       let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs, None).unwrap();
 
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
                .with_features(nodes[1].node.invoice_features());
@@ -1444,7 +1451,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
                route_params.final_cltv_expiry_delta, nodes[0].logger, &scorer, &random_seed_bytes
        ).unwrap();
 
-       let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60).unwrap();
+       let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
        nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
        let payment_event = {
                {
@@ -1575,3 +1582,809 @@ fn do_test_intercepted_payment(test: InterceptTest) {
                assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) });
        }
 }
+
+#[derive(PartialEq)]
+enum AutoRetry {
+       Success,
+       FailAttempts,
+       FailTimeout,
+       FailOnRestart,
+}
+
+#[test]
+fn automatic_retries() {
+       do_automatic_retries(AutoRetry::Success);
+       do_automatic_retries(AutoRetry::FailAttempts);
+       do_automatic_retries(AutoRetry::FailTimeout);
+       do_automatic_retries(AutoRetry::FailOnRestart);
+}
+fn do_automatic_retries(test: AutoRetry) {
+       // Test basic automatic payment retries in ChannelManager. See individual `test` variant comments
+       // below.
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+
+       let persister;
+       let new_chain_monitor;
+       let node_0_deserialized;
+
+       let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       let channel_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1).2;
+       let channel_id_2 = create_announced_chan_between_nodes(&nodes, 2, 1).2;
+
+       // Marshall data to send the payment
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let amt_msat = 1000;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+       let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
+
+       macro_rules! pass_failed_attempt_with_retry_along_path {
+               ($failing_channel_id: expr, $expect_pending_htlcs_forwardable: expr) => {
+                       // Send a payment attempt that fails due to lack of liquidity on the second hop
+                       check_added_monitors!(nodes[0], 1);
+                       let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+                       let mut update_add = update_0.update_add_htlcs[0].clone();
+                       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add);
+                       commitment_signed_dance!(nodes[1], nodes[0], &update_0.commitment_signed, false, true);
+                       expect_pending_htlcs_forwardable_ignore!(nodes[1]);
+                       nodes[1].node.process_pending_htlc_forwards();
+                       expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1],
+                               vec![HTLCDestination::NextHopChannel {
+                                       node_id: Some(nodes[2].node.get_our_node_id()),
+                                       channel_id: $failing_channel_id,
+                               }]);
+                       nodes[1].node.process_pending_htlc_forwards();
+                       let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+                       check_added_monitors!(&nodes[1], 1);
+                       assert!(update_1.update_fail_htlcs.len() == 1);
+                       let fail_msg = update_1.update_fail_htlcs[0].clone();
+
+                       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_msg);
+                       commitment_signed_dance!(nodes[0], nodes[1], update_1.commitment_signed, false);
+
+                       // Ensure the attempt fails and a new PendingHTLCsForwardable event is generated for the retry
+                       let mut events = nodes[0].node.get_and_clear_pending_events();
+                       match events[0] {
+                               Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
+                                       assert_eq!(payment_hash, ev_payment_hash);
+                                       assert_eq!(payment_failed_permanently, false);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+                       if $expect_pending_htlcs_forwardable {
+                               assert_eq!(events.len(), 2);
+                               match events[1] {
+                                       Event::PendingHTLCsForwardable { .. } => {},
+                                       _ => panic!("Unexpected event"),
+                               }
+                       } else { assert_eq!(events.len(), 1) }
+               }
+       }
+
+       if test == AutoRetry::Success {
+               // Test that we can succeed on the first retry.
+               nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+               pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
+
+               // Open a new channel with liquidity on the second hop so we can find a route for the retry
+               // attempt, since the initial second hop channel will be excluded from pathfinding
+               create_announced_chan_between_nodes(&nodes, 1, 2);
+
+               // We retry payments in `process_pending_htlc_forwards`
+               nodes[0].node.process_pending_htlc_forwards();
+               check_added_monitors!(nodes[0], 1);
+               let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(msg_events.len(), 1);
+               pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None);
+               claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       } else if test == AutoRetry::FailAttempts {
+               // Ensure ChannelManager will not retry a payment if it has run out of payment attempts.
+               nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+               pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
+
+               // Open a new channel with no liquidity on the second hop so we can find a (bad) route for
+               // the retry attempt, since the initial second hop channel will be excluded from pathfinding
+               let channel_id_3 = create_announced_chan_between_nodes(&nodes, 2, 1).2;
+
+               // We retry payments in `process_pending_htlc_forwards`
+               nodes[0].node.process_pending_htlc_forwards();
+               pass_failed_attempt_with_retry_along_path!(channel_id_3, false);
+
+               // Ensure we won't retry a second time.
+               nodes[0].node.process_pending_htlc_forwards();
+               let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(msg_events.len(), 0);
+
+               nodes[0].node.abandon_payment(PaymentId(payment_hash.0));
+               let events = nodes[0].node.get_and_clear_pending_events();
+               assert_eq!(events.len(), 1);
+               match events[0] {
+                       Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id } => {
+                               assert_eq!(payment_hash, *ev_payment_hash);
+                               assert_eq!(PaymentId(payment_hash.0), *ev_payment_id);
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+       } else if test == AutoRetry::FailTimeout {
+               #[cfg(not(feature = "no-std"))] {
+                       // Ensure ChannelManager will not retry a payment if it times out due to Retry::Timeout.
+                       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Timeout(Duration::from_secs(60))).unwrap();
+                       pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
+
+                       // Advance the time so the second attempt fails due to timeout.
+                       SinceEpoch::advance(Duration::from_secs(61));
+
+                       // Make sure we don't retry again.
+                       nodes[0].node.process_pending_htlc_forwards();
+                       let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+                       assert_eq!(msg_events.len(), 0);
+
+                       nodes[0].node.abandon_payment(PaymentId(payment_hash.0));
+                       let mut events = nodes[0].node.get_and_clear_pending_events();
+                       assert_eq!(events.len(), 1);
+                       match events[0] {
+                               Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id } => {
+                                       assert_eq!(payment_hash, *ev_payment_hash);
+                                       assert_eq!(PaymentId(payment_hash.0), *ev_payment_id);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+               }
+       } else if test == AutoRetry::FailOnRestart {
+               // Ensure ChannelManager will not retry a payment after restart, even if there were retry
+               // attempts remaining prior to restart.
+               nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(2)).unwrap();
+               pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
+
+               // Open a new channel with no liquidity on the second hop so we can find a (bad) route for
+               // the retry attempt, since the initial second hop channel will be excluded from pathfinding
+               let channel_id_3 = create_announced_chan_between_nodes(&nodes, 2, 1).2;
+
+               // Ensure the first retry attempt fails, with 1 retry attempt remaining
+               nodes[0].node.process_pending_htlc_forwards();
+               pass_failed_attempt_with_retry_along_path!(channel_id_3, true);
+
+               // Restart the node and ensure that ChannelManager does not use its remaining retry attempt
+               let node_encoded = nodes[0].node.encode();
+               let chan_1_monitor_serialized = get_monitor!(nodes[0], channel_id_1).encode();
+               reload_node!(nodes[0], node_encoded, &[&chan_1_monitor_serialized], persister, new_chain_monitor, node_0_deserialized);
+
+               // Make sure we don't retry again.
+               nodes[0].node.process_pending_htlc_forwards();
+               let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(msg_events.len(), 0);
+
+               nodes[0].node.abandon_payment(PaymentId(payment_hash.0));
+               let mut events = nodes[0].node.get_and_clear_pending_events();
+               assert_eq!(events.len(), 1);
+               match events[0] {
+                       Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id } => {
+                               assert_eq!(payment_hash, *ev_payment_hash);
+                               assert_eq!(PaymentId(payment_hash.0), *ev_payment_id);
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+       }
+}
+
+#[test]
+fn auto_retry_partial_failure() {
+       // Test that we'll retry appropriately on send partial failure and retry partial failure.
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+       let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+       let chan_3_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+
+       // Marshall data to send the payment
+       let amt_msat = 20_000;
+       let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       // Ensure the first monitor update (for the initial send path1 over chan_1) succeeds, but the
+       // second (for the initial send path2 over chan_2) fails.
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
+       // Ensure third monitor update (for the retry1's path1 over chan_1) succeeds, but the fourth (for
+       // the retry1's path2 over chan_3) fails, and monitor updates succeed after that.
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
+
+       // Configure the initial send, retry1 and retry2's paths.
+       let send_route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_1_id,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: amt_msat / 2,
+                               cltv_expiry_delta: 100,
+                       }],
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_2_id,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: amt_msat / 2,
+                               cltv_expiry_delta: 100,
+                       }],
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+       };
+       let retry_1_route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_1_id,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: amt_msat / 4,
+                               cltv_expiry_delta: 100,
+                       }],
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_3_id,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: amt_msat / 4,
+                               cltv_expiry_delta: 100,
+                       }],
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+       };
+       let retry_2_route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_1_id,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: amt_msat / 4,
+                               cltv_expiry_delta: 100,
+                       }],
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+       };
+       nodes[0].router.expect_find_route(Ok(send_route));
+       nodes[0].router.expect_find_route(Ok(retry_1_route));
+       nodes[0].router.expect_find_route(Ok(retry_2_route));
+
+       // Send a payment that will partially fail on send, then partially fail on retry, then succeed.
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(3)).unwrap();
+       let closed_chan_events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(closed_chan_events.len(), 2);
+       match closed_chan_events[0] {
+               Event::ChannelClosed { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+       match closed_chan_events[1] {
+               Event::ChannelClosed { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+
+       // Pass the first part of the payment along the path.
+       check_added_monitors!(nodes[0], 5); // three outbound channel updates succeeded, two permanently failed
+       let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+
+       // First message is the first update_add, remaining messages are broadcasting channel updates and
+       // errors for the permfailed channels
+       assert_eq!(msg_events.len(), 5);
+       let mut payment_event = SendEvent::from_event(msg_events.remove(0));
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg);
+       check_added_monitors!(nodes[1], 1);
+       let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
+       check_added_monitors!(nodes[0], 1);
+       let as_second_htlc_updates = SendEvent::from_node(&nodes[0]);
+
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_cs);
+       check_added_monitors!(nodes[0], 1);
+       let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_first_raa);
+       check_added_monitors!(nodes[1], 1);
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[0]);
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[1]);
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.commitment_msg);
+       check_added_monitors!(nodes[1], 1);
+       let (bs_second_raa, bs_second_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_cs);
+       check_added_monitors!(nodes[0], 1);
+       let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
+       check_added_monitors!(nodes[1], 1);
+
+       expect_pending_htlcs_forwardable_ignore!(nodes[1]);
+       nodes[1].node.process_pending_htlc_forwards();
+       expect_payment_claimable!(nodes[1], payment_hash, payment_secret, amt_msat);
+       nodes[1].node.claim_funds(payment_preimage);
+       expect_payment_claimed!(nodes[1], payment_hash, amt_msat);
+       let bs_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       assert_eq!(bs_claim_update.update_fulfill_htlcs.len(), 1);
+
+       nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_claim_update.update_fulfill_htlcs[0]);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_claim_update.commitment_signed);
+       check_added_monitors!(nodes[0], 1);
+       let (as_third_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_third_raa);
+       check_added_monitors!(nodes[1], 4);
+       let bs_second_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_third_cs);
+       check_added_monitors!(nodes[1], 1);
+       let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[0]);
+       nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[1]);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.commitment_signed);
+       check_added_monitors!(nodes[0], 1);
+       let (as_fourth_raa, as_fourth_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_fourth_raa);
+       check_added_monitors!(nodes[1], 1);
+
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_fourth_cs);
+       check_added_monitors!(nodes[1], 1);
+       let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
+       check_added_monitors!(nodes[0], 1);
+       expect_payment_sent!(nodes[0], payment_preimage);
+}
+
+#[test]
+fn auto_retry_zero_attempts_send_error() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+       create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+
+       // Marshall data to send the payment
+       let amt_msat = 20_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
+       let err = nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap_err();
+       if let PaymentSendFailure::AllFailedResendSafe(_) = err {
+       } else { panic!("Unexpected error"); }
+       assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 2); // channel close messages
+       assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 1); // channel close event
+       check_added_monitors!(nodes[0], 2);
+}
+
+#[test]
+fn fails_paying_after_rejected_by_payee() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
+
+       // Marshall data to send the payment
+       let amt_msat = 20_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       check_added_monitors!(nodes[0], 1);
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+       check_added_monitors!(nodes[1], 0);
+       commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+       expect_pending_htlcs_forwardable!(nodes[1]);
+       expect_payment_claimable!(&nodes[1], payment_hash, payment_secret, amt_msat);
+
+       nodes[1].node.fail_htlc_backwards(&payment_hash);
+       expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::FailedPayment { payment_hash }]);
+       pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, payment_hash);
+}
+
+#[test]
+fn retry_multi_path_single_failed_payment() {
+       // Tests that we can/will retry after a single path of an MPP payment failed immediately
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+       let chans = nodes[0].node.list_usable_channels();
+       let mut route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chans[0].short_channel_id.unwrap(),
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: 10_000,
+                               cltv_expiry_delta: 100,
+                       }],
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chans[1].short_channel_id.unwrap(),
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
+                               cltv_expiry_delta: 100,
+                       }],
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+       };
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+       // On retry, split the payment across both channels.
+       route.paths[0][0].fee_msat = 50_000_001;
+       route.paths[1][0].fee_msat = 50_000_000;
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+
+       let amt_msat = 100_010_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(htlc_msgs.len(), 2);
+       check_added_monitors!(nodes[0], 2);
+}
+
+#[test]
+fn immediate_retry_on_failure() {
+       // Tests that we can/will retry immediately after a failure
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+       let chans = nodes[0].node.list_usable_channels();
+       let mut route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chans[0].short_channel_id.unwrap(),
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
+                               cltv_expiry_delta: 100,
+                       }],
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+       };
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+       // On retry, split the payment across both channels.
+       route.paths.push(route.paths[0].clone());
+       route.paths[0][0].short_channel_id = chans[1].short_channel_id.unwrap();
+       route.paths[0][0].fee_msat = 50_000_000;
+       route.paths[1][0].fee_msat = 50_000_001;
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+
+       let amt_msat = 100_010_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(htlc_msgs.len(), 2);
+       check_added_monitors!(nodes[0], 2);
+}
+
+#[test]
+fn no_extra_retries_on_back_to_back_fail() {
+       // In a previous release, we had a race where we may exceed the payment retry count if we
+       // get two failures in a row with the second having `all_paths_failed` set.
+       // Generally, when we give up trying to retry a payment, we don't know for sure what the
+       // current state of the ChannelManager event queue is. Specifically, we cannot be sure that
+       // there are not multiple additional `PaymentPathFailed` or even `PaymentSent` events
+       // pending which we will see later. Thus, when we previously removed the retry tracking map
+       // entry after a `all_paths_failed` `PaymentPathFailed` event, we may have dropped the
+       // retry entry even though more events for the same payment were still pending. This led to
+       // us retrying a payment again even though we'd already given up on it.
+       //
+       // We now have a separate event - `PaymentFailed` which indicates no HTLCs remain and which
+       // is used to remove the payment retry counter entries instead. This tests for the specific
+       // excess-retry case while also testing `PaymentFailed` generation.
+
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+       let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0).0.contents.short_channel_id;
+       let chan_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 0).0.contents.short_channel_id;
+
+       let mut route = Route {
+               paths: vec![
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_1_scid,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: 0,
+                               cltv_expiry_delta: 100,
+                       }, RouteHop {
+                               pubkey: nodes[2].node.get_our_node_id(),
+                               node_features: nodes[2].node.node_features(),
+                               short_channel_id: chan_2_scid,
+                               channel_features: nodes[2].node.channel_features(),
+                               fee_msat: 100_000_000,
+                               cltv_expiry_delta: 100,
+                       }],
+                       vec![RouteHop {
+                               pubkey: nodes[1].node.get_our_node_id(),
+                               node_features: nodes[1].node.node_features(),
+                               short_channel_id: chan_1_scid,
+                               channel_features: nodes[1].node.channel_features(),
+                               fee_msat: 0,
+                               cltv_expiry_delta: 100,
+                       }, RouteHop {
+                               pubkey: nodes[2].node.get_our_node_id(),
+                               node_features: nodes[2].node.node_features(),
+                               short_channel_id: chan_2_scid,
+                               channel_features: nodes[2].node.channel_features(),
+                               fee_msat: 100_000_000,
+                               cltv_expiry_delta: 100,
+                       }]
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())),
+       };
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+       // On retry, we'll only be asked for one path
+       route.paths.remove(1);
+       nodes[0].router.expect_find_route(Ok(route.clone()));
+
+       let amt_msat = 100_010_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
+       #[cfg(feature = "std")]
+       let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
+       #[cfg(not(feature = "std"))]
+       let payment_expiry_secs = 60 * 60;
+       let mut invoice_features = InvoiceFeatures::empty();
+       invoice_features.set_variable_length_onion_required();
+       invoice_features.set_payment_secret_required();
+       invoice_features.set_basic_mpp_optional();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       let htlc_updates = SendEvent::from_node(&nodes[0]);
+       check_added_monitors!(nodes[0], 1);
+       assert_eq!(htlc_updates.msgs.len(), 1);
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &htlc_updates.msgs[0]);
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &htlc_updates.commitment_msg);
+       check_added_monitors!(nodes[1], 1);
+       let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
+       check_added_monitors!(nodes[0], 1);
+       let second_htlc_updates = SendEvent::from_node(&nodes[0]);
+
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_cs);
+       check_added_monitors!(nodes[0], 1);
+       let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]);
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &second_htlc_updates.commitment_msg);
+       check_added_monitors!(nodes[1], 1);
+       let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_first_raa);
+       check_added_monitors!(nodes[1], 1);
+       let bs_fail_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_fail_update.commitment_signed);
+       check_added_monitors!(nodes[0], 1);
+       let (as_second_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
+       check_added_monitors!(nodes[1], 1);
+       let bs_second_fail_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_third_cs);
+       check_added_monitors!(nodes[1], 1);
+       let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_second_fail_update.update_fail_htlcs[0]);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_fail_update.commitment_signed);
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
+       check_added_monitors!(nodes[0], 1);
+       let (as_third_raa, as_fourth_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_third_raa);
+       check_added_monitors!(nodes[1], 1);
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_fourth_cs);
+       check_added_monitors!(nodes[1], 1);
+       let bs_fourth_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_fourth_raa);
+       check_added_monitors!(nodes[0], 1);
+
+       // At this point A has sent two HTLCs which both failed due to lack of fee. It now has two
+       // pending `PaymentPathFailed` events, one with `all_paths_failed` unset, and the second
+       // with it set. The first event will use up the only retry we are allowed, with the second
+       // `PaymentPathFailed` being passed up to the user (us, in this case). Previously, we'd
+       // treated this as "HTLC complete" and dropped the retry counter, causing us to retry again
+       // if the final HTLC failed.
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 4);
+       match events[0] {
+               Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
+                       assert_eq!(payment_hash, ev_payment_hash);
+                       assert_eq!(payment_failed_permanently, false);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       match events[1] {
+               Event::PendingHTLCsForwardable { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+       match events[2] {
+               Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
+                       assert_eq!(payment_hash, ev_payment_hash);
+                       assert_eq!(payment_failed_permanently, false);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       match events[3] {
+               Event::PendingHTLCsForwardable { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+
+       nodes[0].node.process_pending_htlc_forwards();
+       let retry_htlc_updates = SendEvent::from_node(&nodes[0]);
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &retry_htlc_updates.msgs[0]);
+       commitment_signed_dance!(nodes[1], nodes[0], &retry_htlc_updates.commitment_msg, false, true);
+       let bs_fail_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]);
+       commitment_signed_dance!(nodes[0], nodes[1], &bs_fail_update.commitment_signed, false, true);
+
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events[0] {
+               Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
+                       assert_eq!(payment_hash, ev_payment_hash);
+                       assert_eq!(payment_failed_permanently, false);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       nodes[0].node.abandon_payment(PaymentId(payment_hash.0));
+       events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events[0] {
+               Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id } => {
+                       assert_eq!(payment_hash, *ev_payment_hash);
+                       assert_eq!(PaymentId(payment_hash.0), *ev_payment_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
+}
index 277b0faf6a0d4e81f488a40b440de9d09940caad..4632007a0adcc04ce2273d7aacf216786fea0336 100644 (file)
@@ -9,6 +9,7 @@
 
 use crate::prelude::*;
 
+use crate::chain::keysinterface::{NodeSigner, Recipient};
 use crate::ln::msgs::LightningError;
 use crate::ln::msgs;
 use crate::ln::wire;
@@ -26,6 +27,8 @@ use crate::util::crypto::hkdf_extract_expand_twice;
 use crate::util::ser::VecWriter;
 use bitcoin::hashes::hex::ToHex;
 
+use core::ops::Deref;
+
 /// Maximum Lightning message data length according to
 /// [BOLT-8](https://github.com/lightning/bolts/blob/v1.0/08-transport.md#lightning-message-specification)
 /// and [BOLT-1](https://github.com/lightning/bolts/blob/master/01-messaging.md#lightning-message-format):
@@ -36,6 +39,11 @@ const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29
 // Sha256(NOISE_CK || "lightning")
 const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76];
 
+enum NoiseSecretKey<'a, 'b, NS: Deref> where NS::Target: NodeSigner {
+       InMemory(&'a SecretKey),
+       NodeSigner(&'b NS)
+}
+
 pub enum NextNoiseStep {
        ActOne,
        ActTwo,
@@ -109,10 +117,10 @@ impl PeerChannelEncryptor {
                }
        }
 
-       pub fn new_inbound<C: secp256k1::Signing>(our_node_secret: &SecretKey, secp_ctx: &Secp256k1<C>) -> PeerChannelEncryptor {
+       pub fn new_inbound<NS: Deref>(node_signer: &NS) -> PeerChannelEncryptor where NS::Target: NodeSigner {
                let mut sha = Sha256::engine();
                sha.input(&NOISE_H);
-               let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret);
+               let our_node_id = node_signer.get_node_id(Recipient::Node).unwrap();
                sha.input(&our_node_id.serialize()[..]);
                let h = Sha256::from_engine(sha).into_inner();
 
@@ -201,7 +209,9 @@ impl PeerChannelEncryptor {
        }
 
        #[inline]
-       fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), LightningError> {
+       fn inbound_noise_act<'a, 'b, NS: Deref>(
+               state: &mut BidirectionalNoiseState, act: &[u8], secret_key: NoiseSecretKey<'a, 'b, NS>
+       ) -> Result<(PublicKey, [u8; 32]), LightningError> where NS::Target: NodeSigner {
                assert_eq!(act.len(), 50);
 
                if act[0] != 0 {
@@ -218,7 +228,15 @@ impl PeerChannelEncryptor {
                sha.input(&their_pub.serialize()[..]);
                state.h = Sha256::from_engine(sha).into_inner();
 
-               let ss = SharedSecret::new(&their_pub, &our_key);
+               let ss = match secret_key {
+                       NoiseSecretKey::InMemory(secret_key) => SharedSecret::new(&their_pub, secret_key),
+                       NoiseSecretKey::NodeSigner(node_signer) => node_signer
+                               .ecdh(Recipient::Node, &their_pub, None)
+                               .map_err(|_| LightningError {
+                                       err: "Failed to derive shared secret".to_owned(),
+                                       action: msgs::ErrorAction::DisconnectPeer { msg: None }
+                               })?,
+               };
                let temp_k = PeerChannelEncryptor::hkdf(state, ss);
 
                let mut dec = [0; 0];
@@ -251,9 +269,9 @@ impl PeerChannelEncryptor {
                }
        }
 
-       pub fn process_act_one_with_keys<C: secp256k1::Signing>(
-               &mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey, secp_ctx: &Secp256k1<C>)
-       -> Result<[u8; 50], LightningError> {
+       pub fn process_act_one_with_keys<C: secp256k1::Signing, NS: Deref>(
+               &mut self, act_one: &[u8], node_signer: &NS, our_ephemeral: SecretKey, secp_ctx: &Secp256k1<C>)
+       -> Result<[u8; 50], LightningError> where NS::Target: NodeSigner {
                assert_eq!(act_one.len(), 50);
 
                match self.noise_state {
@@ -264,7 +282,7 @@ impl PeerChannelEncryptor {
                                                        panic!("Requested act at wrong step");
                                                }
 
-                                               let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, &our_node_secret)?;
+                                               let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, NoiseSecretKey::NodeSigner(node_signer))?;
                                                ie.get_or_insert(their_pub);
 
                                                re.get_or_insert(our_ephemeral);
@@ -281,9 +299,9 @@ impl PeerChannelEncryptor {
                }
        }
 
-       pub fn process_act_two<C: secp256k1::Signing>(
-               &mut self, act_two: &[u8], our_node_secret: &SecretKey, secp_ctx: &Secp256k1<C>)
-       -> Result<([u8; 66], PublicKey), LightningError> {
+       pub fn process_act_two<NS: Deref>(
+               &mut self, act_two: &[u8], node_signer: &NS)
+       -> Result<([u8; 66], PublicKey), LightningError> where NS::Target: NodeSigner {
                assert_eq!(act_two.len(), 50);
 
                let final_hkdf;
@@ -296,10 +314,13 @@ impl PeerChannelEncryptor {
                                                        panic!("Requested act at wrong step");
                                                }
 
-                                               let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, &ie)?;
+                                               let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, NoiseSecretKey::<NS>::InMemory(&ie))?;
 
                                                let mut res = [0; 66];
-                                               let our_node_id = PublicKey::from_secret_key(secp_ctx, &our_node_secret);
+                                               let our_node_id = node_signer.get_node_id(Recipient::Node).map_err(|_| LightningError {
+                                                       err: "Failed to encrypt message".to_owned(),
+                                                       action: msgs::ErrorAction::DisconnectPeer { msg: None }
+                                               })?;
 
                                                PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]);
 
@@ -308,7 +329,10 @@ impl PeerChannelEncryptor {
                                                sha.input(&res[1..50]);
                                                bidirectional_state.h = Sha256::from_engine(sha).into_inner();
 
-                                               let ss = SharedSecret::new(&re, our_node_secret);
+                                               let ss = node_signer.ecdh(Recipient::Node, &re, None).map_err(|_| LightningError {
+                                                       err: "Failed to derive shared secret".to_owned(),
+                                                       action: msgs::ErrorAction::DisconnectPeer { msg: None }
+                                               })?;
                                                let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss);
 
                                                PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]);
@@ -522,12 +546,13 @@ impl PeerChannelEncryptor {
 mod tests {
        use super::LN_MAX_MSG_LEN;
 
-       use bitcoin::secp256k1::{PublicKey,SecretKey};
+       use bitcoin::secp256k1::{PublicKey, SecretKey};
        use bitcoin::secp256k1::Secp256k1;
 
        use hex;
 
        use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState};
+       use crate::util::test_utils::TestNodeSigner;
 
        fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor {
                let their_node_id = PublicKey::from_slice(&hex::decode("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap();
@@ -542,12 +567,13 @@ mod tests {
                // transport-responder successful handshake
                let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap();
                let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap();
-               let secp_ctx = Secp256k1::signing_only();
+               let secp_ctx = Secp256k1::new();
+               let node_signer = TestNodeSigner::new(our_node_id);
 
-               let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+               let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-               assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+               assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
 
                let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
                // test vector doesn't specify the initiator static key, but it's the same as the one
@@ -572,14 +598,14 @@ mod tests {
        #[test]
        fn noise_initiator_test_vectors() {
                let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
-               let secp_ctx = Secp256k1::signing_only();
+               let node_signer = TestNodeSigner::new(our_node_id);
 
                {
                        // transport-initiator successful handshake
                        let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
 
                        let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
-                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
+                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
 
                        match outbound_peer.noise_state {
                                NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
@@ -602,7 +628,7 @@ mod tests {
                        let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
 
                        let act_two = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
-                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err());
+                       assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err());
                }
 
                {
@@ -610,7 +636,7 @@ mod tests {
                        let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
 
                        let act_two = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
-                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err());
+                       assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err());
                }
 
                {
@@ -618,7 +644,7 @@ mod tests {
                        let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
 
                        let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec();
-                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err());
+                       assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err());
                }
        }
 
@@ -626,7 +652,8 @@ mod tests {
        fn noise_responder_test_vectors() {
                let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap();
                let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap();
-               let secp_ctx = Secp256k1::signing_only();
+               let secp_ctx = Secp256k1::new();
+               let node_signer = TestNodeSigner::new(our_node_id);
 
                {
                        let _ = get_inbound_peer_for_test_vectors();
@@ -637,31 +664,31 @@ mod tests {
                }
                {
                        // transport-responder act1 bad version test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err());
+                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err());
                }
                {
                        // transport-responder act1 bad key serialization test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err());
+                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err());
                }
                {
                        // transport-responder act1 bad MAC test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec();
-                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err());
+                       assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err());
                }
                {
                        // transport-responder act3 bad version test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
 
                        let act_three = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
                        assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
@@ -672,30 +699,30 @@ mod tests {
                }
                {
                        // transport-responder act3 bad MAC for ciphertext test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
 
                        let act_three = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
                        assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
                }
                {
                        // transport-responder act3 bad rs test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
 
                        let act_three = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec();
                        assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
                }
                {
                        // transport-responder act3 bad MAC test
-                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx);
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer);
 
                        let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
-                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+                       assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
 
                        let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec();
                        assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
@@ -708,13 +735,13 @@ mod tests {
                // We use the same keys as the initiator and responder test vectors, so we copy those tests
                // here and use them to encrypt.
                let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
-               let secp_ctx = Secp256k1::signing_only();
 
                {
                        let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
+                       let node_signer = TestNodeSigner::new(our_node_id);
 
                        let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
-                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
+                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
 
                        match outbound_peer.noise_state {
                                NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
index dffda9967badfe28b5afb3d2ebc0a3a4457e18fd..a63f764cd8f839c3afeae5febae6bc05231a5455 100644 (file)
@@ -17,6 +17,7 @@
 
 use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
 
+use crate::chain::keysinterface::{KeysManager, NodeSigner, Recipient};
 use crate::ln::features::{InitFeatures, NodeFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler, LightningError, NetAddress, OnionMessageHandler, RoutingMessageHandler};
@@ -28,7 +29,6 @@ use crate::ln::wire::Encode;
 use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
 use crate::routing::gossip::{NetworkGraph, P2PGossipSync};
 use crate::util::atomic_counter::AtomicCounter;
-use crate::util::crypto::sign;
 use crate::util::events::{MessageSendEvent, MessageSendEventsProvider, OnionMessageProvider};
 use crate::util::logger::Logger;
 
@@ -43,7 +43,6 @@ use core::convert::Infallible;
 #[cfg(feature = "std")] use std::error;
 
 use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::sha256::HashEngine as Sha256Engine;
 use bitcoin::hashes::{HashEngine, Hash};
 
@@ -491,7 +490,7 @@ impl Peer {
 /// issues such as overly long function definitions.
 ///
 /// (C-not exported) as `Arc`s don't make sense in bindings.
-pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, Arc<SimpleArcOnionMessenger<L>>, Arc<L>, IgnoringMessageHandler>;
+pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, Arc<SimpleArcOnionMessenger<L>>, Arc<L>, IgnoringMessageHandler, Arc<KeysManager>>;
 
 /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference
 /// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't
@@ -501,7 +500,7 @@ pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArc
 /// helps with issues such as long function definitions.
 ///
 /// (C-not exported) as general type aliases don't make sense in bindings.
-pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'm, M, T, F, L>, &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler>;
+pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'm, M, T, F, L>, &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler, &'c KeysManager>;
 
 /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
 /// socket events into messages which it passes on to its [`MessageHandler`].
@@ -522,12 +521,13 @@ pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm
 /// you're using lightning-net-tokio.
 ///
 /// [`read_event`]: PeerManager::read_event
-pub struct PeerManager<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CMH: Deref> where
+pub struct PeerManager<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CMH: Deref, NS: Deref> where
                CM::Target: ChannelMessageHandler,
                RM::Target: RoutingMessageHandler,
                OM::Target: OnionMessageHandler,
                L::Target: Logger,
-               CMH::Target: CustomMessageHandler {
+               CMH::Target: CustomMessageHandler,
+               NS::Target: NodeSigner {
        message_handler: MessageHandler<CM, RM, OM>,
        /// Connection state for each connected peer - we have an outer read-write lock which is taken
        /// as read while we're doing processing for a peer and taken write when a peer is being added
@@ -557,12 +557,13 @@ pub struct PeerManager<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: D
        /// value increases strictly since we don't assume access to a time source.
        last_node_announcement_serial: AtomicU32,
 
-       our_node_secret: SecretKey,
        ephemeral_key_midstate: Sha256Engine,
        custom_message_handler: CMH,
 
        peer_counter: AtomicCounter,
 
+       node_signer: NS,
+
        logger: L,
        secp_ctx: Secp256k1<secp256k1::SignOnly>
 }
@@ -592,10 +593,11 @@ macro_rules! encode_msg {
        }}
 }
 
-impl<Descriptor: SocketDescriptor, CM: Deref, OM: Deref, L: Deref> PeerManager<Descriptor, CM, IgnoringMessageHandler, OM, L, IgnoringMessageHandler> where
+impl<Descriptor: SocketDescriptor, CM: Deref, OM: Deref, L: Deref, NS: Deref> PeerManager<Descriptor, CM, IgnoringMessageHandler, OM, L, IgnoringMessageHandler, NS> where
                CM::Target: ChannelMessageHandler,
                OM::Target: OnionMessageHandler,
-               L::Target: Logger {
+               L::Target: Logger,
+               NS::Target: NodeSigner {
        /// Constructs a new `PeerManager` with the given `ChannelMessageHandler` and
        /// `OnionMessageHandler`. No routing message handler is used and network graph messages are
        /// ignored.
@@ -609,18 +611,19 @@ impl<Descriptor: SocketDescriptor, CM: Deref, OM: Deref, L: Deref> PeerManager<D
        /// minute should suffice.
        ///
        /// (C-not exported) as we can't export a PeerManager with a dummy route handler
-       pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
+       pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self {
                Self::new(MessageHandler {
                        chan_handler: channel_message_handler,
                        route_handler: IgnoringMessageHandler{},
                        onion_message_handler,
-               }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{})
+               }, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}, node_signer)
        }
 }
 
-impl<Descriptor: SocketDescriptor, RM: Deref, L: Deref> PeerManager<Descriptor, ErroringMessageHandler, RM, IgnoringMessageHandler, L, IgnoringMessageHandler> where
+impl<Descriptor: SocketDescriptor, RM: Deref, L: Deref, NS: Deref> PeerManager<Descriptor, ErroringMessageHandler, RM, IgnoringMessageHandler, L, IgnoringMessageHandler, NS> where
                RM::Target: RoutingMessageHandler,
-               L::Target: Logger {
+               L::Target: Logger,
+               NS::Target: NodeSigner {
        /// Constructs a new `PeerManager` with the given `RoutingMessageHandler`. No channel message
        /// handler or onion message handler is used and onion and channel messages will be ignored (or
        /// generate error messages). Note that some other lightning implementations time-out connections
@@ -635,12 +638,12 @@ impl<Descriptor: SocketDescriptor, RM: Deref, L: Deref> PeerManager<Descriptor,
        /// cryptographically secure random bytes.
        ///
        /// (C-not exported) as we can't export a PeerManager with a dummy channel handler
-       pub fn new_routing_only(routing_message_handler: RM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
+       pub fn new_routing_only(routing_message_handler: RM, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self {
                Self::new(MessageHandler {
                        chan_handler: ErroringMessageHandler::new(),
                        route_handler: routing_message_handler,
                        onion_message_handler: IgnoringMessageHandler{},
-               }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{})
+               }, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}, node_signer)
        }
 }
 
@@ -685,12 +688,14 @@ fn filter_addresses(ip_address: Option<NetAddress>) -> Option<NetAddress> {
        }
 }
 
-impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CMH: Deref> PeerManager<Descriptor, CM, RM, OM, L, CMH> where
+impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CMH: Deref, NS: Deref> PeerManager<Descriptor, CM, RM, OM, L, CMH, NS> where
                CM::Target: ChannelMessageHandler,
                RM::Target: RoutingMessageHandler,
                OM::Target: OnionMessageHandler,
                L::Target: Logger,
-               CMH::Target: CustomMessageHandler {
+               CMH::Target: CustomMessageHandler,
+               NS::Target: NodeSigner
+{
        /// Constructs a new PeerManager with the given message handlers and node_id secret key
        /// ephemeral_random_data is used to derive per-connection ephemeral keys and must be
        /// cryptographically secure random bytes.
@@ -699,7 +704,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
        /// incremented irregularly internally. In general it is best to simply use the current UNIX
        /// timestamp, however if it is not available a persistent counter that increases once per
        /// minute should suffice.
-       pub fn new(message_handler: MessageHandler<CM, RM, OM>, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self {
+       pub fn new(message_handler: MessageHandler<CM, RM, OM>, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH, node_signer: NS) -> Self {
                let mut ephemeral_key_midstate = Sha256::engine();
                ephemeral_key_midstate.input(ephemeral_random_data);
 
@@ -713,12 +718,12 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        node_id_to_descriptor: Mutex::new(HashMap::new()),
                        event_processing_lock: Mutex::new(()),
                        blocked_event_processors: AtomicBool::new(false),
-                       our_node_secret,
                        ephemeral_key_midstate,
                        peer_counter: AtomicCounter::new(),
                        last_node_announcement_serial: AtomicU32::new(current_time),
                        logger,
                        custom_message_handler,
+                       node_signer,
                        secp_ctx,
                }
        }
@@ -810,7 +815,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
        ///
        /// [`socket_disconnected()`]: PeerManager::socket_disconnected
        pub fn new_inbound_connection(&self, descriptor: Descriptor, remote_network_address: Option<NetAddress>) -> Result<(), PeerHandleError> {
-               let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret, &self.secp_ctx);
+               let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.node_signer);
                let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes
 
                let mut peers = self.peers.write().unwrap();
@@ -1079,14 +1084,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                        NextNoiseStep::ActOne => {
                                                                let act_two = try_potential_handleerror!(peer, peer.channel_encryptor
                                                                        .process_act_one_with_keys(&peer.pending_read_buffer[..],
-                                                                               &self.our_node_secret, self.get_ephemeral_key(), &self.secp_ctx)).to_vec();
+                                                                               &self.node_signer, self.get_ephemeral_key(), &self.secp_ctx)).to_vec();
                                                                peer.pending_outbound_buffer.push_back(act_two);
                                                                peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long
                                                        },
                                                        NextNoiseStep::ActTwo => {
                                                                let (act_three, their_node_id) = try_potential_handleerror!(peer,
                                                                        peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..],
-                                                                               &self.our_node_secret, &self.secp_ctx));
+                                                                               &self.node_signer));
                                                                peer.pending_outbound_buffer.push_back(act_three.to_vec());
                                                                peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
                                                                peer.pending_read_is_header = true;
@@ -2016,13 +2021,20 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                let announcement = msgs::UnsignedNodeAnnouncement {
                        features,
                        timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel),
-                       node_id: PublicKey::from_secret_key(&self.secp_ctx, &self.our_node_secret),
+                       node_id: self.node_signer.get_node_id(Recipient::Node).unwrap(),
                        rgb, alias, addresses,
                        excess_address_data: Vec::new(),
                        excess_data: Vec::new(),
                };
-               let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
-               let node_announce_sig = sign(&self.secp_ctx, &msghash, &self.our_node_secret);
+               let node_announce_sig = match self.node_signer.sign_gossip_message(
+                       msgs::UnsignedGossipMessage::NodeAnnouncement(&announcement)
+               ) {
+                       Ok(sig) => sig,
+                       Err(_) => {
+                               log_error!(self.logger, "Failed to generate signature for node_announcement");
+                               return;
+                       },
+               };
 
                let msg = msgs::NodeAnnouncement {
                        signature: node_announce_sig,
@@ -2050,14 +2062,14 @@ fn is_gossip_msg(type_id: u16) -> bool {
 
 #[cfg(test)]
 mod tests {
+       use crate::chain::keysinterface::{NodeSigner, Recipient};
        use crate::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler, filter_addresses};
        use crate::ln::{msgs, wire};
        use crate::ln::msgs::NetAddress;
        use crate::util::events;
        use crate::util::test_utils;
 
-       use bitcoin::secp256k1::Secp256k1;
-       use bitcoin::secp256k1::{SecretKey, PublicKey};
+       use bitcoin::secp256k1::SecretKey;
 
        use crate::prelude::*;
        use crate::sync::{Arc, Mutex};
@@ -2093,16 +2105,19 @@ mod tests {
                chan_handler: test_utils::TestChannelMessageHandler,
                routing_handler: test_utils::TestRoutingMessageHandler,
                logger: test_utils::TestLogger,
+               node_signer: test_utils::TestNodeSigner,
        }
 
        fn create_peermgr_cfgs(peer_count: usize) -> Vec<PeerManagerCfg> {
                let mut cfgs = Vec::new();
-               for _ in 0..peer_count {
+               for i in 0..peer_count {
+                       let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap();
                        cfgs.push(
                                PeerManagerCfg{
                                        chan_handler: test_utils::TestChannelMessageHandler::new(),
                                        logger: test_utils::TestLogger::new(),
                                        routing_handler: test_utils::TestRoutingMessageHandler::new(),
+                                       node_signer: test_utils::TestNodeSigner::new(node_secret),
                                }
                        );
                }
@@ -2110,22 +2125,20 @@ mod tests {
                cfgs
        }
 
-       fn create_network<'a>(peer_count: usize, cfgs: &'a Vec<PeerManagerCfg>) -> Vec<PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler>> {
+       fn create_network<'a>(peer_count: usize, cfgs: &'a Vec<PeerManagerCfg>) -> Vec<PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler, &'a test_utils::TestNodeSigner>> {
                let mut peers = Vec::new();
                for i in 0..peer_count {
-                       let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap();
                        let ephemeral_bytes = [i as u8; 32];
                        let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler, onion_message_handler: IgnoringMessageHandler {} };
-                       let peer = PeerManager::new(msg_handler, node_secret, 0, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {});
+                       let peer = PeerManager::new(msg_handler, 0, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {}, &cfgs[i].node_signer);
                        peers.push(peer);
                }
 
                peers
        }
 
-       fn establish_connection<'a>(peer_a: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler>, peer_b: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler>) -> (FileDescriptor, FileDescriptor) {
-               let secp_ctx = Secp256k1::new();
-               let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.our_node_secret);
+       fn establish_connection<'a>(peer_a: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler, &'a test_utils::TestNodeSigner>, peer_b: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, IgnoringMessageHandler, &'a test_utils::TestLogger, IgnoringMessageHandler, &'a test_utils::TestNodeSigner>) -> (FileDescriptor, FileDescriptor) {
+               let a_id = peer_a.node_signer.get_node_id(Recipient::Node).unwrap();
                let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) };
                let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) };
                let initial_data = peer_b.new_outbound_connection(a_id, fd_b.clone(), None).unwrap();
@@ -2157,8 +2170,7 @@ mod tests {
                establish_connection(&peers[0], &peers[1]);
                assert_eq!(peers[0].peers.read().unwrap().len(), 1);
 
-               let secp_ctx = Secp256k1::new();
-               let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret);
+               let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap();
 
                chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError {
                        node_id: their_id,
@@ -2182,8 +2194,7 @@ mod tests {
                let (fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]);
                assert_eq!(peers[0].peers.read().unwrap().len(), 1);
 
-               let secp_ctx = Secp256k1::new();
-               let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret);
+               let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap();
 
                let msg = msgs::Shutdown { channel_id: [42; 32], scriptpubkey: bitcoin::Script::new() };
                a_chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::SendShutdown {
@@ -2283,8 +2294,7 @@ mod tests {
                cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release);
                let peers = create_network(2, &cfgs);
 
-               let secp_ctx = Secp256k1::new();
-               let a_id = PublicKey::from_secret_key(&secp_ctx, &peers[0].our_node_secret);
+               let a_id = peers[0].node_signer.get_node_id(Recipient::Node).unwrap();
                let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) };
                let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) };
                let initial_data = peers[1].new_outbound_connection(a_id, fd_b.clone(), None).unwrap();
index 9bfed7e2c2029547f5fcf603c7a9c684181c48f0..aca781b9fd6f50ef2908d4fa518678c932ec522f 100644 (file)
@@ -12,7 +12,7 @@
 //! LSP).
 
 use crate::chain::ChannelMonitorUpdateStatus;
-use crate::chain::keysinterface::{Recipient, NodeSigner};
+use crate::chain::keysinterface::NodeSigner;
 use crate::ln::channelmanager::{ChannelManager, MIN_CLTV_EXPIRY_DELTA, PaymentId};
 use crate::routing::gossip::RoutingFees;
 use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop};
@@ -31,10 +31,7 @@ use core::default::Default;
 use crate::ln::functional_test_utils::*;
 
 use bitcoin::blockdata::constants::genesis_block;
-use bitcoin::hashes::Hash;
-use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::Secp256k1;
 
 #[test]
 fn test_priv_forwarding_rejection() {
@@ -493,8 +490,7 @@ fn test_scid_alias_returned() {
                fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths,
                excess_data: Vec::new(),
        };
-       let msg_hash = Sha256dHash::hash(&contents.encode()[..]);
-       let signature = Secp256k1::new().sign_ecdsa(&hash_to_message!(&msg_hash[..]), &nodes[1].keys_manager.get_node_secret(Recipient::Node).unwrap());
+       let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)).unwrap();
        let msg = msgs::ChannelUpdate { signature, contents };
 
        let mut err_data = Vec::new();
index 144b0e711b2646636cd55831fc2ca439aaf72ee7..1309baf60eac7ed85a5493ec8ca102653cad6eb6 100644 (file)
@@ -30,8 +30,7 @@ struct MessengerNode {
 
 impl MessengerNode {
        fn get_node_pk(&self) -> PublicKey {
-               let secp_ctx = Secp256k1::new();
-               PublicKey::from_secret_key(&secp_ctx, &self.keys_manager.get_node_secret(Recipient::Node).unwrap())
+               self.keys_manager.get_node_id(Recipient::Node).unwrap()
        }
 }
 
index 39f07914a61a11541b055fe9cabafc6a7dcce43d..950782d46f665bae2e0dd3baff42633456e3ec2d 100644 (file)
@@ -32,11 +32,11 @@ use crate::util::logger::{Logger, Level};
 use crate::util::events::{MessageSendEvent, MessageSendEventsProvider};
 use crate::util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
 use crate::util::string::PrintableString;
+use crate::util::indexed_map::{IndexedMap, Entry as IndexedMapEntry};
 
 use crate::io;
 use crate::io_extras::{copy, sink};
 use crate::prelude::*;
-use alloc::collections::{BTreeMap, btree_map::Entry as BtreeEntry};
 use core::{cmp, fmt};
 use crate::sync::{RwLock, RwLockReadGuard};
 #[cfg(feature = "std")]
@@ -133,8 +133,8 @@ pub struct NetworkGraph<L: Deref> where L::Target: Logger {
        genesis_hash: BlockHash,
        logger: L,
        // Lock order: channels -> nodes
-       channels: RwLock<BTreeMap<u64, ChannelInfo>>,
-       nodes: RwLock<BTreeMap<NodeId, NodeInfo>>,
+       channels: RwLock<IndexedMap<u64, ChannelInfo>>,
+       nodes: RwLock<IndexedMap<NodeId, NodeInfo>>,
        // Lock order: removed_channels -> removed_nodes
        //
        // NOTE: In the following `removed_*` maps, we use seconds since UNIX epoch to track time instead
@@ -158,8 +158,8 @@ pub struct NetworkGraph<L: Deref> where L::Target: Logger {
 
 /// A read-only view of [`NetworkGraph`].
 pub struct ReadOnlyNetworkGraph<'a> {
-       channels: RwLockReadGuard<'a, BTreeMap<u64, ChannelInfo>>,
-       nodes: RwLockReadGuard<'a, BTreeMap<NodeId, NodeInfo>>,
+       channels: RwLockReadGuard<'a, IndexedMap<u64, ChannelInfo>>,
+       nodes: RwLockReadGuard<'a, IndexedMap<NodeId, NodeInfo>>,
 }
 
 /// Update to the [`NetworkGraph`] based on payment failure information conveyed via the Onion
@@ -1054,10 +1054,6 @@ impl Readable for NodeAlias {
 pub struct NodeInfo {
        /// All valid channels a node has announced
        pub channels: Vec<u64>,
-       /// Lowest fees enabling routing via any of the enabled, known channels to a node.
-       /// The two fields (flat and proportional fee) are independent,
-       /// meaning they don't have to refer to the same channel.
-       pub lowest_inbound_channel_fees: Option<RoutingFees>,
        /// More information about a node from node_announcement.
        /// Optional because we store a Node entry after learning about it from
        /// a channel announcement, but before receiving a node announcement.
@@ -1066,8 +1062,8 @@ pub struct NodeInfo {
 
 impl fmt::Display for NodeInfo {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-               write!(f, "lowest_inbound_channel_fees: {:?}, channels: {:?}, announcement_info: {:?}",
-                  self.lowest_inbound_channel_fees, &self.channels[..], self.announcement_info)?;
+               write!(f, " channels: {:?}, announcement_info: {:?}",
+                       &self.channels[..], self.announcement_info)?;
                Ok(())
        }
 }
@@ -1075,7 +1071,7 @@ impl fmt::Display for NodeInfo {
 impl Writeable for NodeInfo {
        fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                write_tlv_fields!(writer, {
-                       (0, self.lowest_inbound_channel_fees, option),
+                       // Note that older versions of LDK wrote the lowest inbound fees here at type 0
                        (2, self.announcement_info, option),
                        (4, self.channels, vec_type),
                });
@@ -1103,18 +1099,22 @@ impl MaybeReadable for NodeAnnouncementInfoDeserWrapper {
 
 impl Readable for NodeInfo {
        fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               _init_tlv_field_var!(lowest_inbound_channel_fees, option);
+               // Historically, we tracked the lowest inbound fees for any node in order to use it as an
+               // A* heuristic when routing. Sadly, these days many, many nodes have at least one channel
+               // with zero inbound fees, causing that heuristic to provide little gain. Worse, because it
+               // requires additional complexity and lookups during routing, it ends up being a
+               // performance loss. Thus, we simply ignore the old field here and no longer track it.
+               let mut _lowest_inbound_channel_fees: Option<RoutingFees> = None;
                let mut announcement_info_wrap: Option<NodeAnnouncementInfoDeserWrapper> = None;
                _init_tlv_field_var!(channels, vec_type);
 
                read_tlv_fields!(reader, {
-                       (0, lowest_inbound_channel_fees, option),
+                       (0, _lowest_inbound_channel_fees, option),
                        (2, announcement_info_wrap, ignorable),
                        (4, channels, vec_type),
                });
 
                Ok(NodeInfo {
-                       lowest_inbound_channel_fees: _init_tlv_based_struct_field!(lowest_inbound_channel_fees, option),
                        announcement_info: announcement_info_wrap.map(|w| w.0),
                        channels: _init_tlv_based_struct_field!(channels, vec_type),
                })
@@ -1131,13 +1131,13 @@ impl<L: Deref> Writeable for NetworkGraph<L> where L::Target: Logger {
                self.genesis_hash.write(writer)?;
                let channels = self.channels.read().unwrap();
                (channels.len() as u64).write(writer)?;
-               for (ref chan_id, ref chan_info) in channels.iter() {
+               for (ref chan_id, ref chan_info) in channels.unordered_iter() {
                        (*chan_id).write(writer)?;
                        chan_info.write(writer)?;
                }
                let nodes = self.nodes.read().unwrap();
                (nodes.len() as u64).write(writer)?;
-               for (ref node_id, ref node_info) in nodes.iter() {
+               for (ref node_id, ref node_info) in nodes.unordered_iter() {
                        node_id.write(writer)?;
                        node_info.write(writer)?;
                }
@@ -1156,14 +1156,14 @@ impl<L: Deref> ReadableArgs<L> for NetworkGraph<L> where L::Target: Logger {
 
                let genesis_hash: BlockHash = Readable::read(reader)?;
                let channels_count: u64 = Readable::read(reader)?;
-               let mut channels = BTreeMap::new();
+               let mut channels = IndexedMap::new();
                for _ in 0..channels_count {
                        let chan_id: u64 = Readable::read(reader)?;
                        let chan_info = Readable::read(reader)?;
                        channels.insert(chan_id, chan_info);
                }
                let nodes_count: u64 = Readable::read(reader)?;
-               let mut nodes = BTreeMap::new();
+               let mut nodes = IndexedMap::new();
                for _ in 0..nodes_count {
                        let node_id = Readable::read(reader)?;
                        let node_info = Readable::read(reader)?;
@@ -1191,11 +1191,11 @@ impl<L: Deref> ReadableArgs<L> for NetworkGraph<L> where L::Target: Logger {
 impl<L: Deref> fmt::Display for NetworkGraph<L> where L::Target: Logger {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                writeln!(f, "Network map\n[Channels]")?;
-               for (key, val) in self.channels.read().unwrap().iter() {
+               for (key, val) in self.channels.read().unwrap().unordered_iter() {
                        writeln!(f, " {}: {}", key, val)?;
                }
                writeln!(f, "[Nodes]")?;
-               for (&node_id, val) in self.nodes.read().unwrap().iter() {
+               for (&node_id, val) in self.nodes.read().unwrap().unordered_iter() {
                        writeln!(f, " {}: {}", log_bytes!(node_id.as_slice()), val)?;
                }
                Ok(())
@@ -1218,8 +1218,8 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        secp_ctx: Secp256k1::verification_only(),
                        genesis_hash,
                        logger,
-                       channels: RwLock::new(BTreeMap::new()),
-                       nodes: RwLock::new(BTreeMap::new()),
+                       channels: RwLock::new(IndexedMap::new()),
+                       nodes: RwLock::new(IndexedMap::new()),
                        last_rapid_gossip_sync_timestamp: Mutex::new(None),
                        removed_channels: Mutex::new(HashMap::new()),
                        removed_nodes: Mutex::new(HashMap::new()),
@@ -1252,7 +1252,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        /// purposes.
        #[cfg(test)]
        pub fn clear_nodes_announcement_info(&self) {
-               for node in self.nodes.write().unwrap().iter_mut() {
+               for node in self.nodes.write().unwrap().unordered_iter_mut() {
                        node.1.announcement_info = None;
                }
        }
@@ -1382,7 +1382,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                let node_id_b = channel_info.node_two.clone();
 
                match channels.entry(short_channel_id) {
-                       BtreeEntry::Occupied(mut entry) => {
+                       IndexedMapEntry::Occupied(mut entry) => {
                                //TODO: because asking the blockchain if short_channel_id is valid is only optional
                                //in the blockchain API, we need to handle it smartly here, though it's unclear
                                //exactly how...
@@ -1401,20 +1401,19 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                        return Err(LightningError{err: "Already have knowledge of channel".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
                                }
                        },
-                       BtreeEntry::Vacant(entry) => {
+                       IndexedMapEntry::Vacant(entry) => {
                                entry.insert(channel_info);
                        }
                };
 
                for current_node_id in [node_id_a, node_id_b].iter() {
                        match nodes.entry(current_node_id.clone()) {
-                               BtreeEntry::Occupied(node_entry) => {
+                               IndexedMapEntry::Occupied(node_entry) => {
                                        node_entry.into_mut().channels.push(short_channel_id);
                                },
-                               BtreeEntry::Vacant(node_entry) => {
+                               IndexedMapEntry::Vacant(node_entry) => {
                                        node_entry.insert(NodeInfo {
                                                channels: vec!(short_channel_id),
-                                               lowest_inbound_channel_fees: None,
                                                announcement_info: None,
                                        });
                                }
@@ -1586,7 +1585,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        for scid in node.channels.iter() {
                                if let Some(chan_info) = channels.remove(scid) {
                                        let other_node_id = if node_id == chan_info.node_one { chan_info.node_two } else { chan_info.node_one };
-                                       if let BtreeEntry::Occupied(mut other_node_entry) = nodes.entry(other_node_id) {
+                                       if let IndexedMapEntry::Occupied(mut other_node_entry) = nodes.entry(other_node_id) {
                                                other_node_entry.get_mut().channels.retain(|chan_id| {
                                                        *scid != *chan_id
                                                });
@@ -1645,7 +1644,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                // Sadly BTreeMap::retain was only stabilized in 1.53 so we can't switch to it for some
                // time.
                let mut scids_to_remove = Vec::new();
-               for (scid, info) in channels.iter_mut() {
+               for (scid, info) in channels.unordered_iter_mut() {
                        if info.one_to_two.is_some() && info.one_to_two.as_ref().unwrap().last_update < min_time_unix {
                                info.one_to_two = None;
                        }
@@ -1715,9 +1714,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        }
 
        fn update_channel_intern(&self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, sig: Option<&secp256k1::ecdsa::Signature>) -> Result<(), LightningError> {
-               let dest_node_id;
                let chan_enabled = msg.flags & (1 << 1) != (1 << 1);
-               let chan_was_enabled;
 
                #[cfg(all(feature = "std", not(test), not(feature = "_test_utils")))]
                {
@@ -1765,9 +1762,6 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                                        } else if existing_chan_info.last_update == msg.timestamp {
                                                                return Err(LightningError{err: "Update had same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
                                                        }
-                                                       chan_was_enabled = existing_chan_info.enabled;
-                                               } else {
-                                                       chan_was_enabled = false;
                                                }
                                        }
                                }
@@ -1795,7 +1789,6 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
 
                                let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
                                if msg.flags & 1 == 1 {
-                                       dest_node_id = channel.node_one.clone();
                                        check_update_latest!(channel.two_to_one);
                                        if let Some(sig) = sig {
                                                secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
@@ -1805,7 +1798,6 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                        }
                                        channel.two_to_one = get_new_channel_info!();
                                } else {
-                                       dest_node_id = channel.node_two.clone();
                                        check_update_latest!(channel.one_to_two);
                                        if let Some(sig) = sig {
                                                secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
@@ -1818,51 +1810,13 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        }
                }
 
-               let mut nodes = self.nodes.write().unwrap();
-               if chan_enabled {
-                       let node = nodes.get_mut(&dest_node_id).unwrap();
-                       let mut base_msat = msg.fee_base_msat;
-                       let mut proportional_millionths = msg.fee_proportional_millionths;
-                       if let Some(fees) = node.lowest_inbound_channel_fees {
-                               base_msat = cmp::min(base_msat, fees.base_msat);
-                               proportional_millionths = cmp::min(proportional_millionths, fees.proportional_millionths);
-                       }
-                       node.lowest_inbound_channel_fees = Some(RoutingFees {
-                               base_msat,
-                               proportional_millionths
-                       });
-               } else if chan_was_enabled {
-                       let node = nodes.get_mut(&dest_node_id).unwrap();
-                       let mut lowest_inbound_channel_fees = None;
-
-                       for chan_id in node.channels.iter() {
-                               let chan = channels.get(chan_id).unwrap();
-                               let chan_info_opt;
-                               if chan.node_one == dest_node_id {
-                                       chan_info_opt = chan.two_to_one.as_ref();
-                               } else {
-                                       chan_info_opt = chan.one_to_two.as_ref();
-                               }
-                               if let Some(chan_info) = chan_info_opt {
-                                       if chan_info.enabled {
-                                               let fees = lowest_inbound_channel_fees.get_or_insert(RoutingFees {
-                                                       base_msat: u32::max_value(), proportional_millionths: u32::max_value() });
-                                               fees.base_msat = cmp::min(fees.base_msat, chan_info.fees.base_msat);
-                                               fees.proportional_millionths = cmp::min(fees.proportional_millionths, chan_info.fees.proportional_millionths);
-                                       }
-                               }
-                       }
-
-                       node.lowest_inbound_channel_fees = lowest_inbound_channel_fees;
-               }
-
                Ok(())
        }
 
-       fn remove_channel_in_nodes(nodes: &mut BTreeMap<NodeId, NodeInfo>, chan: &ChannelInfo, short_channel_id: u64) {
+       fn remove_channel_in_nodes(nodes: &mut IndexedMap<NodeId, NodeInfo>, chan: &ChannelInfo, short_channel_id: u64) {
                macro_rules! remove_from_node {
                        ($node_id: expr) => {
-                               if let BtreeEntry::Occupied(mut entry) = nodes.entry($node_id) {
+                               if let IndexedMapEntry::Occupied(mut entry) = nodes.entry($node_id) {
                                        entry.get_mut().channels.retain(|chan_id| {
                                                short_channel_id != *chan_id
                                        });
@@ -1883,8 +1837,8 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
 impl ReadOnlyNetworkGraph<'_> {
        /// Returns all known valid channels' short ids along with announced channel info.
        ///
-       /// (C-not exported) because we have no mapping for `BTreeMap`s
-       pub fn channels(&self) -> &BTreeMap<u64, ChannelInfo> {
+       /// (C-not exported) because we don't want to return lifetime'd references
+       pub fn channels(&self) -> &IndexedMap<u64, ChannelInfo> {
                &*self.channels
        }
 
@@ -1896,13 +1850,13 @@ impl ReadOnlyNetworkGraph<'_> {
        #[cfg(c_bindings)] // Non-bindings users should use `channels`
        /// Returns the list of channels in the graph
        pub fn list_channels(&self) -> Vec<u64> {
-               self.channels.keys().map(|c| *c).collect()
+               self.channels.unordered_keys().map(|c| *c).collect()
        }
 
        /// Returns all known nodes' public keys along with announced node info.
        ///
-       /// (C-not exported) because we have no mapping for `BTreeMap`s
-       pub fn nodes(&self) -> &BTreeMap<NodeId, NodeInfo> {
+       /// (C-not exported) because we don't want to return lifetime'd references
+       pub fn nodes(&self) -> &IndexedMap<NodeId, NodeInfo> {
                &*self.nodes
        }
 
@@ -1914,7 +1868,7 @@ impl ReadOnlyNetworkGraph<'_> {
        #[cfg(c_bindings)] // Non-bindings users should use `nodes`
        /// Returns the list of nodes in the graph
        pub fn list_nodes(&self) -> Vec<NodeId> {
-               self.nodes.keys().map(|n| *n).collect()
+               self.nodes.unordered_keys().map(|n| *n).collect()
        }
 
        /// Get network addresses by node id.
@@ -3276,7 +3230,6 @@ mod tests {
                // 2. Check we can read a NodeInfo anyways, but set the NodeAnnouncementInfo to None if invalid
                let valid_node_info = NodeInfo {
                        channels: Vec::new(),
-                       lowest_inbound_channel_fees: None,
                        announcement_info: Some(valid_node_ann_info),
                };
 
index c15b612d939b16d4b75e79c81b3077cd60cadb09..1e2ca10c0bf4a0795bc4089d0145b69ad8914de5 100644 (file)
@@ -363,7 +363,7 @@ impl Readable for Route {
 /// [`Event::PaymentPathFailed`] for retrying a failed payment path.
 ///
 /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct RouteParameters {
        /// The parameters of the failed payment path.
        pub payment_params: PaymentParameters,
@@ -582,7 +582,6 @@ impl_writeable_tlv_based!(RouteHintHop, {
 #[derive(Eq, PartialEq)]
 struct RouteGraphNode {
        node_id: NodeId,
-       lowest_fee_to_peer_through_node: u64,
        lowest_fee_to_node: u64,
        total_cltv_delta: u32,
        // The maximum value a yet-to-be-constructed payment path might flow through this node.
@@ -603,9 +602,9 @@ struct RouteGraphNode {
 
 impl cmp::Ord for RouteGraphNode {
        fn cmp(&self, other: &RouteGraphNode) -> cmp::Ordering {
-               let other_score = cmp::max(other.lowest_fee_to_peer_through_node, other.path_htlc_minimum_msat)
+               let other_score = cmp::max(other.lowest_fee_to_node, other.path_htlc_minimum_msat)
                        .saturating_add(other.path_penalty_msat);
-               let self_score = cmp::max(self.lowest_fee_to_peer_through_node, self.path_htlc_minimum_msat)
+               let self_score = cmp::max(self.lowest_fee_to_node, self.path_htlc_minimum_msat)
                        .saturating_add(self.path_penalty_msat);
                other_score.cmp(&self_score).then_with(|| other.node_id.cmp(&self.node_id))
        }
@@ -729,8 +728,6 @@ struct PathBuildingHop<'a> {
        candidate: CandidateRouteHop<'a>,
        fee_msat: u64,
 
-       /// Minimal fees required to route to the source node of the current hop via any of its inbound channels.
-       src_lowest_inbound_fees: RoutingFees,
        /// All the fees paid *after* this channel on the way to the destination
        next_hops_fee_msat: u64,
        /// Fee paid for the use of the current channel (see candidate.fees()).
@@ -888,18 +885,20 @@ impl<'a> PaymentPath<'a> {
        }
 }
 
+#[inline(always)]
+/// Calculate the fees required to route the given amount over a channel with the given fees.
 fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
-       let proportional_fee_millions =
-               amount_msat.checked_mul(channel_fees.proportional_millionths as u64);
-       if let Some(new_fee) = proportional_fee_millions.and_then(|part| {
-                       (channel_fees.base_msat as u64).checked_add(part / 1_000_000) }) {
+       amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
+               .and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000))
+}
 
-               Some(new_fee)
-       } else {
-               // This function may be (indirectly) called without any verification,
-               // with channel_fees provided by a caller. We should handle it gracefully.
-               None
-       }
+#[inline(always)]
+/// Calculate the fees required to route the given amount over a channel with the given fees,
+/// saturating to [`u64::max_value`].
+fn compute_fees_saturating(amount_msat: u64, channel_fees: RoutingFees) -> u64 {
+       amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
+               .map(|prop| prop / 1_000_000).unwrap_or(u64::max_value())
+               .saturating_add(channel_fees.base_msat as u64)
 }
 
 /// The default `features` we assume for a node in a route, when no `features` are known about that
@@ -1007,9 +1006,8 @@ where L::Target: Logger {
        // 8. If our maximum channel saturation limit caused us to pick two identical paths, combine
        //    them so that we're not sending two HTLCs along the same path.
 
-       // As for the actual search algorithm,
-       // we do a payee-to-payer pseudo-Dijkstra's sorting by each node's distance from the payee
-       // plus the minimum per-HTLC fee to get from it to another node (aka "shitty pseudo-A*").
+       // As for the actual search algorithm, we do a payee-to-payer Dijkstra's sorting by each node's
+       // distance from the payee
        //
        // We are not a faithful Dijkstra's implementation because we can change values which impact
        // earlier nodes while processing later nodes. Specifically, if we reach a channel with a lower
@@ -1044,10 +1042,6 @@ where L::Target: Logger {
        // runtime for little gain. Specifically, the current algorithm rather efficiently explores the
        // graph for candidate paths, calculating the maximum value which can realistically be sent at
        // the same time, remaining generic across different payment values.
-       //
-       // TODO: There are a few tweaks we could do, including possibly pre-calculating more stuff
-       // to use as the A* heuristic beyond just the cost to get one node further than the current
-       // one.
 
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
@@ -1097,7 +1091,7 @@ where L::Target: Logger {
                }
        }
 
-       // The main heap containing all candidate next-hops sorted by their score (max(A* fee,
+       // The main heap containing all candidate next-hops sorted by their score (max(fee,
        // htlc_minimum)). Ideally this would be a heap which allowed cheap score reduction instead of
        // adding duplicate entries when we find a better path to a given node.
        let mut targets: BinaryHeap<RouteGraphNode> = BinaryHeap::new();
@@ -1262,10 +1256,10 @@ where L::Target: Logger {
                                                // might violate htlc_minimum_msat on the hops which are next along the
                                                // payment path (upstream to the payee). To avoid that, we recompute
                                                // path fees knowing the final path contribution after constructing it.
-                                               let path_htlc_minimum_msat = compute_fees($next_hops_path_htlc_minimum_msat, $candidate.fees())
-                                                       .and_then(|fee_msat| fee_msat.checked_add($next_hops_path_htlc_minimum_msat))
-                                                       .map(|fee_msat| cmp::max(fee_msat, $candidate.htlc_minimum_msat()))
-                                                       .unwrap_or_else(|| u64::max_value());
+                                               let path_htlc_minimum_msat = cmp::max(
+                                                       compute_fees_saturating($next_hops_path_htlc_minimum_msat, $candidate.fees())
+                                                               .saturating_add($next_hops_path_htlc_minimum_msat),
+                                                       $candidate.htlc_minimum_msat());
                                                let hm_entry = dist.entry($src_node_id);
                                                let old_entry = hm_entry.or_insert_with(|| {
                                                        // If there was previously no known way to access the source node
@@ -1273,20 +1267,10 @@ where L::Target: Logger {
                                                        // semi-dummy record just to compute the fees to reach the source node.
                                                        // This will affect our decision on selecting short_channel_id
                                                        // as a way to reach the $dest_node_id.
-                                                       let mut fee_base_msat = 0;
-                                                       let mut fee_proportional_millionths = 0;
-                                                       if let Some(Some(fees)) = network_nodes.get(&$src_node_id).map(|node| node.lowest_inbound_channel_fees) {
-                                                               fee_base_msat = fees.base_msat;
-                                                               fee_proportional_millionths = fees.proportional_millionths;
-                                                       }
                                                        PathBuildingHop {
                                                                node_id: $dest_node_id.clone(),
                                                                candidate: $candidate.clone(),
                                                                fee_msat: 0,
-                                                               src_lowest_inbound_fees: RoutingFees {
-                                                                       base_msat: fee_base_msat,
-                                                                       proportional_millionths: fee_proportional_millionths,
-                                                               },
                                                                next_hops_fee_msat: u64::max_value(),
                                                                hop_use_fee_msat: u64::max_value(),
                                                                total_fee_msat: u64::max_value(),
@@ -1309,38 +1293,15 @@ where L::Target: Logger {
 
                                                if should_process {
                                                        let mut hop_use_fee_msat = 0;
-                                                       let mut total_fee_msat = $next_hops_fee_msat;
+                                                       let mut total_fee_msat: u64 = $next_hops_fee_msat;
 
                                                        // Ignore hop_use_fee_msat for channel-from-us as we assume all channels-from-us
                                                        // will have the same effective-fee
                                                        if $src_node_id != our_node_id {
-                                                               match compute_fees(amount_to_transfer_over_msat, $candidate.fees()) {
-                                                                       // max_value means we'll always fail
-                                                                       // the old_entry.total_fee_msat > total_fee_msat check
-                                                                       None => total_fee_msat = u64::max_value(),
-                                                                       Some(fee_msat) => {
-                                                                               hop_use_fee_msat = fee_msat;
-                                                                               total_fee_msat += hop_use_fee_msat;
-                                                                               // When calculating the lowest inbound fees to a node, we
-                                                                               // calculate fees here not based on the actual value we think
-                                                                               // will flow over this channel, but on the minimum value that
-                                                                               // we'll accept flowing over it. The minimum accepted value
-                                                                               // is a constant through each path collection run, ensuring
-                                                                               // consistent basis. Otherwise we may later find a
-                                                                               // different path to the source node that is more expensive,
-                                                                               // but which we consider to be cheaper because we are capacity
-                                                                               // constrained and the relative fee becomes lower.
-                                                                               match compute_fees(minimal_value_contribution_msat, old_entry.src_lowest_inbound_fees)
-                                                                                               .map(|a| a.checked_add(total_fee_msat)) {
-                                                                                       Some(Some(v)) => {
-                                                                                               total_fee_msat = v;
-                                                                                       },
-                                                                                       _ => {
-                                                                                               total_fee_msat = u64::max_value();
-                                                                                       }
-                                                                               };
-                                                                       }
-                                                               }
+                                                               // Note that `u64::max_value` means we'll always fail the
+                                                               // `old_entry.total_fee_msat > total_fee_msat` check below
+                                                               hop_use_fee_msat = compute_fees_saturating(amount_to_transfer_over_msat, $candidate.fees());
+                                                               total_fee_msat = total_fee_msat.saturating_add(hop_use_fee_msat);
                                                        }
 
                                                        let channel_usage = ChannelUsage {
@@ -1355,8 +1316,7 @@ where L::Target: Logger {
                                                                .saturating_add(channel_penalty_msat);
                                                        let new_graph_node = RouteGraphNode {
                                                                node_id: $src_node_id,
-                                                               lowest_fee_to_peer_through_node: total_fee_msat,
-                                                               lowest_fee_to_node: $next_hops_fee_msat as u64 + hop_use_fee_msat,
+                                                               lowest_fee_to_node: total_fee_msat,
                                                                total_cltv_delta: hop_total_cltv_delta,
                                                                value_contribution_msat,
                                                                path_htlc_minimum_msat,
@@ -5544,9 +5504,9 @@ mod tests {
                'load_endpoints: for _ in 0..10 {
                        loop {
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                let payment_params = PaymentParameters::from_node_id(dst);
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
@@ -5582,9 +5542,9 @@ mod tests {
                'load_endpoints: for _ in 0..10 {
                        loop {
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                let payment_params = PaymentParameters::from_node_id(dst).with_features(channelmanager::provided_invoice_features(&config));
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
@@ -5639,8 +5599,8 @@ pub(crate) mod bench_utils {
        use std::fs::File;
        /// Tries to open a network graph file, or panics with a URL to fetch it.
        pub(crate) fn get_route_file() -> Result<std::fs::File, &'static str> {
-               let res = File::open("net_graph-2021-05-31.bin") // By default we're run in RL/lightning
-                       .or_else(|_| File::open("lightning/net_graph-2021-05-31.bin")) // We may be run manually in RL/
+               let res = File::open("net_graph-2023-01-18.bin") // By default we're run in RL/lightning
+                       .or_else(|_| File::open("lightning/net_graph-2023-01-18.bin")) // We may be run manually in RL/
                        .or_else(|_| { // Fall back to guessing based on the binary location
                                // path is likely something like .../rust-lightning/target/debug/deps/lightning-...
                                let mut path = std::env::current_exe().unwrap();
@@ -5649,11 +5609,11 @@ pub(crate) mod bench_utils {
                                path.pop(); // debug
                                path.pop(); // target
                                path.push("lightning");
-                               path.push("net_graph-2021-05-31.bin");
+                               path.push("net_graph-2023-01-18.bin");
                                eprintln!("{}", path.to_str().unwrap());
                                File::open(path)
                        })
-               .map_err(|_| "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.15-2021-05-31.bin and place it at lightning/net_graph-2021-05-31.bin");
+               .map_err(|_| "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.113-2023-01-18.bin and place it at lightning/net_graph-2023-01-18.bin");
                #[cfg(require_route_graph_test)]
                return Ok(res.unwrap());
                #[cfg(not(require_route_graph_test))]
@@ -5782,9 +5742,9 @@ mod benches {
                'load_endpoints: for _ in 0..150 {
                        loop {
                                seed *= 0xdeadbeef;
-                               let src = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed *= 0xdeadbeef;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                let params = PaymentParameters::from_node_id(dst).with_features(features.clone());
                                let first_hop = first_hop(src);
                                let amt = seed as u64 % 1_000_000;
index 18bba29fef414434b1fe4df2215e1dd59cbc3e7c..b32e8660d0a8b3490c2f06f15206760a7725f6eb 100644 (file)
@@ -126,7 +126,6 @@ pub struct ChannelHandshakeConfig {
        ///
        /// [`SignerProvider::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::SignerProvider::get_shutdown_scriptpubkey
        pub commit_upfront_shutdown_pubkey: bool,
-
        /// The Proportion of the channel value to configure as counterparty's channel reserve,
        /// i.e., `their_channel_reserve_satoshis` for both outbound and inbound channels.
        ///
@@ -149,7 +148,28 @@ pub struct ChannelHandshakeConfig {
        ///                as 1000 sats instead, which is a safe implementation-specific lower bound.
        /// Maximum value: 1,000,000, any values larger than 1 Million will be treated as 1 Million (or 100%)
        ///                instead, although channel negotiations will fail in that case.
-       pub their_channel_reserve_proportional_millionths: u32
+       pub their_channel_reserve_proportional_millionths: u32,
+       #[cfg(anchors)]
+       /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for outbound channels.
+       ///
+       /// If this option is set, channels may be created that will not be readable by LDK versions
+       /// prior to 0.0.114, causing [`ChannelManager`]'s read method to return a
+       /// [`DecodeError::InvalidValue`].
+       ///
+       /// Note that setting this to true does *not* prevent us from opening channels with
+       /// counterparties that do not support the `anchors_zero_fee_htlc_tx` option; we will simply
+       /// fall back to a `static_remote_key` channel.
+       ///
+       /// LDK will not support the legacy `option_anchors` commitment version due to a discovered
+       /// vulnerability after its deployment. For more context, see the [`SIGHASH_SINGLE + update_fee
+       /// Considered Harmful`] mailing list post.
+       ///
+       /// Default value: false. This value is likely to change to true in the future.
+       ///
+       /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+       /// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue
+       /// [`SIGHASH_SINGLE + update_fee Considered Harmful`]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html
+       pub negotiate_anchors_zero_fee_htlc_tx: bool,
 }
 
 impl Default for ChannelHandshakeConfig {
@@ -163,6 +183,8 @@ impl Default for ChannelHandshakeConfig {
                        announced_channel: false,
                        commit_upfront_shutdown_pubkey: true,
                        their_channel_reserve_proportional_millionths: 10_000,
+                       #[cfg(anchors)]
+                       negotiate_anchors_zero_fee_htlc_tx: false,
                }
        }
 }
index dfec1be7e91bc5896882560afa2939d46f0b0318..1f7b5221c8f781e337ae4a3a61b460ab21391829 100644 (file)
@@ -10,7 +10,7 @@
 use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS};
 use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction};
 use crate::ln::{chan_utils, msgs, PaymentPreimage};
-use crate::chain::keysinterface::{Sign, InMemorySigner, BaseSign};
+use crate::chain::keysinterface::{WriteableEcdsaChannelSigner, InMemorySigner, ChannelSigner, EcdsaChannelSigner};
 
 use crate::prelude::*;
 use core::cmp;
@@ -58,6 +58,12 @@ pub struct EnforcingSigner {
        pub disable_revocation_policy_check: bool,
 }
 
+impl PartialEq for EnforcingSigner {
+       fn eq(&self, o: &Self) -> bool {
+               Arc::ptr_eq(&self.state, &o.state)
+       }
+}
+
 impl EnforcingSigner {
        /// Construct an EnforcingSigner
        pub fn new(inner: InMemorySigner) -> Self {
@@ -90,7 +96,7 @@ impl EnforcingSigner {
        }
 }
 
-impl BaseSign for EnforcingSigner {
+impl ChannelSigner for EnforcingSigner {
        fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1<secp256k1::All>) -> PublicKey {
                self.inner.get_per_commitment_point(idx, secp_ctx)
        }
@@ -114,8 +120,15 @@ impl BaseSign for EnforcingSigner {
        }
 
        fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() }
+
        fn channel_keys_id(&self) -> [u8; 32] { self.inner.channel_keys_id() }
 
+       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) {
+               self.inner.provide_channel_parameters(channel_parameters)
+       }
+}
+
+impl EcdsaChannelSigner for EnforcingSigner {
        fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
                self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx);
 
@@ -223,17 +236,14 @@ impl BaseSign for EnforcingSigner {
                self.inner.sign_holder_anchor_input(anchor_tx, input, secp_ctx)
        }
 
-       fn sign_channel_announcement(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>)
-       -> Result<(Signature, Signature), ()> {
-               self.inner.sign_channel_announcement(msg, secp_ctx)
-       }
-
-       fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) {
-               self.inner.provide_channel_parameters(channel_parameters)
+       fn sign_channel_announcement_with_funding_key(
+               &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>
+       ) -> Result<Signature, ()> {
+               self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx)
        }
 }
 
-impl Sign for EnforcingSigner {}
+impl WriteableEcdsaChannelSigner for EnforcingSigner {}
 
 impl Writeable for EnforcingSigner {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
index 375174f6f6afa86c556c6804586adfa52020844a..475533c902a372fdb0bea1b86cb0e754dc90fbe4 100644 (file)
@@ -46,7 +46,7 @@ use crate::sync::Arc;
 
 /// Some information provided on receipt of payment depends on whether the payment received is a
 /// spontaneous payment or a "conventional" lightning payment that's paying an invoice.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub enum PaymentPurpose {
        /// Information for receiving a payment that we generated an invoice for.
        InvoicePayment {
@@ -257,10 +257,10 @@ pub struct HTLCDescriptor {
        /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
        pub channel_value_satoshis: u64,
        /// The necessary channel parameters that need to be provided to the re-derived
-       /// [`InMemorySigner`] through [`BaseSign::ready_channel`].
+       /// [`InMemorySigner`] through [`BaseSign::provide_channel_parameters`].
        ///
        /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
-       /// [`BaseSign::ready_channel`]: crate::chain::keysinterface::BaseSign::ready_channel
+       /// [`BaseSign::provide_channel_parameters`]: crate::chain::keysinterface::BaseSign::provide_channel_parameters
        pub channel_parameters: ChannelTransactionParameters,
        /// The txid of the commitment transaction in which the HTLC output lives.
        pub commitment_txid: Txid,
@@ -455,7 +455,7 @@ impl_writeable_tlv_based_enum!(InterceptNextHop,
 /// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
 /// them directly as they don't round-trip exactly (for example FundingGenerationReady is never
 /// written as it makes no sense to respond to it after reconnecting to peers).
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub enum Event {
        /// Used to indicate that the client should generate a funding transaction with the given
        /// parameters and then call [`ChannelManager::funding_transaction_generated`].
@@ -491,10 +491,10 @@ pub enum Event {
        /// [`ChannelManager::claim_funds`] with the preimage given in [`PaymentPurpose`].
        ///
        /// Note that if the preimage is not known, you should call
-       /// [`ChannelManager::fail_htlc_backwards`] to free up resources for this HTLC and avoid
-       /// network congestion.
-       /// If you fail to call either [`ChannelManager::claim_funds`] or
-       /// [`ChannelManager::fail_htlc_backwards`] within the HTLC's timeout, the HTLC will be
+       /// [`ChannelManager::fail_htlc_backwards`] or [`ChannelManager::fail_htlc_backwards_with_reason`]
+       /// to free up resources for this HTLC and avoid network congestion.
+       /// If you fail to call either [`ChannelManager::claim_funds`], [`ChannelManager::fail_htlc_backwards`],
+       /// or [`ChannelManager::fail_htlc_backwards_with_reason`] within the HTLC's timeout, the HTLC will be
        /// automatically failed.
        ///
        /// # Note
@@ -506,6 +506,7 @@ pub enum Event {
        ///
        /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
        /// [`ChannelManager::fail_htlc_backwards`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards
+       /// [`ChannelManager::fail_htlc_backwards_with_reason`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards_with_reason
        PaymentClaimable {
                /// The node that will receive the payment after it has been claimed.
                /// This is useful to identify payments received via [phantom nodes].
diff --git a/lightning/src/util/indexed_map.rs b/lightning/src/util/indexed_map.rs
new file mode 100644 (file)
index 0000000..cccbfe7
--- /dev/null
@@ -0,0 +1,203 @@
+//! This module has a map which can be iterated in a deterministic order. See the [`IndexedMap`].
+
+use crate::prelude::{HashMap, hash_map};
+use alloc::collections::{BTreeSet, btree_set};
+use core::hash::Hash;
+use core::cmp::Ord;
+use core::ops::RangeBounds;
+
+/// A map which can be iterated in a deterministic order.
+///
+/// This would traditionally be accomplished by simply using a [`BTreeMap`], however B-Trees
+/// generally have very slow lookups. Because we use a nodes+channels map while finding routes
+/// across the network graph, our network graph backing map must be as performant as possible.
+/// However, because peers expect to sync the network graph from us (and we need to support that
+/// without holding a lock on the graph for the duration of the sync or dumping the entire graph
+/// into our outbound message queue), we need an iterable map with a consistent iteration order we
+/// can jump to a starting point on.
+///
+/// Thus, we have a custom data structure here - its API mimics that of Rust's [`BTreeMap`], but is
+/// actually backed by a [`HashMap`], with some additional tracking to ensure we can iterate over
+/// keys in the order defined by [`Ord`].
+///
+/// [`BTreeMap`]: alloc::collections::BTreeMap
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct IndexedMap<K: Hash + Ord, V> {
+       map: HashMap<K, V>,
+       // TODO: Explore swapping this for a sorted vec (that is only sorted on first range() call)
+       keys: BTreeSet<K>,
+}
+
+impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
+       /// Constructs a new, empty map
+       pub fn new() -> Self {
+               Self {
+                       map: HashMap::new(),
+                       keys: BTreeSet::new(),
+               }
+       }
+
+       #[inline(always)]
+       /// Fetches the element with the given `key`, if one exists.
+       pub fn get(&self, key: &K) -> Option<&V> {
+               self.map.get(key)
+       }
+
+       /// Fetches a mutable reference to the element with the given `key`, if one exists.
+       pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
+               self.map.get_mut(key)
+       }
+
+       #[inline]
+       /// Returns true if an element with the given `key` exists in the map.
+       pub fn contains_key(&self, key: &K) -> bool {
+               self.map.contains_key(key)
+       }
+
+       /// Removes the element with the given `key`, returning it, if one exists.
+       pub fn remove(&mut self, key: &K) -> Option<V> {
+               let ret = self.map.remove(key);
+               if let Some(_) = ret {
+                       assert!(self.keys.remove(key), "map and keys must be consistent");
+               }
+               ret
+       }
+
+       /// Inserts the given `key`/`value` pair into the map, returning the element that was
+       /// previously stored at the given `key`, if one exists.
+       pub fn insert(&mut self, key: K, value: V) -> Option<V> {
+               let ret = self.map.insert(key.clone(), value);
+               if ret.is_none() {
+                       assert!(self.keys.insert(key), "map and keys must be consistent");
+               }
+               ret
+       }
+
+       /// Returns an [`Entry`] for the given `key` in the map, allowing access to the value.
+       pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
+               match self.map.entry(key.clone()) {
+                       hash_map::Entry::Vacant(entry) => {
+                               Entry::Vacant(VacantEntry {
+                                       underlying_entry: entry,
+                                       key,
+                                       keys: &mut self.keys,
+                               })
+                       },
+                       hash_map::Entry::Occupied(entry) => {
+                               Entry::Occupied(OccupiedEntry {
+                                       underlying_entry: entry,
+                                       keys: &mut self.keys,
+                               })
+                       }
+               }
+       }
+
+       /// Returns an iterator which iterates over the keys in the map, in a random order.
+       pub fn unordered_keys(&self) -> impl Iterator<Item = &K> {
+               self.map.keys()
+       }
+
+       /// Returns an iterator which iterates over the `key`/`value` pairs in a random order.
+       pub fn unordered_iter(&self) -> impl Iterator<Item = (&K, &V)> {
+               self.map.iter()
+       }
+
+       /// Returns an iterator which iterates over the `key`s and mutable references to `value`s in a
+       /// random order.
+       pub fn unordered_iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
+               self.map.iter_mut()
+       }
+
+       /// Returns an iterator which iterates over the `key`/`value` pairs in a given range.
+       pub fn range<R: RangeBounds<K>>(&self, range: R) -> Range<K, V> {
+               Range {
+                       inner_range: self.keys.range(range),
+                       map: &self.map,
+               }
+       }
+
+       /// Returns the number of `key`/`value` pairs in the map
+       pub fn len(&self) -> usize {
+               self.map.len()
+       }
+
+       /// Returns true if there are no elements in the map
+       pub fn is_empty(&self) -> bool {
+               self.map.is_empty()
+       }
+}
+
+/// An iterator over a range of values in an [`IndexedMap`]
+pub struct Range<'a, K: Hash + Ord, V> {
+       inner_range: btree_set::Range<'a, K>,
+       map: &'a HashMap<K, V>,
+}
+impl<'a, K: Hash + Ord, V: 'a> Iterator for Range<'a, K, V> {
+       type Item = (&'a K, &'a V);
+       fn next(&mut self) -> Option<(&'a K, &'a V)> {
+               self.inner_range.next().map(|k| {
+                       (k, self.map.get(k).expect("map and keys must be consistent"))
+               })
+       }
+}
+
+/// An [`Entry`] for a key which currently has no value
+pub struct VacantEntry<'a, K: Hash + Ord, V> {
+       #[cfg(feature = "hashbrown")]
+       underlying_entry: hash_map::VacantEntry<'a, K, V, hash_map::DefaultHashBuilder>,
+       #[cfg(not(feature = "hashbrown"))]
+       underlying_entry: hash_map::VacantEntry<'a, K, V>,
+       key: K,
+       keys: &'a mut BTreeSet<K>,
+}
+
+/// An [`Entry`] for an existing key-value pair
+pub struct OccupiedEntry<'a, K: Hash + Ord, V> {
+       #[cfg(feature = "hashbrown")]
+       underlying_entry: hash_map::OccupiedEntry<'a, K, V, hash_map::DefaultHashBuilder>,
+       #[cfg(not(feature = "hashbrown"))]
+       underlying_entry: hash_map::OccupiedEntry<'a, K, V>,
+       keys: &'a mut BTreeSet<K>,
+}
+
+/// A mutable reference to a position in the map. This can be used to reference, add, or update the
+/// value at a fixed key.
+pub enum Entry<'a, K: Hash + Ord, V> {
+       /// A mutable reference to a position within the map where there is no value.
+       Vacant(VacantEntry<'a, K, V>),
+       /// A mutable reference to a position within the map where there is currently a value.
+       Occupied(OccupiedEntry<'a, K, V>),
+}
+
+impl<'a, K: Hash + Ord, V> VacantEntry<'a, K, V> {
+       /// Insert a value into the position described by this entry.
+       pub fn insert(self, value: V) -> &'a mut V {
+               assert!(self.keys.insert(self.key), "map and keys must be consistent");
+               self.underlying_entry.insert(value)
+       }
+}
+
+impl<'a, K: Hash + Ord, V> OccupiedEntry<'a, K, V> {
+       /// Remove the value at the position described by this entry.
+       pub fn remove_entry(self) -> (K, V) {
+               let res = self.underlying_entry.remove_entry();
+               assert!(self.keys.remove(&res.0), "map and keys must be consistent");
+               res
+       }
+
+       /// Get a reference to the value at the position described by this entry.
+       pub fn get(&self) -> &V {
+               self.underlying_entry.get()
+       }
+
+       /// Get a mutable reference to the value at the position described by this entry.
+       pub fn get_mut(&mut self) -> &mut V {
+               self.underlying_entry.get_mut()
+       }
+
+       /// Consume this entry, returning a mutable reference to the value at the position described by
+       /// this entry.
+       pub fn into_mut(self) -> &'a mut V {
+               self.underlying_entry.into_mut()
+       }
+}
index 8c2aba0c1c1cf87ac15ec95076a3a5cc05ea1330..e83e6e2ee48ea27d40327c4e56cb50e2827e94fc 100644 (file)
@@ -107,7 +107,7 @@ impl<'a> core::fmt::Display for DebugTx<'a> {
                                        }
                                }
                                if num_preimage > 0 || num_timeout > 0 || num_revoked > 0 {
-                                       write!(f, "HTLC claim tx ({} preimage, {} timeout, {} revoked)",
+                                       write!(f, "HTLC claim tx ({} preimage, {} timeout, {} revoked) ",
                                                num_preimage, num_timeout, num_revoked)?;
                                }
                        }
index 1d46865b6019b0158659ccab2c590c419416e36c..1673bd07f69b24d7af49f7d9c3604ea33f000422 100644 (file)
@@ -40,6 +40,8 @@ pub(crate) mod transaction_utils;
 pub(crate) mod scid_utils;
 pub(crate) mod time;
 
+pub mod indexed_map;
+
 /// Logging macro utilities.
 #[macro_use]
 pub(crate) mod macro_logger;
index 2e45685daa00709ecea13cd0e8dc521028b05e16..aa705f286736ada5cf8d12635fc91f0d459dd29c 100644 (file)
@@ -16,7 +16,7 @@ use crate::routing::scoring::WriteableScore;
 use crate::chain;
 use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
 use crate::chain::chainmonitor::{Persist, MonitorUpdateId};
-use crate::chain::keysinterface::{EntropySource, NodeSigner, Sign, SignerProvider};
+use crate::chain::keysinterface::{EntropySource, NodeSigner, WriteableEcdsaChannelSigner, SignerProvider};
 use crate::chain::transaction::OutPoint;
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate};
 use crate::ln::channelmanager::ChannelManager;
@@ -80,7 +80,7 @@ impl<'a, A: KVStorePersister, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Dere
        }
 }
 
-impl<ChannelSigner: Sign, K: KVStorePersister> Persist<ChannelSigner> for K {
+impl<ChannelSigner: WriteableEcdsaChannelSigner, K: KVStorePersister> Persist<ChannelSigner> for K {
        // TODO: We really need a way for the persister to inform the user that its time to crash/shut
        // down once these start returning failure.
        // A PermanentFailure implies we should probably just shut down the node since we're
index f528ae2d547c61f78c09fbbe64b2a3e3da6aa173..1dae61ab3ef5b1841241b069612f71c7e5cc8f38 100644 (file)
@@ -20,6 +20,7 @@ use crate::chain::keysinterface;
 use crate::ln::channelmanager;
 use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use crate::ln::{msgs, wire};
+use crate::ln::msgs::LightningError;
 use crate::ln::script::ShutdownScript;
 use crate::routing::gossip::NetworkGraph;
 use crate::routing::router::{find_route, InFlightHtlcs, Route, RouteHop, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
@@ -51,7 +52,7 @@ use crate::sync::{Mutex, Arc};
 use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use core::mem;
 use bitcoin::bech32::u5;
-use crate::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
+use crate::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider};
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -76,11 +77,17 @@ impl chaininterface::FeeEstimator for TestFeeEstimator {
 
 pub struct TestRouter<'a> {
        pub network_graph: Arc<NetworkGraph<&'a TestLogger>>,
+       pub next_routes: Mutex<VecDeque<Result<Route, LightningError>>>,
 }
 
 impl<'a> TestRouter<'a> {
        pub fn new(network_graph: Arc<NetworkGraph<&'a TestLogger>>) -> Self {
-               Self { network_graph }
+               Self { network_graph, next_routes: Mutex::new(VecDeque::new()), }
+       }
+
+       pub fn expect_find_route(&self, result: Result<Route, LightningError>) {
+               let mut expected_routes = self.next_routes.lock().unwrap();
+               expected_routes.push_back(result);
        }
 }
 
@@ -89,6 +96,9 @@ impl<'a> Router for TestRouter<'a> {
                &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&channelmanager::ChannelDetails]>,
                inflight_htlcs: &InFlightHtlcs
        ) -> Result<Route, msgs::LightningError> {
+               if let Some(find_route_res) = self.next_routes.lock().unwrap().pop_front() {
+                       return find_route_res
+               }
                let logger = TestLogger::new();
                find_route(
                        payer, params, &self.network_graph, first_hops, &logger,
@@ -102,22 +112,21 @@ impl<'a> Router for TestRouter<'a> {
        fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
 }
 
+#[cfg(feature = "std")] // If we put this on the `if`, we get "attributes are not yet allowed on `if` expressions" on 1.41.1
+impl<'a> Drop for TestRouter<'a> {
+       fn drop(&mut self) {
+               if std::thread::panicking() {
+                       return;
+               }
+               assert!(self.next_routes.lock().unwrap().is_empty());
+       }
+}
+
 pub struct OnlyReadsKeysInterface {}
 
 impl EntropySource for OnlyReadsKeysInterface {
        fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }}
 
-impl NodeSigner for OnlyReadsKeysInterface {
-       fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { unreachable!(); }
-       fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
-               let secp_ctx = Secp256k1::signing_only();
-               Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
-       }
-       fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result<SharedSecret, ()> { unreachable!(); }
-       fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!(); }
-       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { unreachable!(); }
-}
-
 impl SignerProvider for OnlyReadsKeysInterface {
        type Signer = EnforcingSigner;
 
@@ -126,8 +135,7 @@ impl SignerProvider for OnlyReadsKeysInterface {
        fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { unreachable!(); }
 
        fn read_chan_signer(&self, mut reader: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
-               let dummy_sk = SecretKey::from_slice(&[42; 32]).unwrap();
-               let inner: InMemorySigner = ReadableArgs::read(&mut reader, dummy_sk)?;
+               let inner: InMemorySigner = Readable::read(&mut reader)?;
                let state = Arc::new(Mutex::new(EnforcementState::new()));
 
                Ok(EnforcingSigner::new_with_revoked(
@@ -246,7 +254,7 @@ impl TestPersister {
                self.update_rets.lock().unwrap().push_back(next_ret);
        }
 }
-impl<Signer: keysinterface::Sign> chainmonitor::Persist<Signer> for TestPersister {
+impl<Signer: keysinterface::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for TestPersister {
        fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>, _id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
                if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() {
                        return update_ret
@@ -632,6 +640,49 @@ impl Logger for TestLogger {
        }
 }
 
+pub struct TestNodeSigner {
+       node_secret: SecretKey,
+}
+
+impl TestNodeSigner {
+       pub fn new(node_secret: SecretKey) -> Self {
+               Self { node_secret }
+       }
+}
+
+impl NodeSigner for TestNodeSigner {
+       fn get_inbound_payment_key_material(&self) -> crate::chain::keysinterface::KeyMaterial {
+               unreachable!()
+       }
+
+       fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+               let node_secret = match recipient {
+                       Recipient::Node => Ok(&self.node_secret),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret))
+       }
+
+       fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&bitcoin::secp256k1::Scalar>) -> Result<SharedSecret, ()> {
+               let mut node_secret = match recipient {
+                       Recipient::Node => Ok(self.node_secret.clone()),
+                       Recipient::PhantomNode => Err(())
+               }?;
+               if let Some(tweak) = tweak {
+                       node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
+               }
+               Ok(SharedSecret::new(other_key, &node_secret))
+       }
+
+       fn sign_invoice(&self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
+               unreachable!()
+       }
+
+       fn sign_gossip_message(&self, _msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
+               unreachable!()
+       }
+}
+
 pub struct TestKeysInterface {
        pub backing: keysinterface::PhantomKeysManager,
        pub override_random_bytes: Mutex<Option<[u8; 32]>>,
@@ -651,10 +702,6 @@ impl EntropySource for TestKeysInterface {
 }
 
 impl NodeSigner for TestKeysInterface {
-       fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
-               self.backing.get_node_secret(recipient)
-       }
-
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
                self.backing.get_node_id(recipient)
        }
@@ -670,6 +717,10 @@ impl NodeSigner for TestKeysInterface {
        fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
                self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
        }
+
+       fn sign_gossip_message(&self, msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
+               self.backing.sign_gossip_message(msg)
+       }
 }
 
 impl SignerProvider for TestKeysInterface {
@@ -688,7 +739,7 @@ impl SignerProvider for TestKeysInterface {
        fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
                let mut reader = io::Cursor::new(buffer);
 
-               let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?;
+               let inner: InMemorySigner = Readable::read(&mut reader)?;
                let state = self.make_enforcement_state_cell(inner.commitment_seed);
 
                Ok(EnforcingSigner::new_with_revoked(
diff --git a/pending_changelog/1878.txt b/pending_changelog/1878.txt
new file mode 100644 (file)
index 0000000..775c46e
--- /dev/null
@@ -0,0 +1,11 @@
+## API Updates
+- The functions `inbound_payment::{create, create_from_hash}` and
+  `channelmanager::{create_inbound_payment, create_inbound_payment_for_hash}` now accept a
+  `min_final_cltv_expiry_delta` argument. This encodes the `min_final_cltv_expiry_delta` in the
+  payment secret metadata bytes to be validated on payment receipt.
+
+## Backwards Compatibility
+- If `min_final_cltv_expiry_delta` set for any of `inbound_payment::{create, create_from_hash}` or
+  `channelmanager::{create_inbound_payment, create_inbound_payment_for_hash}` then the payment will
+  not be receivable on versions of LDK prior to 0.0.114.
+