Merge pull request #1977 from jkczyz/2023-01-offers-fuzz
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Sat, 25 Feb 2023 18:03:51 +0000 (18:03 +0000)
committerGitHub <noreply@github.com>
Sat, 25 Feb 2023 18:03:51 +0000 (18:03 +0000)
BOLT 12 deserialization fuzzers

61 files changed:
.github/workflows/build.yml
.gitignore
ARCH.md
Cargo.toml
SECURITY.md
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/indexedmap.rs
fuzz/src/router.rs
lightning-background-processor/src/lib.rs
lightning-custom-message/Cargo.toml [new file with mode: 0644]
lightning-custom-message/src/lib.rs [new file with mode: 0644]
lightning-invoice/src/payment.rs
lightning-invoice/src/utils.rs
lightning-net-tokio/src/lib.rs
lightning-rapid-gossip-sync/src/lib.rs
lightning-rapid-gossip-sync/src/processing.rs
lightning-transaction-sync/Cargo.toml [new file with mode: 0644]
lightning-transaction-sync/src/common.rs [new file with mode: 0644]
lightning-transaction-sync/src/error.rs [new file with mode: 0644]
lightning-transaction-sync/src/esplora.rs [new file with mode: 0644]
lightning-transaction-sync/src/lib.rs [new file with mode: 0644]
lightning-transaction-sync/tests/integration_tests.rs [new file with mode: 0644]
lightning/src/chain/chainmonitor.rs
lightning/src/chain/mod.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.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_handler.rs
lightning/src/ln/priv_short_conf_tests.rs
lightning/src/ln/reload_tests.rs
lightning/src/ln/reorg_tests.rs
lightning/src/ln/shutdown_tests.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/routing/gossip.rs
lightning/src/routing/mod.rs
lightning/src/routing/router.rs
lightning/src/routing/scoring.rs
lightning/src/routing/test_utils.rs
lightning/src/routing/utxo.rs [new file with mode: 0644]
lightning/src/sync/debug_sync.rs
lightning/src/sync/fairrwlock.rs [new file with mode: 0644]
lightning/src/sync/mod.rs
lightning/src/sync/nostd_sync.rs
lightning/src/sync/test_lockorder_checks.rs
lightning/src/util/events.rs
lightning/src/util/fairrwlock.rs [deleted file]
lightning/src/util/indexed_map.rs
lightning/src/util/mod.rs
lightning/src/util/ser.rs
lightning/src/util/ser_macros.rs
lightning/src/util/test_utils.rs

index 340b7f898d9ded31ba5b035e71fcf0ca83924419..a8f0aa69d94502caaf8e2e420c85a07821d6555b 100644 (file)
@@ -12,52 +12,72 @@ jobs:
                      beta,
                      # 1.41.1 is MSRV for Rust-Lightning, lightning-invoice, and lightning-persister
                      1.41.1,
-                     # 1.45.2 is MSRV for lightning-net-tokio, lightning-block-sync, lightning-background-processor, and coverage generation
+                     # 1.45.2 is MSRV for lightning-net-tokio, lightning-block-sync, lightning-background-processor
                      1.45.2,
                      # 1.47.0 will be the MSRV for no-std builds using hashbrown once core2 is updated
-                     1.47.0]
+                     1.47.0,
+                     # 1.59.0 is the MSRV for lightning-transaction-sync
+                     1.59.0]
         include:
           - toolchain: stable
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: true
+            coverage: true
           - toolchain: stable
             platform: macos-latest
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: true
+          - toolchain: stable
+            test-custom-message: true
           - toolchain: beta
             platform: macos-latest
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: true
           - toolchain: stable
             platform: windows-latest
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: false
           - toolchain: beta
             platform: windows-latest
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: false
           - toolchain: beta
             build-net-tokio: true
             build-no-std: true
             build-futures: true
+            build-tx-sync: true
+          - toolchain: beta
+            test-custom-message: true
           - toolchain: 1.41.1
             build-no-std: false
             test-log-variants: true
             build-futures: false
+            build-tx-sync: false
           - toolchain: 1.45.2
             build-net-old-tokio: true
             build-net-tokio: true
             build-no-std: false
             build-futures: true
-            coverage: true
+            build-tx-sync: false
           - toolchain: 1.47.0
             build-futures: true
             build-no-std: true
+            build-tx-sync: false
+          - toolchain: 1.59.0
+            build-net-tokio: false
+            build-no-std: false
+            build-futures: false
+            build-tx-sync: true
     runs-on: ${{ matrix.platform }}
     steps:
       - name: Checkout source code
@@ -73,10 +93,10 @@ jobs:
         run: cargo update -p tokio --precise "1.14.0" --verbose
         env:
           CARGO_NET_GIT_FETCH_WITH_CLI: "true"
-      - name: Build on Rust ${{ matrix.toolchain }} with net-tokio
-        if: "matrix.build-net-tokio && !matrix.coverage"
+      - name: Build on Rust ${{ matrix.toolchain }} with net-tokio and tx-sync
+        if: "matrix.build-net-tokio && !matrix.coverage && matrix.build-tx-sync"
         run: cargo build --verbose --color always
-      - name: Build on Rust ${{ matrix.toolchain }} with net-tokio and full code-linking for coverage generation
+      - name: Build on Rust ${{ matrix.toolchain }} with net-tokio, tx-sync, and full code-linking for coverage generation
         if: matrix.coverage
         run: RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always
       - name: Build on Rust ${{ matrix.toolchain }}
@@ -108,14 +128,32 @@ jobs:
           RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client
           RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client
           RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client,tokio
+      - name: Build Transaction Sync Clients on Rust ${{ matrix.toolchain }} with features
+        if: "matrix.build-tx-sync && !matrix.coverage"
+        run: |
+          cd lightning-transaction-sync
+          cargo build --verbose --color always --features esplora-blocking
+          cargo build --verbose --color always --features esplora-async
+      - name: Build transaction sync clients on Rust ${{ matrix.toolchain }} with features and full code-linking for coverage generation
+        if: "matrix.build-tx-sync && matrix.coverage"
+        run: |
+          cd lightning-transaction-sync
+          RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features esplora-blocking
+          RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features esplora-async
+      - name: Test transaction sync clients on Rust ${{ matrix.toolchain }} with features
+        if: "matrix.build-tx-sync"
+        run: |
+          cd lightning-transaction-sync
+          cargo test --verbose --color always --features esplora-blocking
+          cargo test --verbose --color always --features esplora-async
       - name: Test backtrace-debug builds on Rust ${{ matrix.toolchain }}
         if: "matrix.toolchain == 'stable'"
         run: |
           cd lightning && cargo test --verbose --color always --features backtrace
       - name: Test on Rust ${{ matrix.toolchain }} with net-tokio
-        if: "matrix.build-net-tokio && !matrix.coverage"
+        if: "matrix.build-net-tokio && !matrix.coverage && matrix.build-tx-sync"
         run: cargo test --verbose --color always
-      - name: Test on Rust ${{ matrix.toolchain }} with net-tokio and full code-linking for coverage generation
+      - name: Test on Rust ${{ matrix.toolchain }} with net-tokio, tx-sync, and full code-linking for coverage generation
         if: matrix.coverage
         run: RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always
       - name: Test no-std builds on Rust ${{ matrix.toolchain }}
@@ -192,6 +230,11 @@ jobs:
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client,tokio
+      - name: Test Custom Message Macros on Rust ${{ matrix.toolchain }}
+        if: "matrix.test-custom-message"
+        run: |
+          cd lightning-custom-message
+          cargo test --verbose --color always
       - name: Install deps for kcov
         if: matrix.coverage
         run: |
@@ -349,7 +392,7 @@ jobs:
   linting:
     runs-on: ubuntu-latest
     env:
-      TOOLCHAIN: 1.47.0
+      TOOLCHAIN: stable
     steps:
       - name: Checkout source code
         uses: actions/checkout@v3
index d99c5a4ddf6603b32fb97d666d49c3ebb631df79..7a889b5b8230af929cd28134454d2f93502531bd 100644 (file)
@@ -9,5 +9,5 @@ Cargo.lock
 .idea
 lightning/target
 lightning/ldk-net_graph-*.bin
+lightning-custom-message/target
 no-std-check/target
-
diff --git a/ARCH.md b/ARCH.md
index 9efccd9c9ddcec9d9812e0d0eb420975b3a0e98c..bd5fc1bd3164a5ce749ade66c19bb55f6fd74700 100644 (file)
--- a/ARCH.md
+++ b/ARCH.md
@@ -51,9 +51,9 @@ At a high level, some of the common interfaces fit together as follows:
 --------------- /                  (as EventsProvider)         ^            |           |
 | PeerManager |-                             \                 |            |           |
 ---------------                               \                | (is-a)     |           |
- |                    -----------------        \       _----------------   /           /
- |                    | chain::Access |         \     / | ChainMonitor |---------------
- |                    -----------------          \   /  ----------------
+ |                    --------------           \       _----------------   /           /
+ |                    | UtxoLookup |            \     / | ChainMonitor |---------------
+ |                    --------------             \   /  ----------------
  |                            ^                   \ /          |
 (as RoutingMessageHandler)    |                    v           v
   \                   -----------------        ---------   -----------------
index 89b92a8c6e4ba4e6a7bbd230d0e721230a552e6f..be76477f4c0f0548121cc8f5770053e798bbd3d0 100644 (file)
@@ -3,6 +3,7 @@
 members = [
     "lightning",
     "lightning-block-sync",
+    "lightning-transaction-sync",
     "lightning-invoice",
     "lightning-net-tokio",
     "lightning-persister",
@@ -11,6 +12,7 @@ members = [
 ]
 
 exclude = [
+    "lightning-custom-message",
     "no-std-check",
 ]
 
index d4b33ec3609019497ac93bfee2c6e6579f70644e..3f6b25fe8b993da805c3a8656527e74a50568fb8 100644 (file)
@@ -13,7 +13,7 @@ your own public key as an attachment or inline for replies.
 
  * 07DF3E57A548CCFB7530709189BBB8663E2E65CE (Matt Corallo)
  * 5DBC576CCCF546CA72AB06CE912EF12EA67705F5 (Jeffrey Czyz)
- * 729E9D9D92C75A5FBFEEE057B5DD717BEF7CA5B1 (Wilmer Paulino)
+ * 0A156842CF60B58BD826ABDD808FC696767C6147 (Wilmer Paulino)
  * BD6EED4D339EDBF7E7CE7F8836153082BDF676FD (Elias Rohrer)
  * 6E0287D8849AE741E47CC586FD3E106A2CE099B4 (Valentine Wallace)
  * 69CFEA635D0E6E6F13FD9D9136D932FCAC0305F0 (Arik Sosman)
index 0caee0801aa1d747ec6f564a2cc86f9658172f78..4386302f845b0d95279bbba99c975dede237df8a 100644 (file)
@@ -97,10 +97,6 @@ impl Router for FuzzRouter {
                        action: msgs::ErrorAction::IgnoreError
                })
        }
-       fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-       fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {}
-       fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {}
-       fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
 }
 
 pub struct TestBroadcaster {}
@@ -299,7 +295,7 @@ fn check_api_err(api_err: APIError) {
                        // all others. If you hit this panic, the list of acceptable errors
                        // is probably just stale and you should add new messages here.
                        match err.as_str() {
-                               "Peer for first hop currently disconnected/pending monitor update!" => {},
+                               "Peer for first hop currently disconnected" => {},
                                _ if err.starts_with("Cannot push more than their max accepted HTLCs ") => {},
                                _ if err.starts_with("Cannot send value that would put us over the max HTLC value in flight our peer will accept ") => {},
                                _ if err.starts_with("Cannot send value that would put our balance under counterparty-announced channel reserve value") => {},
@@ -478,8 +474,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
        let mut channel_txn = Vec::new();
        macro_rules! make_channel {
                ($source: expr, $dest: expr, $chan_id: expr) => { {
-                       $source.peer_connected(&$dest.get_our_node_id(), &Init { features: $dest.init_features(), remote_network_address: None }).unwrap();
-                       $dest.peer_connected(&$source.get_our_node_id(), &Init { features: $source.init_features(), remote_network_address: None }).unwrap();
+                       $source.peer_connected(&$dest.get_our_node_id(), &Init { features: $dest.init_features(), remote_network_address: None }, true).unwrap();
+                       $dest.peer_connected(&$source.get_our_node_id(), &Init { features: $source.init_features(), remote_network_address: None }, false).unwrap();
 
                        $source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None).unwrap();
                        let open_channel = {
@@ -918,6 +914,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
                                                events::Event::PaymentClaimed { .. } => {},
                                                events::Event::PaymentPathSuccessful { .. } => {},
                                                events::Event::PaymentPathFailed { .. } => {},
+                                               events::Event::PaymentFailed { .. } => {},
                                                events::Event::ProbeSuccessful { .. } | events::Event::ProbeFailed { .. } => {
                                                        // Even though we don't explicitly send probes, because probes are
                                                        // detected based on hashing the payment hash+preimage, its rather
@@ -982,31 +979,31 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
 
                        0x0c => {
                                if !chan_a_disconnected {
-                                       nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false);
-                                       nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false);
+                                       nodes[0].peer_disconnected(&nodes[1].get_our_node_id());
+                                       nodes[1].peer_disconnected(&nodes[0].get_our_node_id());
                                        chan_a_disconnected = true;
                                        drain_msg_events_on_disconnect!(0);
                                }
                        },
                        0x0d => {
                                if !chan_b_disconnected {
-                                       nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false);
-                                       nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false);
+                                       nodes[1].peer_disconnected(&nodes[2].get_our_node_id());
+                                       nodes[2].peer_disconnected(&nodes[1].get_our_node_id());
                                        chan_b_disconnected = true;
                                        drain_msg_events_on_disconnect!(2);
                                }
                        },
                        0x0e => {
                                if chan_a_disconnected {
-                                       nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }).unwrap();
-                                       nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: nodes[0].init_features(), remote_network_address: None }).unwrap();
+                                       nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }, true).unwrap();
+                                       nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: nodes[0].init_features(), remote_network_address: None }, false).unwrap();
                                        chan_a_disconnected = false;
                                }
                        },
                        0x0f => {
                                if chan_b_disconnected {
-                                       nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: nodes[2].init_features(), remote_network_address: None }).unwrap();
-                                       nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }).unwrap();
+                                       nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: nodes[2].init_features(), remote_network_address: None }, true).unwrap();
+                                       nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }, false).unwrap();
                                        chan_b_disconnected = false;
                                }
                        },
@@ -1043,7 +1040,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
 
                        0x2c => {
                                if !chan_a_disconnected {
-                                       nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false);
+                                       nodes[1].peer_disconnected(&nodes[0].get_our_node_id());
                                        chan_a_disconnected = true;
                                        drain_msg_events_on_disconnect!(0);
                                }
@@ -1057,14 +1054,14 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
                        },
                        0x2d => {
                                if !chan_a_disconnected {
-                                       nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false);
+                                       nodes[0].peer_disconnected(&nodes[1].get_our_node_id());
                                        chan_a_disconnected = true;
                                        nodes[0].get_and_clear_pending_msg_events();
                                        ab_events.clear();
                                        ba_events.clear();
                                }
                                if !chan_b_disconnected {
-                                       nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false);
+                                       nodes[2].peer_disconnected(&nodes[1].get_our_node_id());
                                        chan_b_disconnected = true;
                                        nodes[2].get_and_clear_pending_msg_events();
                                        bc_events.clear();
@@ -1076,7 +1073,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
                        },
                        0x2e => {
                                if !chan_b_disconnected {
-                                       nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false);
+                                       nodes[1].peer_disconnected(&nodes[2].get_our_node_id());
                                        chan_b_disconnected = true;
                                        drain_msg_events_on_disconnect!(2);
                                }
@@ -1201,13 +1198,13 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
 
                                // Next, make sure peers are all connected to each other
                                if chan_a_disconnected {
-                                       nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }).unwrap();
-                                       nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: nodes[0].init_features(), remote_network_address: None }).unwrap();
+                                       nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }, true).unwrap();
+                                       nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: nodes[0].init_features(), remote_network_address: None }, false).unwrap();
                                        chan_a_disconnected = false;
                                }
                                if chan_b_disconnected {
-                                       nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: nodes[2].init_features(), remote_network_address: None }).unwrap();
-                                       nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }).unwrap();
+                                       nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: nodes[2].init_features(), remote_network_address: None }, true).unwrap();
+                                       nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: nodes[1].init_features(), remote_network_address: None }, false).unwrap();
                                        chan_b_disconnected = false;
                                }
 
index fb2740c1de9c26acadb2f0e30f1b04f27cd85a48..ca42466880a110e3e0e24873efe85f377a4974ad 100644 (file)
@@ -41,6 +41,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
 use lightning::ln::msgs::{self, DecodeError};
 use lightning::ln::script::ShutdownScript;
 use lightning::routing::gossip::{P2PGossipSync, NetworkGraph};
+use lightning::routing::utxo::UtxoLookup;
 use lightning::routing::router::{find_route, InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, Router};
 use lightning::routing::scoring::FixedPenaltyScorer;
 use lightning::util::config::UserConfig;
@@ -139,10 +140,6 @@ impl Router for FuzzRouter {
                        action: msgs::ErrorAction::IgnoreError
                })
        }
-       fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-       fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {}
-       fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {}
-       fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
 }
 
 struct TestBroadcaster {
@@ -183,7 +180,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, Arc<KeyProvider>>;
+type PeerMan<'a> = PeerManager<Peer<'a>, Arc<ChannelMan<'a>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<dyn Logger>>>, Arc<dyn UtxoLookup>, Arc<dyn Logger>>>, IgnoringMessageHandler, Arc<dyn Logger>, IgnoringMessageHandler, Arc<KeyProvider>>;
 
 struct MoneyLossDetector<'a> {
        manager: Arc<ChannelMan<'a>>,
@@ -512,7 +509,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                        },
                        4 => {
                                let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
-                               let payment_params = PaymentParameters::from_node_id(get_pubkey!());
+                               let payment_params = PaymentParameters::from_node_id(get_pubkey!(), 42);
                                let params = RouteParameters {
                                        payment_params,
                                        final_value_msat,
@@ -536,7 +533,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                        },
                        15 => {
                                let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
-                               let payment_params = PaymentParameters::from_node_id(get_pubkey!());
+                               let payment_params = PaymentParameters::from_node_id(get_pubkey!(), 42);
                                let params = RouteParameters {
                                        payment_params,
                                        final_value_msat,
@@ -637,11 +634,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                        if let Err(e) = channelmanager.funding_transaction_generated(&funding_generation.0, &funding_generation.1, tx.clone()) {
                                                // It's possible the channel has been closed in the mean time, but any other
                                                // failure may be a bug.
-                                               if let APIError::ChannelUnavailable { err } = e {
-                                                       if !err.starts_with("Can't find a peer matching the passed counterparty node_id ") {
-                                                               assert_eq!(err, "No such channel");
-                                                       }
-                                               } else { panic!(); }
+                                               if let APIError::ChannelUnavailable { .. } = e { } else { panic!(); }
                                        }
                                        pending_funding_signatures.insert(funding_output, tx);
                                }
index 795d6175bb5dc2dd8aee2b0cdce76ccc6a95c12b..7cbb8957ad247f807ff91f8851af44f0b8a546a8 100644 (file)
@@ -13,14 +13,27 @@ use hashbrown::HashSet;
 
 use crate::utils::test_logger;
 
-fn check_eq(btree: &BTreeMap<u8, u8>, indexed: &IndexedMap<u8, u8>) {
+use std::ops::{RangeBounds, Bound};
+
+struct ExclLowerInclUpper(u8, u8);
+impl RangeBounds<u8> for ExclLowerInclUpper {
+       fn start_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.0) }
+       fn end_bound(&self) -> Bound<&u8> { Bound::Included(&self.1) }
+}
+struct ExclLowerExclUpper(u8, u8);
+impl RangeBounds<u8> for ExclLowerExclUpper {
+       fn start_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.0) }
+       fn end_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.1) }
+}
+
+fn check_eq(btree: &BTreeMap<u8, u8>, mut 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);
+       assert!(indexed_clone == indexed);
 
        for k in 0..=255 {
                assert_eq!(btree.contains_key(&k), indexed.contains_key(&k));
@@ -43,16 +56,27 @@ fn check_eq(btree: &BTreeMap<u8, u8>, indexed: &IndexedMap<u8, u8>) {
        }
 
        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; }
+       for range_type in 0..4 {
+               for k in 0..=255/STRIDE {
+                       let lower_bound = k * STRIDE;
+                       let upper_bound = lower_bound + (STRIDE - 1);
+                       macro_rules! range { ($map: expr) => {
+                               match range_type {
+                                       0 => $map.range(lower_bound..upper_bound),
+                                       1 => $map.range(lower_bound..=upper_bound),
+                                       2 => $map.range(ExclLowerInclUpper(lower_bound, upper_bound)),
+                                       3 => $map.range(ExclLowerExclUpper(lower_bound, upper_bound)),
+                                       _ => unreachable!(),
+                               }
+                       } }
+                       let mut btree_iter = range!(btree);
+                       let mut indexed_iter = range!(indexed);
+                       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; }
+                       }
                }
        }
 
@@ -91,7 +115,7 @@ pub fn do_test(data: &[u8]) {
                let prev_value_i = indexed.insert(tuple[0], tuple[1]);
                assert_eq!(prev_value_b, prev_value_i);
        }
-       check_eq(&btree, &indexed);
+       check_eq(&btree, indexed.clone());
 
        // Now, modify the maps in all the ways we have to do so, checking that the maps remain
        // equivalent as we go.
@@ -99,7 +123,7 @@ pub fn do_test(data: &[u8]) {
                *v = *k;
                *btree.get_mut(k).unwrap() = *k;
        }
-       check_eq(&btree, &indexed);
+       check_eq(&btree, indexed.clone());
 
        for k in 0..=255 {
                match btree.entry(k) {
@@ -124,7 +148,7 @@ pub fn do_test(data: &[u8]) {
                        },
                }
        }
-       check_eq(&btree, &indexed);
+       check_eq(&btree, indexed);
 }
 
 pub fn indexedmap_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
index 3e51d0c6a6d37fb4fdd0aa3df8f55987f2fa55be..a7c50de4a471de122c501d8a5789aced9e76bf53 100644 (file)
@@ -11,11 +11,11 @@ use bitcoin::blockdata::script::Builder;
 use bitcoin::blockdata::transaction::TxOut;
 use bitcoin::hash_types::BlockHash;
 
-use lightning::chain;
 use lightning::chain::transaction::OutPoint;
 use lightning::ln::channelmanager::{self, ChannelDetails, ChannelCounterparty};
 use lightning::ln::msgs;
 use lightning::routing::gossip::{NetworkGraph, RoutingFees};
+use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult};
 use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
 use lightning::routing::scoring::FixedPenaltyScorer;
 use lightning::util::config::UserConfig;
@@ -81,17 +81,36 @@ impl InputData {
        }
 }
 
-struct FuzzChainSource {
+struct FuzzChainSource<'a, 'b, Out: test_logger::Output> {
        input: Arc<InputData>,
+       net_graph: &'a NetworkGraph<&'b test_logger::TestLogger<Out>>,
 }
-impl chain::Access for FuzzChainSource {
-       fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> Result<TxOut, chain::AccessError> {
-               match self.input.get_slice(2) {
-                       Some(&[0, _]) => Err(chain::AccessError::UnknownChain),
-                       Some(&[1, _]) => Err(chain::AccessError::UnknownTx),
-                       Some(&[_, x]) => Ok(TxOut { value: 0, script_pubkey: Builder::new().push_int(x as i64).into_script().to_v0_p2wsh() }),
-                       None => Err(chain::AccessError::UnknownTx),
-                       _ => unreachable!(),
+impl<Out: test_logger::Output> UtxoLookup for FuzzChainSource<'_, '_, Out> {
+       fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> UtxoResult {
+               let input_slice = self.input.get_slice(2);
+               if input_slice.is_none() { return UtxoResult::Sync(Err(UtxoLookupError::UnknownTx)); }
+               let input_slice = input_slice.unwrap();
+               let txo_res = TxOut {
+                       value: if input_slice[0] % 2 == 0 { 1_000_000 } else { 1_000 },
+                       script_pubkey: Builder::new().push_int(input_slice[1] as i64).into_script().to_v0_p2wsh(),
+               };
+               match input_slice {
+                       &[0, _] => UtxoResult::Sync(Err(UtxoLookupError::UnknownChain)),
+                       &[1, _] => UtxoResult::Sync(Err(UtxoLookupError::UnknownTx)),
+                       &[2, _] => {
+                               let future = UtxoFuture::new();
+                               future.resolve_without_forwarding(self.net_graph, Ok(txo_res));
+                               UtxoResult::Async(future.clone())
+                       },
+                       &[3, _] => {
+                               let future = UtxoFuture::new();
+                               future.resolve_without_forwarding(self.net_graph, Err(UtxoLookupError::UnknownTx));
+                               UtxoResult::Async(future.clone())
+                       },
+                       &[4, _] => {
+                               UtxoResult::Async(UtxoFuture::new()) // the future will never resolve
+                       },
+                       &[..] => UtxoResult::Sync(Ok(txo_res)),
                }
        }
 }
@@ -149,6 +168,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                }
        }
 
+       macro_rules! get_pubkey_from_node_id {
+               ($node_id: expr ) => {
+                       match PublicKey::from_slice($node_id.as_slice()) {
+                               Ok(pk) => pk,
+                               Err(_) => return,
+                       }
+               }
+       }
+
        macro_rules! get_pubkey {
                () => {
                        match PublicKey::from_slice(get_slice!(33)) {
@@ -162,6 +190,10 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
 
        let our_pubkey = get_pubkey!();
        let net_graph = NetworkGraph::new(genesis_block(Network::Bitcoin).header.block_hash(), &logger);
+       let chain_source = FuzzChainSource {
+               input: Arc::clone(&input),
+               net_graph: &net_graph,
+       };
 
        let mut node_pks = HashSet::new();
        let mut scid = 42;
@@ -175,20 +207,21 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                        return;
                                }
                                let msg = decode_msg_with_len16!(msgs::UnsignedNodeAnnouncement, 288);
-                               node_pks.insert(msg.node_id);
+                               node_pks.insert(get_pubkey_from_node_id!(msg.node_id));
                                let _ = net_graph.update_node_from_unsigned_announcement(&msg);
                        },
                        1 => {
                                let msg = decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32+8+33*4);
-                               node_pks.insert(msg.node_id_1);
-                               node_pks.insert(msg.node_id_2);
-                               let _ = net_graph.update_channel_from_unsigned_announcement::<&FuzzChainSource>(&msg, &None);
+                               node_pks.insert(get_pubkey_from_node_id!(msg.node_id_1));
+                               node_pks.insert(get_pubkey_from_node_id!(msg.node_id_2));
+                               let _ = net_graph.update_channel_from_unsigned_announcement::
+                                       <&FuzzChainSource<'_, '_, Out>>(&msg, &None);
                        },
                        2 => {
                                let msg = decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32+8+33*4);
-                               node_pks.insert(msg.node_id_1);
-                               node_pks.insert(msg.node_id_2);
-                               let _ = net_graph.update_channel_from_unsigned_announcement(&msg, &Some(&FuzzChainSource { input: Arc::clone(&input) }));
+                               node_pks.insert(get_pubkey_from_node_id!(msg.node_id_1));
+                               node_pks.insert(get_pubkey_from_node_id!(msg.node_id_2));
+                               let _ = net_graph.update_channel_from_unsigned_announcement(&msg, &Some(&chain_source));
                        },
                        3 => {
                                let _ = net_graph.update_channel_unsigned(&decode_msg!(msgs::UnsignedChannelUpdate, 72));
@@ -263,10 +296,13 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let scorer = FixedPenaltyScorer::with_penalty(0);
                                let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32];
                                for target in node_pks.iter() {
+                                       let final_value_msat = slice_to_be64(get_slice!(8));
+                                       let final_cltv_expiry_delta = slice_to_be32(get_slice!(4));
                                        let route_params = RouteParameters {
-                                               payment_params: PaymentParameters::from_node_id(*target).with_route_hints(last_hops.clone()),
-                                               final_value_msat: slice_to_be64(get_slice!(8)),
-                                               final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
+                                               payment_params: PaymentParameters::from_node_id(*target, final_cltv_expiry_delta)
+                                                       .with_route_hints(last_hops.clone()),
+                                               final_value_msat,
+                                               final_cltv_expiry_delta,
                                        };
                                        let _ = find_route(&our_pubkey, &route_params, &net_graph,
                                                first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
index 4bd5e463f93d5a877d157e9d5d668e30f7ca9808..c471555d782113b659ec8a41b3cd273456e47632 100644 (file)
@@ -16,6 +16,9 @@
 #[cfg(any(test, feature = "std"))]
 extern crate core;
 
+#[cfg(not(feature = "std"))]
+extern crate alloc;
+
 #[macro_use] extern crate lightning;
 extern crate lightning_rapid_gossip_sync;
 
@@ -27,13 +30,13 @@ use lightning::ln::channelmanager::ChannelManager;
 use lightning::ln::msgs::{ChannelMessageHandler, OnionMessageHandler, RoutingMessageHandler};
 use lightning::ln::peer_handler::{CustomMessageHandler, PeerManager, SocketDescriptor};
 use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
+use lightning::routing::utxo::UtxoLookup;
 use lightning::routing::router::Router;
-use lightning::routing::scoring::WriteableScore;
+use lightning::routing::scoring::{Score, WriteableScore};
 use lightning::util::events::{Event, EventHandler, EventsProvider};
 use lightning::util::logger::Logger;
 use lightning::util::persist::Persister;
 use lightning_rapid_gossip_sync::RapidGossipSync;
-use lightning::io;
 
 use core::ops::Deref;
 use core::time::Duration;
@@ -49,6 +52,8 @@ use std::time::Instant;
 
 #[cfg(feature = "futures")]
 use futures_util::{select_biased, future::FutureExt, task};
+#[cfg(not(feature = "std"))]
+use alloc::vec::Vec;
 
 /// `BackgroundProcessor` takes care of tasks that (1) need to happen periodically to keep
 /// Rust-Lightning running properly, and (2) either can or should be run in the background. Its
@@ -111,13 +116,13 @@ const FIRST_NETWORK_PRUNE_TIMER: u64 = 1;
 
 /// Either [`P2PGossipSync`] or [`RapidGossipSync`].
 pub enum GossipSync<
-       P: Deref<Target = P2PGossipSync<G, A, L>>,
+       P: Deref<Target = P2PGossipSync<G, U, L>>,
        R: Deref<Target = RapidGossipSync<G, L>>,
        G: Deref<Target = NetworkGraph<L>>,
-       A: Deref,
+       U: Deref,
        L: Deref,
 >
-where A::Target: chain::Access, L::Target: Logger {
+where U::Target: UtxoLookup, L::Target: Logger {
        /// Gossip sync via the lightning peer-to-peer network as defined by BOLT 7.
        P2P(P),
        /// Rapid gossip sync from a trusted server.
@@ -127,13 +132,13 @@ where A::Target: chain::Access, L::Target: Logger {
 }
 
 impl<
-       P: Deref<Target = P2PGossipSync<G, A, L>>,
+       P: Deref<Target = P2PGossipSync<G, U, L>>,
        R: Deref<Target = RapidGossipSync<G, L>>,
        G: Deref<Target = NetworkGraph<L>>,
-       A: Deref,
+       U: Deref,
        L: Deref,
-> GossipSync<P, R, G, A, L>
-where A::Target: chain::Access, L::Target: Logger {
+> GossipSync<P, R, G, U, L>
+where U::Target: UtxoLookup, L::Target: Logger {
        fn network_graph(&self) -> Option<&G> {
                match self {
                        GossipSync::P2P(gossip_sync) => Some(gossip_sync.network_graph()),
@@ -158,10 +163,10 @@ where A::Target: chain::Access, L::Target: Logger {
 }
 
 /// (C-not exported) as the bindings concretize everything and have constructors for us
-impl<P: Deref<Target = P2PGossipSync<G, A, L>>, G: Deref<Target = NetworkGraph<L>>, A: Deref, L: Deref>
-       GossipSync<P, &RapidGossipSync<G, L>, G, A, L>
+impl<P: Deref<Target = P2PGossipSync<G, U, L>>, G: Deref<Target = NetworkGraph<L>>, U: Deref, L: Deref>
+       GossipSync<P, &RapidGossipSync<G, L>, G, U, L>
 where
-       A::Target: chain::Access,
+       U::Target: UtxoLookup,
        L::Target: Logger,
 {
        /// Initializes a new [`GossipSync::P2P`] variant.
@@ -173,10 +178,10 @@ where
 /// (C-not exported) as the bindings concretize everything and have constructors for us
 impl<'a, R: Deref<Target = RapidGossipSync<G, L>>, G: Deref<Target = NetworkGraph<L>>, L: Deref>
        GossipSync<
-               &P2PGossipSync<G, &'a (dyn chain::Access + Send + Sync), L>,
+               &P2PGossipSync<G, &'a (dyn UtxoLookup + Send + Sync), L>,
                R,
                G,
-               &'a (dyn chain::Access + Send + Sync),
+               &'a (dyn UtxoLookup + Send + Sync),
                L,
        >
 where
@@ -191,10 +196,10 @@ where
 /// (C-not exported) as the bindings concretize everything and have constructors for us
 impl<'a, L: Deref>
        GossipSync<
-               &P2PGossipSync<&'a NetworkGraph<L>, &'a (dyn chain::Access + Send + Sync), L>,
+               &P2PGossipSync<&'a NetworkGraph<L>, &'a (dyn UtxoLookup + Send + Sync), L>,
                &RapidGossipSync<&'a NetworkGraph<L>, L>,
                &'a NetworkGraph<L>,
-               &'a (dyn chain::Access + Send + Sync),
+               &'a (dyn UtxoLookup + Send + Sync),
                L,
        >
 where
@@ -216,6 +221,37 @@ fn handle_network_graph_update<L: Deref>(
        }
 }
 
+fn update_scorer<'a, S: 'static + Deref<Target = SC> + Send + Sync, SC: 'a + WriteableScore<'a>>(
+       scorer: &'a S, event: &Event
+) {
+       let mut score = scorer.lock();
+       match event {
+               Event::PaymentPathFailed { ref path, short_channel_id: Some(scid), .. } => {
+                       let path = path.iter().collect::<Vec<_>>();
+                       score.payment_path_failed(&path, *scid);
+               },
+               Event::PaymentPathFailed { ref path, payment_failed_permanently: true, .. } => {
+                       // Reached if the destination explicitly failed it back. We treat this as a successful probe
+                       // because the payment made it all the way to the destination with sufficient liquidity.
+                       let path = path.iter().collect::<Vec<_>>();
+                       score.probe_successful(&path);
+               },
+               Event::PaymentPathSuccessful { path, .. } => {
+                       let path = path.iter().collect::<Vec<_>>();
+                       score.payment_path_successful(&path);
+               },
+               Event::ProbeSuccessful { path, .. } => {
+                       let path = path.iter().collect::<Vec<_>>();
+                       score.probe_successful(&path);
+               },
+               Event::ProbeFailed { path, short_channel_id: Some(scid), .. } => {
+                       let path = path.iter().collect::<Vec<_>>();
+                       score.probe_failed(&path, *scid);
+               },
+               _ => {},
+       }
+}
+
 macro_rules! define_run_body {
        ($persister: ident, $chain_monitor: ident, $process_chain_monitor_events: expr,
         $channel_manager: ident, $process_channel_manager_events: expr,
@@ -361,7 +397,7 @@ macro_rules! define_run_body {
 #[cfg(feature = "futures")]
 pub async fn process_events_async<
        'a,
-       CA: 'static + Deref + Send + Sync,
+       UL: 'static + Deref + Send + Sync,
        CF: 'static + Deref + Send + Sync,
        CW: 'static + Deref + Send + Sync,
        T: 'static + Deref + Send + Sync,
@@ -382,21 +418,21 @@ pub async fn process_events_async<
        PS: 'static + Deref + Send,
        M: 'static + Deref<Target = ChainMonitor<<SP::Target as SignerProvider>::Signer, CF, T, F, L, P>> + Send + Sync,
        CM: 'static + Deref<Target = ChannelManager<CW, T, ES, NS, SP, F, R, L>> + Send + Sync,
-       PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
+       PGS: 'static + Deref<Target = P2PGossipSync<G, UL, 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, NS>> + Send + Sync,
        S: 'static + Deref<Target = SC> + Send + Sync,
-       SC: WriteableScore<'a>,
+       SC: for<'b> WriteableScore<'b>,
        SleepFuture: core::future::Future<Output = bool> + core::marker::Unpin,
        Sleeper: Fn(Duration) -> SleepFuture
 >(
        persister: PS, event_handler: EventHandler, chain_monitor: M, channel_manager: CM,
-       gossip_sync: GossipSync<PGS, RGS, G, CA, L>, peer_manager: PM, logger: L, scorer: Option<S>,
+       gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM, logger: L, scorer: Option<S>,
        sleeper: Sleeper,
-) -> Result<(), io::Error>
+) -> Result<(), lightning::io::Error>
 where
-       CA::Target: 'static + chain::Access,
+       UL::Target: 'static + UtxoLookup,
        CF::Target: 'static + chain::Filter,
        CW::Target: 'static + chain::Watch<<SP::Target as SignerProvider>::Signer>,
        T::Target: 'static + BroadcasterInterface,
@@ -417,10 +453,14 @@ where
        let async_event_handler = |event| {
                let network_graph = gossip_sync.network_graph();
                let event_handler = &event_handler;
+               let scorer = &scorer;
                async move {
                        if let Some(network_graph) = network_graph {
                                handle_network_graph_update(network_graph, &event)
                        }
+                       if let Some(ref scorer) = scorer {
+                               update_scorer(scorer, &event);
+                       }
                        event_handler(event).await;
                }
        };
@@ -491,7 +531,7 @@ impl BackgroundProcessor {
        /// [`NetworkGraph::write`]: lightning::routing::gossip::NetworkGraph#impl-Writeable
        pub fn start<
                'a,
-               CA: 'static + Deref + Send + Sync,
+               UL: 'static + Deref + Send + Sync,
                CF: 'static + Deref + Send + Sync,
                CW: 'static + Deref + Send + Sync,
                T: 'static + Deref + Send + Sync,
@@ -511,18 +551,18 @@ impl BackgroundProcessor {
                PS: 'static + Deref + Send,
                M: 'static + Deref<Target = ChainMonitor<<SP::Target as SignerProvider>::Signer, CF, T, F, L, P>> + Send + Sync,
                CM: 'static + Deref<Target = ChannelManager<CW, T, ES, NS, SP, F, R, L>> + Send + Sync,
-               PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
+               PGS: 'static + Deref<Target = P2PGossipSync<G, UL, 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, NS>> + Send + Sync,
                S: 'static + Deref<Target = SC> + Send + Sync,
-               SC: WriteableScore<'a>,
+               SC: for <'b> WriteableScore<'b>,
        >(
                persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM,
-               gossip_sync: GossipSync<PGS, RGS, G, CA, L>, peer_manager: PM, logger: L, scorer: Option<S>,
+               gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM, logger: L, scorer: Option<S>,
        ) -> Self
        where
-               CA::Target: 'static + chain::Access,
+               UL::Target: 'static + UtxoLookup,
                CF::Target: 'static + chain::Filter,
                CW::Target: 'static + chain::Watch<<SP::Target as SignerProvider>::Signer>,
                T::Target: 'static + BroadcasterInterface,
@@ -547,6 +587,9 @@ impl BackgroundProcessor {
                                if let Some(network_graph) = network_graph {
                                        handle_network_graph_update(network_graph, &event)
                                }
+                               if let Some(ref scorer) = scorer {
+                                       update_scorer(scorer, &event);
+                               }
                                event_handler.handle_event(event);
                        };
                        define_run_body!(persister, chain_monitor, chain_monitor.process_pending_events(&event_handler),
@@ -613,25 +656,28 @@ mod tests {
        use bitcoin::blockdata::locktime::PackedLockTime;
        use bitcoin::blockdata::transaction::{Transaction, TxOut};
        use bitcoin::network::constants::Network;
+       use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1};
        use lightning::chain::{BestBlock, Confirm, chainmonitor};
        use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
-       use lightning::chain::keysinterface::{InMemorySigner, EntropySource, KeysManager};
+       use lightning::chain::keysinterface::{InMemorySigner, KeysManager};
        use lightning::chain::transaction::OutPoint;
        use lightning::get_event_msg;
-       use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
-       use lightning::ln::features::ChannelFeatures;
+       use lightning::ln::PaymentHash;
+       use lightning::ln::channelmanager;
+       use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, MIN_CLTV_EXPIRY_DELTA, PaymentId};
+       use lightning::ln::features::{ChannelFeatures, NodeFeatures};
        use lightning::ln::msgs::{ChannelMessageHandler, Init};
        use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler};
-       use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
-       use lightning::routing::router::DefaultRouter;
-       use lightning::routing::scoring::{ProbabilisticScoringParameters, ProbabilisticScorer};
+       use lightning::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync};
+       use lightning::routing::router::{DefaultRouter, RouteHop};
+       use lightning::routing::scoring::{ChannelUsage, Score};
        use lightning::util::config::UserConfig;
        use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent};
        use lightning::util::ser::Writeable;
        use lightning::util::test_utils;
        use lightning::util::persist::KVStorePersister;
-       use lightning_invoice::payment::{InvoicePayer, Retry};
        use lightning_persister::FilesystemPersister;
+       use std::collections::VecDeque;
        use std::fs;
        use std::path::PathBuf;
        use std::sync::{Arc, Mutex};
@@ -654,13 +700,15 @@ mod tests {
                fn disconnect_socket(&mut self) {}
        }
 
+       type ChannelManager = channelmanager::ChannelManager<Arc<ChainMonitor>, Arc<test_utils::TestBroadcaster>, Arc<KeysManager>, Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestFeeEstimator>, Arc<DefaultRouter< Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<Mutex<TestScorer>>>>, Arc<test_utils::TestLogger>>;
+
        type ChainMonitor = chainmonitor::ChainMonitor<InMemorySigner, Arc<test_utils::TestChainSource>, Arc<test_utils::TestBroadcaster>, Arc<test_utils::TestFeeEstimator>, Arc<test_utils::TestLogger>, Arc<FilesystemPersister>>;
 
        type PGS = Arc<P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>>;
        type RGS = Arc<RapidGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>>>;
 
        struct Node {
-               node: Arc<SimpleArcChannelManager<ChainMonitor, test_utils::TestBroadcaster, test_utils::TestFeeEstimator, test_utils::TestLogger>>,
+               node: Arc<ChannelManager>,
                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, Arc<KeysManager>>>,
@@ -670,7 +718,7 @@ mod tests {
                network_graph: Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
                logger: Arc<test_utils::TestLogger>,
                best_block: BestBlock,
-               scorer: Arc<Mutex<ProbabilisticScorer<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>>>>,
+               scorer: Arc<Mutex<TestScorer>>,
        }
 
        impl Node {
@@ -756,6 +804,128 @@ mod tests {
                }
        }
 
+       struct TestScorer {
+               event_expectations: Option<VecDeque<TestResult>>,
+       }
+
+       #[derive(Debug)]
+       enum TestResult {
+               PaymentFailure { path: Vec<RouteHop>, short_channel_id: u64 },
+               PaymentSuccess { path: Vec<RouteHop> },
+               ProbeFailure { path: Vec<RouteHop> },
+               ProbeSuccess { path: Vec<RouteHop> },
+       }
+
+       impl TestScorer {
+               fn new() -> Self {
+                       Self { event_expectations: None }
+               }
+
+               fn expect(&mut self, expectation: TestResult) {
+                       self.event_expectations.get_or_insert_with(|| VecDeque::new()).push_back(expectation);
+               }
+       }
+
+       impl lightning::util::ser::Writeable for TestScorer {
+               fn write<W: lightning::util::ser::Writer>(&self, _: &mut W) -> Result<(), lightning::io::Error> { Ok(()) }
+       }
+
+       impl Score for TestScorer {
+               fn channel_penalty_msat(
+                       &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
+               ) -> u64 { unimplemented!(); }
+
+               fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
+                       if let Some(expectations) = &mut self.event_expectations {
+                               match expectations.pop_front().unwrap() {
+                                       TestResult::PaymentFailure { path, short_channel_id } => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                               assert_eq!(actual_short_channel_id, short_channel_id);
+                                       },
+                                       TestResult::PaymentSuccess { path } => {
+                                               panic!("Unexpected successful payment path: {:?}", path)
+                                       },
+                                       TestResult::ProbeFailure { path } => {
+                                               panic!("Unexpected probe failure: {:?}", path)
+                                       },
+                                       TestResult::ProbeSuccess { path } => {
+                                               panic!("Unexpected probe success: {:?}", path)
+                                       }
+                               }
+                       }
+               }
+
+               fn payment_path_successful(&mut self, actual_path: &[&RouteHop]) {
+                       if let Some(expectations) = &mut self.event_expectations {
+                               match expectations.pop_front().unwrap() {
+                                       TestResult::PaymentFailure { path, .. } => {
+                                               panic!("Unexpected payment path failure: {:?}", path)
+                                       },
+                                       TestResult::PaymentSuccess { path } => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                       },
+                                       TestResult::ProbeFailure { path } => {
+                                               panic!("Unexpected probe failure: {:?}", path)
+                                       },
+                                       TestResult::ProbeSuccess { path } => {
+                                               panic!("Unexpected probe success: {:?}", path)
+                                       }
+                               }
+                       }
+               }
+
+               fn probe_failed(&mut self, actual_path: &[&RouteHop], _: u64) {
+                       if let Some(expectations) = &mut self.event_expectations {
+                               match expectations.pop_front().unwrap() {
+                                       TestResult::PaymentFailure { path, .. } => {
+                                               panic!("Unexpected payment path failure: {:?}", path)
+                                       },
+                                       TestResult::PaymentSuccess { path } => {
+                                               panic!("Unexpected payment path success: {:?}", path)
+                                       },
+                                       TestResult::ProbeFailure { path } => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                       },
+                                       TestResult::ProbeSuccess { path } => {
+                                               panic!("Unexpected probe success: {:?}", path)
+                                       }
+                               }
+                       }
+               }
+               fn probe_successful(&mut self, actual_path: &[&RouteHop]) {
+                       if let Some(expectations) = &mut self.event_expectations {
+                               match expectations.pop_front().unwrap() {
+                                       TestResult::PaymentFailure { path, .. } => {
+                                               panic!("Unexpected payment path failure: {:?}", path)
+                                       },
+                                       TestResult::PaymentSuccess { path } => {
+                                               panic!("Unexpected payment path success: {:?}", path)
+                                       },
+                                       TestResult::ProbeFailure { path } => {
+                                               panic!("Unexpected probe failure: {:?}", path)
+                                       },
+                                       TestResult::ProbeSuccess { path } => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       impl Drop for TestScorer {
+               fn drop(&mut self) {
+                       if std::thread::panicking() {
+                               return;
+                       }
+
+                       if let Some(event_expectations) = &self.event_expectations {
+                               if !event_expectations.is_empty() {
+                                       panic!("Unsatisfied event expectations: {:?}", event_expectations);
+                               }
+                       }
+               }
+       }
+
        fn get_full_filepath(filepath: String, filename: String) -> String {
                let mut path = PathBuf::from(filepath);
                path.push(filename);
@@ -771,8 +941,7 @@ mod tests {
                        let network = Network::Testnet;
                        let genesis_block = genesis_block(network);
                        let network_graph = Arc::new(NetworkGraph::new(genesis_block.header.block_hash(), logger.clone()));
-                       let params = ProbabilisticScoringParameters::default();
-                       let scorer = Arc::new(Mutex::new(ProbabilisticScorer::new(params, network_graph.clone(), logger.clone())));
+                       let scorer = Arc::new(Mutex::new(TestScorer::new()));
                        let seed = [i as u8; 32];
                        let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), seed, scorer.clone()));
                        let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
@@ -793,8 +962,8 @@ mod tests {
 
                for i in 0..num_nodes {
                        for j in (i+1)..num_nodes {
-                               nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: nodes[j].node.init_features(), remote_network_address: None }).unwrap();
-                               nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: nodes[i].node.init_features(), remote_network_address: None }).unwrap();
+                               nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: nodes[j].node.init_features(), remote_network_address: None }, true).unwrap();
+                               nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: nodes[i].node.init_features(), remote_network_address: None }, false).unwrap();
                        }
                }
 
@@ -1141,7 +1310,7 @@ mod tests {
                        0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0,
                        0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192,
                ];
-               nodes[0].rapid_gossip_sync.update_network_graph(&initialization_input[..]).unwrap();
+               nodes[0].rapid_gossip_sync.update_network_graph_no_std(&initialization_input[..], Some(1642291930)).unwrap();
 
                // this should have added two channels
                assert_eq!(network_graph.read_only().channels().len(), 3);
@@ -1157,18 +1326,122 @@ mod tests {
        }
 
        #[test]
-       fn test_invoice_payer() {
-               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
-               let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let nodes = create_nodes(2, "test_invoice_payer".to_string());
+       fn test_payment_path_scoring() {
+               // Ensure that we update the scorer when relevant events are processed. In this case, we ensure
+               // that we update the scorer upon a payment path succeeding (note that the channel must be
+               // public or else we won't score it).
+               // Set up a background event handler for FundingGenerationReady events.
+               let (sender, receiver) = std::sync::mpsc::sync_channel(1);
+               let event_handler = move |event: Event| match event {
+                       Event::PaymentPathFailed { .. } => sender.send(event).unwrap(),
+                       Event::PaymentPathSuccessful { .. } => sender.send(event).unwrap(),
+                       Event::ProbeSuccessful { .. } => sender.send(event).unwrap(),
+                       Event::ProbeFailed { .. } => sender.send(event).unwrap(),
+                       _ => panic!("Unexpected event: {:?}", event),
+               };
 
-               // Initiate the background processors to watch each node.
+               let nodes = create_nodes(1, "test_payment_path_scoring".to_string());
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Arc::new(Persister::new(data_dir));
-               let router = Arc::new(DefaultRouter::new(Arc::clone(&nodes[0].network_graph), Arc::clone(&nodes[0].logger), random_seed_bytes, Arc::clone(&nodes[0].scorer)));
-               let invoice_payer = Arc::new(InvoicePayer::new(Arc::clone(&nodes[0].node), router, Arc::clone(&nodes[0].logger), |_: _| {}, Retry::Attempts(2)));
-               let event_handler = Arc::clone(&invoice_payer);
+               let persister = Arc::new(Persister::new(data_dir.clone()));
                let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+
+               let scored_scid = 4242;
+               let secp_ctx = Secp256k1::new();
+               let node_1_privkey = SecretKey::from_slice(&[42; 32]).unwrap();
+               let node_1_id = PublicKey::from_secret_key(&secp_ctx, &node_1_privkey);
+
+               let path = vec![RouteHop {
+                       pubkey: node_1_id,
+                       node_features: NodeFeatures::empty(),
+                       short_channel_id: scored_scid,
+                       channel_features: ChannelFeatures::empty(),
+                       fee_msat: 0,
+                       cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA as u32,
+               }];
+
+               nodes[0].scorer.lock().unwrap().expect(TestResult::PaymentFailure { path: path.clone(), short_channel_id: scored_scid });
+               nodes[0].node.push_pending_event(Event::PaymentPathFailed {
+                       payment_id: None,
+                       payment_hash: PaymentHash([42; 32]),
+                       payment_failed_permanently: false,
+                       network_update: None,
+                       all_paths_failed: true,
+                       path: path.clone(),
+                       short_channel_id: Some(scored_scid),
+                       retry: None,
+               });
+               let event = receiver
+                       .recv_timeout(Duration::from_secs(EVENT_DEADLINE))
+                       .expect("PaymentPathFailed not handled within deadline");
+               match event {
+                       Event::PaymentPathFailed { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+
+               // Ensure we'll score payments that were explicitly failed back by the destination as
+               // ProbeSuccess.
+               nodes[0].scorer.lock().unwrap().expect(TestResult::ProbeSuccess { path: path.clone() });
+               nodes[0].node.push_pending_event(Event::PaymentPathFailed {
+                       payment_id: None,
+                       payment_hash: PaymentHash([42; 32]),
+                       payment_failed_permanently: true,
+                       network_update: None,
+                       all_paths_failed: true,
+                       path: path.clone(),
+                       short_channel_id: None,
+                       retry: None,
+               });
+               let event = receiver
+                       .recv_timeout(Duration::from_secs(EVENT_DEADLINE))
+                       .expect("PaymentPathFailed not handled within deadline");
+               match event {
+                       Event::PaymentPathFailed { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+
+               nodes[0].scorer.lock().unwrap().expect(TestResult::PaymentSuccess { path: path.clone() });
+               nodes[0].node.push_pending_event(Event::PaymentPathSuccessful {
+                       payment_id: PaymentId([42; 32]),
+                       payment_hash: None,
+                       path: path.clone(),
+               });
+               let event = receiver
+                       .recv_timeout(Duration::from_secs(EVENT_DEADLINE))
+                       .expect("PaymentPathSuccessful not handled within deadline");
+               match event {
+                       Event::PaymentPathSuccessful { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+
+               nodes[0].scorer.lock().unwrap().expect(TestResult::ProbeSuccess { path: path.clone() });
+               nodes[0].node.push_pending_event(Event::ProbeSuccessful {
+                       payment_id: PaymentId([42; 32]),
+                       payment_hash: PaymentHash([42; 32]),
+                       path: path.clone(),
+               });
+               let event = receiver
+                       .recv_timeout(Duration::from_secs(EVENT_DEADLINE))
+                       .expect("ProbeSuccessful not handled within deadline");
+               match event {
+                       Event::ProbeSuccessful  { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+
+               nodes[0].scorer.lock().unwrap().expect(TestResult::ProbeFailure { path: path.clone() });
+               nodes[0].node.push_pending_event(Event::ProbeFailed {
+                       payment_id: PaymentId([42; 32]),
+                       payment_hash: PaymentHash([42; 32]),
+                       path: path.clone(),
+                       short_channel_id: Some(scored_scid),
+               });
+               let event = receiver
+                       .recv_timeout(Duration::from_secs(EVENT_DEADLINE))
+                       .expect("ProbeFailure not handled within deadline");
+               match event {
+                       Event::ProbeFailed { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+
                assert!(bg_processor.stop().is_ok());
        }
 }
diff --git a/lightning-custom-message/Cargo.toml b/lightning-custom-message/Cargo.toml
new file mode 100644 (file)
index 0000000..657844c
--- /dev/null
@@ -0,0 +1,18 @@
+[package]
+name = "lightning-custom-message"
+version = "0.0.113"
+authors = ["Jeffrey Czyz"]
+license = "MIT OR Apache-2.0"
+repository = "http://github.com/lightningdevkit/rust-lightning"
+description = """
+Utilities for supporting custom peer-to-peer messages in LDK.
+"""
+edition = "2021"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+
+[dependencies]
+bitcoin = "0.29.0"
+lightning = { version = "0.0.113", path = "../lightning" }
diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
new file mode 100644 (file)
index 0000000..a6e4397
--- /dev/null
@@ -0,0 +1,310 @@
+//! Utilities for supporting custom peer-to-peer messages in LDK.
+//!
+//! [BOLT 1] specifies a custom message type range for use with experimental or application-specific
+//! messages. While a [`CustomMessageHandler`] can be defined to support more than one message type,
+//! defining such a handler requires a significant amount of boilerplate and can be error prone.
+//!
+//! This crate provides the [`composite_custom_message_handler`] macro for easily composing
+//! pre-defined custom message handlers into one handler. The resulting handler can be further
+//! composed with other custom message handlers using the same macro.
+//!
+//! The following example demonstrates defining a `FooBarHandler` to compose separate handlers for
+//! `Foo` and `Bar` messages, and further composing it with a handler for `Baz` messages.
+//!
+//!```
+//! # extern crate bitcoin;
+//! extern crate lightning;
+//! #[macro_use]
+//! extern crate lightning_custom_message;
+//!
+//! # use bitcoin::secp256k1::PublicKey;
+//! # use lightning::io;
+//! # use lightning::ln::msgs::{DecodeError, LightningError};
+//! use lightning::ln::peer_handler::CustomMessageHandler;
+//! use lightning::ln::wire::{CustomMessageReader, self};
+//! use lightning::util::ser::Writeable;
+//! # use lightning::util::ser::Writer;
+//!
+//! // Assume that `FooHandler` and `BarHandler` are defined in one crate and `BazHandler` is
+//! // defined in another crate, handling messages `Foo`, `Bar`, and `Baz`, respectively.
+//!
+//! #[derive(Debug)]
+//! pub struct Foo;
+//!
+//! macro_rules! foo_type_id {
+//!     () => { 32768 }
+//! }
+//!
+//! impl wire::Type for Foo {
+//!     fn type_id(&self) -> u16 { foo_type_id!() }
+//! }
+//! impl Writeable for Foo {
+//!     // ...
+//! #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! pub struct FooHandler;
+//!
+//! impl CustomMessageReader for FooHandler {
+//!     // ...
+//! #     type CustomMessage = Foo;
+//! #     fn read<R: io::Read>(
+//! #         &self, _message_type: u16, _buffer: &mut R
+//! #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//! impl CustomMessageHandler for FooHandler {
+//!     // ...
+//! #     fn handle_custom_message(
+//! #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
+//! #     ) -> Result<(), LightningError> {
+//! #         unimplemented!()
+//! #     }
+//! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! #[derive(Debug)]
+//! pub struct Bar;
+//!
+//! macro_rules! bar_type_id {
+//!     () => { 32769 }
+//! }
+//!
+//! impl wire::Type for Bar {
+//!     fn type_id(&self) -> u16 { bar_type_id!() }
+//! }
+//! impl Writeable for Bar {
+//!     // ...
+//! #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! pub struct BarHandler;
+//!
+//! impl CustomMessageReader for BarHandler {
+//!     // ...
+//! #     type CustomMessage = Bar;
+//! #     fn read<R: io::Read>(
+//! #         &self, _message_type: u16, _buffer: &mut R
+//! #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//! impl CustomMessageHandler for BarHandler {
+//!     // ...
+//! #     fn handle_custom_message(
+//! #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
+//! #     ) -> Result<(), LightningError> {
+//! #         unimplemented!()
+//! #     }
+//! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! #[derive(Debug)]
+//! pub struct Baz;
+//!
+//! macro_rules! baz_type_id {
+//!     () => { 32770 }
+//! }
+//!
+//! impl wire::Type for Baz {
+//!     fn type_id(&self) -> u16 { baz_type_id!() }
+//! }
+//! impl Writeable for Baz {
+//!     // ...
+//! #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! pub struct BazHandler;
+//!
+//! impl CustomMessageReader for BazHandler {
+//!     // ...
+//! #     type CustomMessage = Baz;
+//! #     fn read<R: io::Read>(
+//! #         &self, _message_type: u16, _buffer: &mut R
+//! #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//! impl CustomMessageHandler for BazHandler {
+//!     // ...
+//! #     fn handle_custom_message(
+//! #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
+//! #     ) -> Result<(), LightningError> {
+//! #         unimplemented!()
+//! #     }
+//! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
+//! #         unimplemented!()
+//! #     }
+//! }
+//!
+//! # fn main() {
+//! // The first crate may define a handler composing `FooHandler` and `BarHandler` and export the
+//! // corresponding message type ids as a macro to use in further composition.
+//!
+//! composite_custom_message_handler!(
+//!     pub struct FooBarHandler {
+//!         foo: FooHandler,
+//!         bar: BarHandler,
+//!     }
+//!
+//!     pub enum FooBarMessage {
+//!         Foo(foo_type_id!()),
+//!         Bar(bar_type_id!()),
+//!     }
+//! );
+//!
+//! #[macro_export]
+//! macro_rules! foo_bar_type_ids {
+//!     () => { foo_type_id!() | bar_type_id!() }
+//! }
+//!
+//! // Another crate can then define a handler further composing `FooBarHandler` with `BazHandler`
+//! // and similarly export the composition of message type ids as a macro.
+//!
+//! composite_custom_message_handler!(
+//!     pub struct FooBarBazHandler {
+//!         foo_bar: FooBarHandler,
+//!         baz: BazHandler,
+//!     }
+//!
+//!     pub enum FooBarBazMessage {
+//!         FooBar(foo_bar_type_ids!()),
+//!         Baz(baz_type_id!()),
+//!     }
+//! );
+//!
+//! #[macro_export]
+//! macro_rules! foo_bar_baz_type_ids {
+//!     () => { foo_bar_type_ids!() | baz_type_id!() }
+//! }
+//! # }
+//!```
+//!
+//! [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md
+//! [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
+
+#![doc(test(no_crate_inject, attr(deny(warnings))))]
+
+pub extern crate bitcoin;
+pub extern crate lightning;
+
+/// Defines a composite type implementing [`CustomMessageHandler`] (and therefore also implementing
+/// [`CustomMessageReader`]), along with a corresponding enumerated custom message [`Type`], from
+/// one or more previously defined custom message handlers.
+///
+/// Useful for parameterizing [`PeerManager`] with custom message handling for one or more sets of
+/// custom messages. Message type ids may be given as a valid `match` pattern, including ranges,
+/// though using OR-ed literal patterns is preferred in order to catch unreachable code for
+/// conflicting handlers.
+///
+/// See [crate documentation] for example usage.
+///
+/// [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
+/// [`CustomMessageReader`]: crate::lightning::ln::wire::CustomMessageReader
+/// [`Type`]: crate::lightning::ln::wire::Type
+/// [`PeerManager`]: crate::lightning::ln::peer_handler::PeerManager
+/// [crate documentation]: self
+#[macro_export]
+macro_rules! composite_custom_message_handler {
+       (
+               $handler_visibility:vis struct $handler:ident {
+                       $($field_visibility:vis $field:ident: $type:ty),* $(,)*
+               }
+
+               $message_visibility:vis enum $message:ident {
+                       $($variant:ident($pattern:pat)),* $(,)*
+               }
+       ) => {
+               #[allow(missing_docs)]
+               $handler_visibility struct $handler {
+                       $(
+                               $field_visibility $field: $type,
+                       )*
+               }
+
+               #[allow(missing_docs)]
+               #[derive(Debug)]
+               $message_visibility enum $message {
+                       $(
+                               $variant(<$type as $crate::lightning::ln::wire::CustomMessageReader>::CustomMessage),
+                       )*
+               }
+
+               impl $crate::lightning::ln::peer_handler::CustomMessageHandler for $handler {
+                       fn handle_custom_message(
+                               &self, msg: Self::CustomMessage, sender_node_id: &$crate::bitcoin::secp256k1::PublicKey
+                       ) -> Result<(), $crate::lightning::ln::msgs::LightningError> {
+                               match msg {
+                                       $(
+                                               $message::$variant(message) => {
+                                                       $crate::lightning::ln::peer_handler::CustomMessageHandler::handle_custom_message(
+                                                               &self.$field, message, sender_node_id
+                                                       )
+                                               },
+                                       )*
+                               }
+                       }
+
+                       fn get_and_clear_pending_msg(&self) -> Vec<($crate::bitcoin::secp256k1::PublicKey, Self::CustomMessage)> {
+                               vec![].into_iter()
+                                       $(
+                                               .chain(
+                                                       self.$field
+                                                               .get_and_clear_pending_msg()
+                                                               .into_iter()
+                                                               .map(|(pubkey, message)| (pubkey, $message::$variant(message)))
+                                               )
+                                       )*
+                                       .collect()
+                       }
+               }
+
+               impl $crate::lightning::ln::wire::CustomMessageReader for $handler {
+                       type CustomMessage = $message;
+                       fn read<R: $crate::lightning::io::Read>(
+                               &self, message_type: u16, buffer: &mut R
+                       ) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> {
+                               match message_type {
+                                       $(
+                                               $pattern => match <$type>::read(&self.$field, message_type, buffer)? {
+                                                       None => unreachable!(),
+                                                       Some(message) => Ok(Some($message::$variant(message))),
+                                               },
+                                       )*
+                                       _ => Ok(None),
+                               }
+                       }
+               }
+
+               impl $crate::lightning::ln::wire::Type for $message {
+                       fn type_id(&self) -> u16 {
+                               match self {
+                                       $(
+                                               Self::$variant(message) => message.type_id(),
+                                       )*
+                               }
+                       }
+               }
+
+               impl $crate::lightning::util::ser::Writeable for $message {
+                       fn write<W: $crate::lightning::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::lightning::io::Error> {
+                               match self {
+                                       $(
+                                               Self::$variant(message) => message.write(writer),
+                                       )*
+                               }
+                       }
+               }
+       }
+}
index a3517264b4a0bd1e8846f26afbf975f0f77b42eb..db47f9954800a2296785bdabd622aa31b7bd41c4 100644 (file)
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-//! A module for paying Lightning invoices and sending spontaneous payments.
-//!
-//! Defines an [`InvoicePayer`] utility for sending payments, parameterized by [`Payer`] and
-//! [`Router`] traits. Implementations of [`Payer`] provide the payer's node id, channels, and means
-//! to send a payment over a [`Route`]. Implementations of [`Router`] find a [`Route`] between payer
-//! and payee using information provided by the payer and from the payee's [`Invoice`], when
-//! applicable.
-//!
-//! [`InvoicePayer`] uses its [`Router`] parameterization for optionally notifying scorers upon
-//! receiving the [`Event::PaymentPathFailed`] and [`Event::PaymentPathSuccessful`] events.
-//! It also does the same for payment probe failure and success events using [`Event::ProbeFailed`]
-//! and [`Event::ProbeSuccessful`].
-//!
-//! [`InvoicePayer`] is capable of retrying failed payments. It accomplishes this by implementing
-//! [`EventHandler`] which decorates a user-provided handler. It will intercept any
-//! [`Event::PaymentPathFailed`] events and retry the failed paths for a fixed number of total
-//! attempts or until retry is no longer possible. In such a situation, [`InvoicePayer`] will pass
-//! along the events to the user-provided handler.
-//!
-//! # Example
-//!
-//! ```
-//! # extern crate lightning;
-//! # extern crate lightning_invoice;
-//! # extern crate secp256k1;
-//! #
-//! # use lightning::io;
-//! # use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-//! # use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
-//! # use lightning::ln::msgs::LightningError;
-//! # use lightning::routing::gossip::NodeId;
-//! # use lightning::routing::router::{InFlightHtlcs, Route, RouteHop, RouteParameters, Router};
-//! # use lightning::routing::scoring::{ChannelUsage, Score};
-//! # use lightning::util::events::{Event, EventHandler, EventsProvider};
-//! # use lightning::util::logger::{Logger, Record};
-//! # use lightning::util::ser::{Writeable, Writer};
-//! # use lightning_invoice::Invoice;
-//! # use lightning_invoice::payment::{InvoicePayer, Payer, Retry};
-//! # use secp256k1::PublicKey;
-//! # use std::cell::RefCell;
-//! # use std::ops::Deref;
-//! #
-//! # struct FakeEventProvider {}
-//! # impl EventsProvider for FakeEventProvider {
-//! #     fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler {}
-//! # }
-//! #
-//! # struct FakePayer {}
-//! # impl Payer for FakePayer {
-//! #     fn node_id(&self) -> PublicKey { unimplemented!() }
-//! #     fn first_hops(&self) -> Vec<ChannelDetails> { unimplemented!() }
-//! #     fn send_payment(
-//! #         &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
-//! #         payment_id: PaymentId
-//! #     ) -> Result<(), PaymentSendFailure> { unimplemented!() }
-//! #     fn send_spontaneous_payment(
-//! #         &self, route: &Route, payment_preimage: PaymentPreimage, payment_id: PaymentId,
-//! #     ) -> Result<(), PaymentSendFailure> { unimplemented!() }
-//! #     fn retry_payment(
-//! #         &self, route: &Route, payment_id: PaymentId
-//! #     ) -> Result<(), PaymentSendFailure> { unimplemented!() }
-//! #     fn abandon_payment(&self, payment_id: PaymentId) { unimplemented!() }
-//! #     fn inflight_htlcs(&self) -> InFlightHtlcs { unimplemented!() }
-//! # }
-//! #
-//! # struct FakeRouter {}
-//! # impl Router for FakeRouter {
-//! #     fn find_route(
-//! #         &self, payer: &PublicKey, params: &RouteParameters,
-//! #         first_hops: Option<&[&ChannelDetails]>, _inflight_htlcs: &InFlightHtlcs
-//! #     ) -> Result<Route, LightningError> { unimplemented!() }
-//! #     fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64) {  unimplemented!() }
-//! #     fn notify_payment_path_successful(&self, path: &[&RouteHop]) {  unimplemented!() }
-//! #     fn notify_payment_probe_successful(&self, path: &[&RouteHop]) {  unimplemented!() }
-//! #     fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64) { unimplemented!() }
-//! # }
-//! #
-//! # struct FakeScorer {}
-//! # impl Writeable for FakeScorer {
-//! #     fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> { unimplemented!(); }
-//! # }
-//! # impl Score for FakeScorer {
-//! #     fn channel_penalty_msat(
-//! #         &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
-//! #     ) -> u64 { 0 }
-//! #     fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
-//! #     fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
-//! #     fn probe_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
-//! #     fn probe_successful(&mut self, _path: &[&RouteHop]) {}
-//! # }
-//! #
-//! # struct FakeLogger {}
-//! # impl Logger for FakeLogger {
-//! #     fn log(&self, record: &Record) { unimplemented!() }
-//! # }
-//! #
-//! # fn main() {
-//! let event_handler = |event: Event| {
-//!     match event {
-//!         Event::PaymentPathFailed { .. } => println!("payment failed after retries"),
-//!         Event::PaymentSent { .. } => println!("payment successful"),
-//!         _ => {},
-//!     }
-//! };
-//! # let payer = FakePayer {};
-//! # let router = FakeRouter {};
-//! # let scorer = RefCell::new(FakeScorer {});
-//! # let logger = FakeLogger {};
-//! let invoice_payer = InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-//!
-//! let invoice = "...";
-//! if let Ok(invoice) = invoice.parse::<Invoice>() {
-//!     invoice_payer.pay_invoice(&invoice).unwrap();
-//!
-//! # let event_provider = FakeEventProvider {};
-//!     loop {
-//!         event_provider.process_pending_events(&invoice_payer);
-//!     }
-//! }
-//! # }
-//! ```
-//!
-//! # Note
-//!
-//! The [`Route`] is computed before each payment attempt. Any updates affecting path finding such
-//! as updates to the network graph or changes to channel scores should be applied prior to
-//! retries, typically by way of composing [`EventHandler`]s accordingly.
+//! Convenient utilities for paying Lightning invoices and sending spontaneous payments.
 
 use crate::Invoice;
 
 use bitcoin_hashes::Hash;
-use bitcoin_hashes::sha256::Hash as Sha256;
 
-use crate::prelude::*;
-use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
-use lightning::ln::msgs::LightningError;
-use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router};
-use lightning::util::events::{Event, EventHandler};
+use lightning::chain;
+use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
+use lightning::chain::keysinterface::{NodeSigner, SignerProvider, EntropySource};
+use lightning::ln::{PaymentHash, PaymentSecret};
+use lightning::ln::channelmanager::{ChannelManager, PaymentId, Retry, RetryableSendFailure};
+use lightning::routing::router::{PaymentParameters, RouteParameters, Router};
 use lightning::util::logger::Logger;
-use crate::time_utils::Time;
-use crate::sync::Mutex;
 
-use secp256k1::PublicKey;
-
-use core::fmt;
-use core::fmt::{Debug, Display, Formatter};
-use core::future::Future;
+use core::fmt::Debug;
 use core::ops::Deref;
 use core::time::Duration;
-#[cfg(feature = "std")]
-use std::time::SystemTime;
 
-/// A utility for paying [`Invoice`]s and sending spontaneous payments.
+/// Pays the given [`Invoice`], retrying if needed based on [`Retry`].
 ///
-/// See [module-level documentation] for details.
+/// [`Invoice::payment_hash`] is used as the [`PaymentId`], which ensures idempotency as long
+/// as the payment is still pending. Once the payment completes or fails, you must ensure that
+/// a second payment with the same [`PaymentHash`] is never sent.
 ///
-/// [module-level documentation]: crate::payment
-pub type InvoicePayer<P, R, L, E> = InvoicePayerUsingTime::<P, R, L, E, ConfiguredTime>;
-
-#[cfg(not(feature = "no-std"))]
-type ConfiguredTime = std::time::Instant;
-#[cfg(feature = "no-std")]
-use crate::time_utils;
-#[cfg(feature = "no-std")]
-type ConfiguredTime = time_utils::Eternity;
-
-/// Sealed trait with a blanket implementation to allow both sync and async implementations of event
-/// handling to exist within the InvoicePayer.
-mod sealed {
-       pub trait BaseEventHandler {}
-       impl<T> BaseEventHandler for T {}
-}
-
-/// (C-not exported) generally all users should use the [`InvoicePayer`] type alias.
-pub struct InvoicePayerUsingTime<
-       P: Deref,
-       R: Deref,
-       L: Deref,
-       E: sealed::BaseEventHandler,
-       T: Time
-> where
-       P::Target: Payer,
-       R::Target: Router,
-       L::Target: Logger,
+/// If you wish to use a different payment idempotency token, see [`pay_invoice_with_id`].
+pub fn pay_invoice<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
+       invoice: &Invoice, retry_strategy: Retry,
+       channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>
+) -> Result<PaymentId, PaymentError>
+where
+               M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
+               T::Target: BroadcasterInterface,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+               R::Target: Router,
+               L::Target: Logger,
 {
-       payer: P,
-       router: R,
-       logger: L,
-       event_handler: E,
-       /// Caches the overall attempts at making a payment, which is updated prior to retrying.
-       payment_cache: Mutex<HashMap<PaymentHash, PaymentAttempts<T>>>,
-       retry: Retry,
-}
-
-/// Storing minimal payment attempts information required for determining if a outbound payment can
-/// be retried.
-#[derive(Clone, Copy)]
-struct PaymentAttempts<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 now known yet.
-       count: usize,
-       /// This field is only used when retry is [`Retry::Timeout`] which is only build with feature std
-       first_attempted_at: T
+       let payment_id = PaymentId(invoice.payment_hash().into_inner());
+       pay_invoice_with_id(invoice, payment_id, retry_strategy, channelmanager)
+               .map(|()| payment_id)
 }
 
-impl<T: Time> PaymentAttempts<T> {
-       fn new() -> Self {
-               PaymentAttempts {
-                       count: 0,
-                       first_attempted_at: T::now()
-               }
-       }
+/// Pays the given [`Invoice`] with a custom idempotency key, retrying if needed based on [`Retry`].
+///
+/// Note that idempotency is only guaranteed as long as the payment is still pending. Once the
+/// payment completes or fails, no idempotency guarantees are made.
+///
+/// You should ensure that the [`Invoice::payment_hash`] is unique and the same [`PaymentHash`]
+/// has never been paid before.
+///
+/// See [`pay_invoice`] for a variant which uses the [`PaymentHash`] for the idempotency token.
+pub fn pay_invoice_with_id<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
+       invoice: &Invoice, payment_id: PaymentId, retry_strategy: Retry,
+       channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>
+) -> Result<(), PaymentError>
+where
+               M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
+               T::Target: BroadcasterInterface,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+               R::Target: Router,
+               L::Target: Logger,
+{
+       let amt_msat = invoice.amount_milli_satoshis().ok_or(PaymentError::Invoice("amount missing"))?;
+       pay_invoice_using_amount(invoice, amt_msat, payment_id, retry_strategy, channelmanager)
 }
 
-impl<T: Time> Display for PaymentAttempts<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()
-               );
-       }
+/// Pays the given zero-value [`Invoice`] using the given amount, retrying if needed based on
+/// [`Retry`].
+///
+/// [`Invoice::payment_hash`] is used as the [`PaymentId`], which ensures idempotency as long
+/// as the payment is still pending. Once the payment completes or fails, you must ensure that
+/// a second payment with the same [`PaymentHash`] is never sent.
+///
+/// If you wish to use a different payment idempotency token, see
+/// [`pay_zero_value_invoice_with_id`].
+pub fn pay_zero_value_invoice<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
+       invoice: &Invoice, amount_msats: u64, retry_strategy: Retry,
+       channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>
+) -> Result<PaymentId, PaymentError>
+where
+               M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
+               T::Target: BroadcasterInterface,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+               R::Target: Router,
+               L::Target: Logger,
+{
+       let payment_id = PaymentId(invoice.payment_hash().into_inner());
+       pay_zero_value_invoice_with_id(invoice, amount_msats, payment_id, retry_strategy,
+               channelmanager)
+               .map(|()| payment_id)
 }
 
-/// A trait defining behavior of an [`Invoice`] payer.
-///
-/// While the behavior of [`InvoicePayer`] provides idempotency of duplicate `send_*payment` calls
-/// with the same [`PaymentHash`], it is up to the `Payer` to provide idempotency across restarts.
+/// Pays the given zero-value [`Invoice`] using the given amount and custom idempotency key,
+/// , retrying if needed based on [`Retry`].
 ///
-/// [`ChannelManager`] provides idempotency for duplicate payments with the same [`PaymentId`].
+/// Note that idempotency is only guaranteed as long as the payment is still pending. Once the
+/// payment completes or fails, no idempotency guarantees are made.
 ///
-/// In order to trivially ensure idempotency for payments, the default `Payer` implementation
-/// reuses the [`PaymentHash`] bytes as the [`PaymentId`]. Custom implementations wishing to
-/// provide payment idempotency with a different idempotency key (i.e. [`PaymentId`]) should map
-/// the [`Invoice`] or spontaneous payment target pubkey to their own idempotency key.
+/// You should ensure that the [`Invoice::payment_hash`] is unique and the same [`PaymentHash`]
+/// has never been paid before.
 ///
-/// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
-pub trait Payer {
-       /// Returns the payer's node id.
-       fn node_id(&self) -> PublicKey;
-
-       /// Returns the payer's channels.
-       fn first_hops(&self) -> Vec<ChannelDetails>;
-
-       /// Sends a payment over the Lightning Network using the given [`Route`].
-       fn send_payment(
-               &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
-               payment_id: PaymentId
-       ) -> Result<(), PaymentSendFailure>;
-
-       /// Sends a spontaneous payment over the Lightning Network using the given [`Route`].
-       fn send_spontaneous_payment(
-               &self, route: &Route, payment_preimage: PaymentPreimage, payment_id: PaymentId
-       ) -> Result<(), PaymentSendFailure>;
-
-       /// Retries a failed payment path for the [`PaymentId`] using the given [`Route`].
-       fn retry_payment(&self, route: &Route, payment_id: PaymentId) -> Result<(), PaymentSendFailure>;
-
-       /// Signals that no further retries for the given payment will occur.
-       fn abandon_payment(&self, payment_id: PaymentId);
-
-       /// Construct an [`InFlightHtlcs`] containing information about currently used up liquidity
-       /// across payments.
-       fn inflight_htlcs(&self) -> InFlightHtlcs;
+/// See [`pay_zero_value_invoice`] for a variant which uses the [`PaymentHash`] for the
+/// idempotency token.
+pub fn pay_zero_value_invoice_with_id<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
+       invoice: &Invoice, amount_msats: u64, payment_id: PaymentId, retry_strategy: Retry,
+       channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>
+) -> Result<(), PaymentError>
+where
+               M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
+               T::Target: BroadcasterInterface,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+               R::Target: Router,
+               L::Target: Logger,
+{
+       if invoice.amount_milli_satoshis().is_some() {
+               Err(PaymentError::Invoice("amount unexpected"))
+       } else {
+               pay_invoice_using_amount(invoice, amount_msats, payment_id, retry_strategy,
+                       channelmanager)
+       }
 }
 
-/// Strategies available to retry payment path failures for an [`Invoice`].
-///
-#[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(feature = "std")]
-       /// Time elapsed before abandoning retries for a payment.
-       Timeout(Duration),
+fn pay_invoice_using_amount<P: Deref>(
+       invoice: &Invoice, amount_msats: u64, payment_id: PaymentId, retry_strategy: Retry,
+       payer: P
+) -> Result<(), PaymentError> where P::Target: Payer {
+       let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
+       let payment_secret = Some(invoice.payment_secret().clone());
+       let mut payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key(),
+               invoice.min_final_cltv_expiry_delta() as u32)
+               .with_expiry_time(expiry_time_from_unix_epoch(&invoice).as_secs())
+               .with_route_hints(invoice.route_hints());
+       if let Some(features) = invoice.features() {
+               payment_params = payment_params.with_features(features.clone());
+       }
+       let route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amount_msats,
+               final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
+       };
+
+       payer.send_payment(payment_hash, &payment_secret, payment_id, route_params, retry_strategy)
 }
 
-impl Retry {
-       fn is_retryable_now<T: Time>(&self, attempts: &PaymentAttempts<T>) -> bool {
-               match (self, attempts) {
-                       (Retry::Attempts(max_retry_count), PaymentAttempts { count, .. }) => {
-                               max_retry_count >= &count
-                       },
-                       #[cfg(feature = "std")]
-                       (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. } ) =>
-                               *max_duration >= T::now().duration_since(*first_attempted_at),
-               }
-       }
+fn expiry_time_from_unix_epoch(invoice: &Invoice) -> Duration {
+       invoice.signed_invoice.raw_invoice.data.timestamp.0 + invoice.expiry_time()
 }
 
 /// An error that may occur when making a payment.
@@ -311,477 +171,115 @@ impl Retry {
 pub enum PaymentError {
        /// An error resulting from the provided [`Invoice`] or payment hash.
        Invoice(&'static str),
-       /// An error occurring when finding a route.
-       Routing(LightningError),
        /// An error occurring when sending a payment.
-       Sending(PaymentSendFailure),
+       Sending(RetryableSendFailure),
 }
 
-impl<P: Deref, R: Deref, L: Deref, E: sealed::BaseEventHandler, T: Time>
-       InvoicePayerUsingTime<P, R, L, E, T>
-where
-       P::Target: Payer,
-       R::Target: Router,
-       L::Target: Logger,
-{
-       /// Creates an invoice payer that retries failed payment paths.
-       ///
-       /// Will forward any [`Event::PaymentPathFailed`] events to the decorated `event_handler` once
-       /// `retry` has been exceeded for a given [`Invoice`].
-       pub fn new(
-               payer: P, router: R, logger: L, event_handler: E, retry: Retry
-       ) -> Self {
-               Self {
-                       payer,
-                       router,
-                       logger,
-                       event_handler,
-                       payment_cache: Mutex::new(HashMap::new()),
-                       retry,
-               }
-       }
-
-       /// Pays the given [`Invoice`], caching it for later use in case a retry is needed.
-       ///
-       /// [`Invoice::payment_hash`] is used as the [`PaymentId`], which ensures idempotency as long
-       /// as the payment is still pending. Once the payment completes or fails, you must ensure that
-       /// a second payment with the same [`PaymentHash`] is never sent.
-       ///
-       /// If you wish to use a different payment idempotency token, see
-       /// [`Self::pay_invoice_with_id`].
-       pub fn pay_invoice(&self, invoice: &Invoice) -> Result<PaymentId, PaymentError> {
-               let payment_id = PaymentId(invoice.payment_hash().into_inner());
-               self.pay_invoice_with_id(invoice, payment_id).map(|()| payment_id)
-       }
-
-       /// Pays the given [`Invoice`] with a custom idempotency key, caching the invoice for later use
-       /// in case a retry is needed.
-       ///
-       /// Note that idempotency is only guaranteed as long as the payment is still pending. Once the
-       /// payment completes or fails, no idempotency guarantees are made.
-       ///
-       /// You should ensure that the [`Invoice::payment_hash`] is unique and the same [`PaymentHash`]
-       /// has never been paid before.
-       ///
-       /// See [`Self::pay_invoice`] for a variant which uses the [`PaymentHash`] for the idempotency
-       /// token.
-       pub fn pay_invoice_with_id(&self, invoice: &Invoice, payment_id: PaymentId) -> Result<(), PaymentError> {
-               if invoice.amount_milli_satoshis().is_none() {
-                       Err(PaymentError::Invoice("amount missing"))
-               } else {
-                       self.pay_invoice_using_amount(invoice, None, payment_id)
-               }
-       }
-
-       /// Pays the given zero-value [`Invoice`] using the given amount, caching it for later use in
-       /// case a retry is needed.
-       ///
-       /// [`Invoice::payment_hash`] is used as the [`PaymentId`], which ensures idempotency as long
-       /// as the payment is still pending. Once the payment completes or fails, you must ensure that
-       /// a second payment with the same [`PaymentHash`] is never sent.
-       ///
-       /// If you wish to use a different payment idempotency token, see
-       /// [`Self::pay_zero_value_invoice_with_id`].
-       pub fn pay_zero_value_invoice(
-               &self, invoice: &Invoice, amount_msats: u64
-       ) -> Result<PaymentId, PaymentError> {
-               let payment_id = PaymentId(invoice.payment_hash().into_inner());
-               self.pay_zero_value_invoice_with_id(invoice, amount_msats, payment_id).map(|()| payment_id)
-       }
-
-       /// Pays the given zero-value [`Invoice`] using the given amount and custom idempotency key,
-       /// caching the invoice for later use in case a retry is needed.
-       ///
-       /// Note that idempotency is only guaranteed as long as the payment is still pending. Once the
-       /// payment completes or fails, no idempotency guarantees are made.
-       ///
-       /// You should ensure that the [`Invoice::payment_hash`] is unique and the same [`PaymentHash`]
-       /// has never been paid before.
-       ///
-       /// See [`Self::pay_zero_value_invoice`] for a variant which uses the [`PaymentHash`] for the
-       /// idempotency token.
-       pub fn pay_zero_value_invoice_with_id(
-               &self, invoice: &Invoice, amount_msats: u64, payment_id: PaymentId
-       ) -> Result<(), PaymentError> {
-               if invoice.amount_milli_satoshis().is_some() {
-                       Err(PaymentError::Invoice("amount unexpected"))
-               } else {
-                       self.pay_invoice_using_amount(invoice, Some(amount_msats), payment_id)
-               }
-       }
-
-       fn pay_invoice_using_amount(
-               &self, invoice: &Invoice, amount_msats: Option<u64>, payment_id: PaymentId
-       ) -> Result<(), PaymentError> {
-               debug_assert!(invoice.amount_milli_satoshis().is_some() ^ amount_msats.is_some());
-
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               match self.payment_cache.lock().unwrap().entry(payment_hash) {
-                       hash_map::Entry::Occupied(_) => return Err(PaymentError::Invoice("payment pending")),
-                       hash_map::Entry::Vacant(entry) => entry.insert(PaymentAttempts::new()),
-               };
-
-               let payment_secret = Some(invoice.payment_secret().clone());
-               let mut payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
-                       .with_expiry_time(expiry_time_from_unix_epoch(&invoice).as_secs())
-                       .with_route_hints(invoice.route_hints());
-               if let Some(features) = invoice.features() {
-                       payment_params = payment_params.with_features(features.clone());
-               }
-               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_delta() as u32,
-               };
-
-               let send_payment = |route: &Route| {
-                       self.payer.send_payment(route, payment_hash, &payment_secret, payment_id)
-               };
-
-               self.pay_internal(&route_params, payment_hash, send_payment)
-                       .map_err(|e| { self.payment_cache.lock().unwrap().remove(&payment_hash); e })
-       }
-
-       /// Pays `pubkey` an amount using the hash of the given preimage, caching it for later use in
-       /// case a retry is needed.
-       ///
-       /// The hash of the [`PaymentPreimage`] is used as the [`PaymentId`], which ensures idempotency
-       /// as long as the payment is still pending. Once the payment completes or fails, you must
-       /// ensure that a second payment with the same [`PaymentPreimage`] is never sent.
-       pub fn pay_pubkey(
-               &self, pubkey: PublicKey, payment_preimage: PaymentPreimage, amount_msats: u64,
-               final_cltv_expiry_delta: u32
-       ) -> Result<PaymentId, PaymentError> {
-               let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
-               let payment_id = PaymentId(payment_hash.0);
-               self.do_pay_pubkey(pubkey, payment_preimage, payment_hash, payment_id, amount_msats,
-                               final_cltv_expiry_delta)
-                       .map(|()| payment_id)
-       }
-
-       /// Pays `pubkey` an amount using the hash of the given preimage and a custom idempotency key,
-       /// caching the invoice for later use in case a retry is needed.
-       ///
-       /// Note that idempotency is only guaranteed as long as the payment is still pending. Once the
-       /// payment completes or fails, no idempotency guarantees are made.
+/// A trait defining behavior of an [`Invoice`] payer.
+///
+/// Useful for unit testing internal methods.
+trait Payer {
+       /// Sends a payment over the Lightning Network using the given [`Route`].
        ///
-       /// You should ensure that the [`PaymentPreimage`] is unique and the corresponding
-       /// [`PaymentHash`] has never been paid before.
-       pub fn pay_pubkey_with_id(
-               &self, pubkey: PublicKey, payment_preimage: PaymentPreimage, payment_id: PaymentId,
-               amount_msats: u64, final_cltv_expiry_delta: u32
-       ) -> Result<(), PaymentError> {
-               let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
-               self.do_pay_pubkey(pubkey, payment_preimage, payment_hash, payment_id, amount_msats,
-                               final_cltv_expiry_delta)
-       }
+       /// [`Route`]: lightning::routing::router::Route
+       fn send_payment(
+               &self, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
+               payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry
+       ) -> Result<(), PaymentError>;
+}
 
-       fn do_pay_pubkey(
-               &self, pubkey: PublicKey, payment_preimage: PaymentPreimage, payment_hash: PaymentHash,
-               payment_id: PaymentId, amount_msats: u64, final_cltv_expiry_delta: u32
+impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> Payer for ChannelManager<M, T, ES, NS, SP, F, R, L>
+where
+               M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
+               T::Target: BroadcasterInterface,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+               R::Target: Router,
+               L::Target: Logger,
+{
+       fn send_payment(
+               &self, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
+               payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry
        ) -> Result<(), PaymentError> {
-               match self.payment_cache.lock().unwrap().entry(payment_hash) {
-                       hash_map::Entry::Occupied(_) => return Err(PaymentError::Invoice("payment pending")),
-                       hash_map::Entry::Vacant(entry) => entry.insert(PaymentAttempts::new()),
-               };
-
-               let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(pubkey),
-                       final_value_msat: amount_msats,
-                       final_cltv_expiry_delta,
-               };
-
-               let send_payment = |route: &Route| {
-                       self.payer.send_spontaneous_payment(route, payment_preimage, payment_id)
-               };
-               self.pay_internal(&route_params, payment_hash, send_payment)
-                       .map_err(|e| { self.payment_cache.lock().unwrap().remove(&payment_hash); e })
+               self.send_payment_with_retry(payment_hash, payment_secret, payment_id, route_params, retry_strategy)
+                       .map_err(|e| PaymentError::Sending(e))
        }
+}
 
-       fn pay_internal<F: FnOnce(&Route) -> Result<(), PaymentSendFailure> + Copy>(
-               &self, params: &RouteParameters, payment_hash: PaymentHash, send_payment: F,
-       ) -> Result<(), PaymentError> {
-               #[cfg(feature = "std")] {
-                       if has_expired(params) {
-                               log_trace!(self.logger, "Invoice expired prior to send for payment {}", log_bytes!(payment_hash.0));
-                               return Err(PaymentError::Invoice("Invoice expired prior to send"));
-                       }
-               }
-
-               let payer = self.payer.node_id();
-               let first_hops = self.payer.first_hops();
-               let inflight_htlcs = self.payer.inflight_htlcs();
-               let route = self.router.find_route(
-                       &payer, &params, Some(&first_hops.iter().collect::<Vec<_>>()), &inflight_htlcs
-               ).map_err(|e| PaymentError::Routing(e))?;
+#[cfg(test)]
+mod tests {
+       use super::*;
+       use crate::{InvoiceBuilder, Currency};
+       use bitcoin_hashes::sha256::Hash as Sha256;
+       use lightning::ln::PaymentPreimage;
+       use lightning::ln::functional_test_utils::*;
+       use secp256k1::{SecretKey, Secp256k1};
+       use std::collections::VecDeque;
+       use std::time::{SystemTime, Duration};
 
-               match send_payment(&route) {
-                       Ok(()) => Ok(()),
-                       Err(e) => match e {
-                               PaymentSendFailure::ParameterError(_) => Err(e),
-                               PaymentSendFailure::PathParameterError(_) => Err(e),
-                               PaymentSendFailure::DuplicatePayment => Err(e),
-                               PaymentSendFailure::AllFailedResendSafe(_) => {
-                                       let mut payment_cache = self.payment_cache.lock().unwrap();
-                                       let payment_attempts = payment_cache.get_mut(&payment_hash).unwrap();
-                                       payment_attempts.count += 1;
-                                       if self.retry.is_retryable_now(payment_attempts) {
-                                               core::mem::drop(payment_cache);
-                                               Ok(self.pay_internal(params, payment_hash, send_payment)?)
-                                       } else {
-                                               Err(e)
-                                       }
-                               },
-                               PaymentSendFailure::PartialFailure { failed_paths_retry, payment_id, .. } => {
-                                       if let Some(retry_data) = failed_paths_retry {
-                                               // 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.retry_payment(payment_id, payment_hash, &retry_data);
-                                               Ok(())
-                                       } else {
-                                               // 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(())
-                                       }
-                               },
-                       },
-               }.map_err(|e| PaymentError::Sending(e))
+       struct TestPayer {
+               expectations: core::cell::RefCell<VecDeque<Amount>>,
        }
 
-       fn retry_payment(
-               &self, payment_id: PaymentId, payment_hash: PaymentHash, params: &RouteParameters
-       ) -> Result<(), ()> {
-               let attempts =
-                       *self.payment_cache.lock().unwrap().entry(payment_hash)
-                               .and_modify(|attempts| attempts.count += 1)
-                               .or_insert(PaymentAttempts {
-                                       count: 1,
-                                       first_attempted_at: T::now()
-                               });
-
-               if !self.retry.is_retryable_now(&attempts) {
-                       log_trace!(self.logger, "Payment {} exceeded maximum attempts; not retrying ({})", log_bytes!(payment_hash.0), attempts);
-                       return Err(());
-               }
-
-               #[cfg(feature = "std")] {
-                       if has_expired(params) {
-                               log_trace!(self.logger, "Invoice expired for payment {}; not retrying ({:})", log_bytes!(payment_hash.0), attempts);
-                               return Err(());
+       impl TestPayer {
+               fn new() -> Self {
+                       Self {
+                               expectations: core::cell::RefCell::new(VecDeque::new()),
                        }
                }
 
-               let payer = self.payer.node_id();
-               let first_hops = self.payer.first_hops();
-               let inflight_htlcs = self.payer.inflight_htlcs();
-
-               let route = self.router.find_route(
-                       &payer, &params, Some(&first_hops.iter().collect::<Vec<_>>()), &inflight_htlcs
-               );
-
-               if route.is_err() {
-                       log_trace!(self.logger, "Failed to find a route for payment {}; not retrying ({:})", log_bytes!(payment_hash.0), attempts);
-                       return Err(());
+               fn expect_send(self, value_msat: Amount) -> Self {
+                       self.expectations.borrow_mut().push_back(value_msat);
+                       self
                }
 
-               match self.payer.retry_payment(&route.as_ref().unwrap(), payment_id) {
-                       Ok(()) => Ok(()),
-                       Err(PaymentSendFailure::ParameterError(_)) |
-                       Err(PaymentSendFailure::PathParameterError(_)) => {
-                               log_trace!(self.logger, "Failed to retry for payment {} due to bogus route/payment data, not retrying.", log_bytes!(payment_hash.0));
-                               Err(())
-                       },
-                       Err(PaymentSendFailure::AllFailedResendSafe(_)) => {
-                               self.retry_payment(payment_id, payment_hash, params)
-                       },
-                       Err(PaymentSendFailure::DuplicatePayment) => {
-                               log_error!(self.logger, "Got a DuplicatePayment error when attempting to retry a payment, this shouldn't happen.");
-                               Err(())
+               fn check_value_msats(&self, actual_value_msats: Amount) {
+                       let expected_value_msats = self.expectations.borrow_mut().pop_front();
+                       if let Some(expected_value_msats) = expected_value_msats {
+                               assert_eq!(actual_value_msats, expected_value_msats);
+                       } else {
+                               panic!("Unexpected amount: {:?}", actual_value_msats);
                        }
-                       Err(PaymentSendFailure::PartialFailure { failed_paths_retry, .. }) => {
-                               if let Some(retry) = failed_paths_retry {
-                                       // Always return Ok for the same reason as noted in pay_internal.
-                                       let _ = self.retry_payment(payment_id, payment_hash, &retry);
-                               }
-                               Ok(())
-                       },
                }
        }
 
-       /// Removes the payment cached by the given payment hash.
-       ///
-       /// Should be called once a payment has failed or succeeded if not using [`InvoicePayer`] as an
-       /// [`EventHandler`]. Otherwise, calling this method is unnecessary.
-       pub fn remove_cached_payment(&self, payment_hash: &PaymentHash) {
-               self.payment_cache.lock().unwrap().remove(payment_hash);
-       }
-}
-
-fn expiry_time_from_unix_epoch(invoice: &Invoice) -> Duration {
-       invoice.signed_invoice.raw_invoice.data.timestamp.0 + invoice.expiry_time()
-}
-
-#[cfg(feature = "std")]
-fn has_expired(route_params: &RouteParameters) -> bool {
-       if let Some(expiry_time) = route_params.payment_params.expiry_time {
-               Invoice::is_expired_from_epoch(&SystemTime::UNIX_EPOCH, Duration::from_secs(expiry_time))
-       } else { false }
-}
-
-impl<P: Deref, R: Deref, L: Deref, E: sealed::BaseEventHandler, T: Time>
-       InvoicePayerUsingTime<P, R, L, E, T>
-where
-       P::Target: Payer,
-       R::Target: Router,
-       L::Target: Logger,
-{
-       /// Returns a bool indicating whether the processed event should be forwarded to a user-provided
-       /// event handler.
-       fn handle_event_internal(&self, event: &Event) -> bool {
-               match event {
-                       Event::PaymentPathFailed {
-                               payment_id, payment_hash, payment_failed_permanently, path, short_channel_id, retry, ..
-                       } => {
-                               if let Some(short_channel_id) = short_channel_id {
-                                       let path = path.iter().collect::<Vec<_>>();
-                                       self.router.notify_payment_path_failed(&path, *short_channel_id)
-                               }
+       #[derive(Clone, Debug, PartialEq, Eq)]
+       struct Amount(u64); // msat
 
-                               if payment_id.is_none() {
-                                       log_trace!(self.logger, "Payment {} has no id; not retrying", log_bytes!(payment_hash.0));
-                               } else if *payment_failed_permanently {
-                                       log_trace!(self.logger, "Payment {} rejected by destination; not retrying", log_bytes!(payment_hash.0));
-                                       self.payer.abandon_payment(payment_id.unwrap());
-                               } else if retry.is_none() {
-                                       log_trace!(self.logger, "Payment {} missing retry params; not retrying", log_bytes!(payment_hash.0));
-                                       self.payer.abandon_payment(payment_id.unwrap());
-                               } else if self.retry_payment(payment_id.unwrap(), *payment_hash, retry.as_ref().unwrap()).is_ok() {
-                                       // We retried at least somewhat, don't provide the PaymentPathFailed event to the user.
-                                       return false;
-                               } else {
-                                       self.payer.abandon_payment(payment_id.unwrap());
-                               }
-                       },
-                       Event::PaymentFailed { payment_hash, .. } => {
-                               self.remove_cached_payment(&payment_hash);
-                       },
-                       Event::PaymentPathSuccessful { path, .. } => {
-                               let path = path.iter().collect::<Vec<_>>();
-                               self.router.notify_payment_path_successful(&path);
-                       },
-                       Event::PaymentSent { payment_hash, .. } => {
-                               let mut payment_cache = self.payment_cache.lock().unwrap();
-                               let attempts = payment_cache
-                                       .remove(payment_hash)
-                                       .map_or(1, |attempts| attempts.count + 1);
-                               log_trace!(self.logger, "Payment {} succeeded (attempts: {})", log_bytes!(payment_hash.0), attempts);
-                       },
-                       Event::ProbeSuccessful { payment_hash, path, .. } => {
-                               log_trace!(self.logger, "Probe payment {} of {}msat was successful", log_bytes!(payment_hash.0), path.last().unwrap().fee_msat);
-                               let path = path.iter().collect::<Vec<_>>();
-                               self.router.notify_payment_probe_successful(&path);
-                       },
-                       Event::ProbeFailed { payment_hash, path, short_channel_id, .. } => {
-                               if let Some(short_channel_id) = short_channel_id {
-                                       log_trace!(self.logger, "Probe payment {} of {}msat failed at channel {}", log_bytes!(payment_hash.0), path.last().unwrap().fee_msat, *short_channel_id);
-                                       let path = path.iter().collect::<Vec<_>>();
-                                       self.router.notify_payment_probe_failed(&path, *short_channel_id);
-                               }
-                       },
-                       _ => {},
+       impl Payer for TestPayer {
+               fn send_payment(
+                       &self, _payment_hash: PaymentHash, _payment_secret: &Option<PaymentSecret>,
+                       _payment_id: PaymentId, route_params: RouteParameters, _retry_strategy: Retry
+               ) -> Result<(), PaymentError> {
+                       self.check_value_msats(Amount(route_params.final_value_msat));
+                       Ok(())
                }
-
-               // Delegate to the decorated event handler unless the payment is retried.
-               true
        }
-}
 
-impl<P: Deref, R: Deref, L: Deref, E: EventHandler, T: Time>
-       EventHandler for InvoicePayerUsingTime<P, R, L, E, T>
-where
-       P::Target: Payer,
-       R::Target: Router,
-       L::Target: Logger,
-{
-       fn handle_event(&self, event: Event) {
-               let should_forward = self.handle_event_internal(&event);
-               if should_forward {
-                       self.event_handler.handle_event(event)
-               }
-       }
-}
+       impl Drop for TestPayer {
+               fn drop(&mut self) {
+                       if std::thread::panicking() {
+                               return;
+                       }
 
-impl<P: Deref, R: Deref, L: Deref, T: Time, F: Future, H: Fn(Event) -> F>
-       InvoicePayerUsingTime<P, R, L, H, T>
-where
-       P::Target: Payer,
-       R::Target: Router,
-       L::Target: Logger,
-{
-       /// Intercepts events required by the [`InvoicePayer`] and forwards them to the underlying event
-       /// handler, if necessary, to handle them asynchronously.
-       pub async fn handle_event_async(&self, event: Event) {
-               let should_forward = self.handle_event_internal(&event);
-               if should_forward {
-                       (self.event_handler)(event).await;
+                       if !self.expectations.borrow().is_empty() {
+                               panic!("Unsatisfied payment expectations: {:?}", self.expectations.borrow());
+                       }
                }
        }
-}
-
-#[cfg(test)]
-mod tests {
-       use super::*;
-       use crate::{InvoiceBuilder, Currency};
-       use crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch;
-       use bitcoin_hashes::sha256::Hash as Sha256;
-       use lightning::ln::PaymentPreimage;
-       use lightning::ln::features::{ChannelFeatures, NodeFeatures};
-       use lightning::ln::functional_test_utils::*;
-       use lightning::ln::msgs::{ChannelMessageHandler, ErrorAction, LightningError};
-       use lightning::routing::gossip::{EffectiveCapacity, NodeId};
-       use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, Router, ScorerAccountingForInFlightHtlcs};
-       use lightning::routing::scoring::{ChannelUsage, LockableScore, Score};
-       use lightning::util::test_utils::TestLogger;
-       use lightning::util::errors::APIError;
-       use lightning::util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
-       use secp256k1::{SecretKey, PublicKey, Secp256k1};
-       use std::cell::RefCell;
-       use std::collections::VecDeque;
-       use std::time::{SystemTime, Duration};
-       use crate::time_utils::tests::SinceEpoch;
-       use crate::DEFAULT_EXPIRY_TIME;
-
-       fn invoice(payment_preimage: PaymentPreimage) -> Invoice {
-               let payment_hash = Sha256::hash(&payment_preimage.0);
-               let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
-
-               InvoiceBuilder::new(Currency::Bitcoin)
-                       .description("test".into())
-                       .payment_hash(payment_hash)
-                       .payment_secret(PaymentSecret([0; 32]))
-                       .duration_since_epoch(duration_since_epoch())
-                       .min_final_cltv_expiry_delta(144)
-                       .amount_milli_satoshis(128)
-                       .build_signed(|hash| {
-                               Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
-                       })
-                       .unwrap()
-       }
 
        fn duration_since_epoch() -> Duration {
                #[cfg(feature = "std")]
-                       let duration_since_epoch =
+               let duration_since_epoch =
                        SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
                #[cfg(not(feature = "std"))]
-                       let duration_since_epoch = Duration::from_secs(1234567);
+               let duration_since_epoch = Duration::from_secs(1234567);
                duration_since_epoch
        }
 
-       fn zero_value_invoice(payment_preimage: PaymentPreimage) -> Invoice {
+       fn invoice(payment_preimage: PaymentPreimage) -> Invoice {
                let payment_hash = Sha256::hash(&payment_preimage.0);
                let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
 
@@ -791,1522 +289,65 @@ mod tests {
                        .payment_secret(PaymentSecret([0; 32]))
                        .duration_since_epoch(duration_since_epoch())
                        .min_final_cltv_expiry_delta(144)
+                       .amount_milli_satoshis(128)
                        .build_signed(|hash| {
                                Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
                        })
                        .unwrap()
        }
 
-       #[cfg(feature = "std")]
-       fn expired_invoice(payment_preimage: PaymentPreimage) -> Invoice {
+       fn zero_value_invoice(payment_preimage: PaymentPreimage) -> Invoice {
                let payment_hash = Sha256::hash(&payment_preimage.0);
                let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
-               let duration = duration_since_epoch()
-                       .checked_sub(Duration::from_secs(DEFAULT_EXPIRY_TIME * 2))
-                       .unwrap();
+
                InvoiceBuilder::new(Currency::Bitcoin)
                        .description("test".into())
                        .payment_hash(payment_hash)
                        .payment_secret(PaymentSecret([0; 32]))
-                       .duration_since_epoch(duration)
+                       .duration_since_epoch(duration_since_epoch())
                        .min_final_cltv_expiry_delta(144)
-                       .amount_milli_satoshis(128)
                        .build_signed(|hash| {
                                Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
                        })
-                       .unwrap()
-       }
-
-       fn pubkey() -> PublicKey {
-               PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap()
-       }
-
-       #[test]
-       fn pays_invoice_on_first_attempt() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(0));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               invoice_payer.handle_event(Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
-               });
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 1);
-       }
-
-       #[test]
-       fn pays_invoice_on_retry() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 2);
-
-               invoice_payer.handle_event(Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
-               });
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 2);
-       }
-
-       #[test]
-       fn pays_invoice_on_partial_failure() {
-               let event_handler = |_: Event| { panic!() };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let retry = TestRouter::retry_for_invoice(&invoice);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .fails_with_partial_failure(retry.clone(), OnAttempt(1), None)
-                       .fails_with_partial_failure(retry, OnAttempt(2), None)
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               assert!(invoice_payer.pay_invoice(&invoice).is_ok());
+               .unwrap()
        }
 
        #[test]
-       fn retries_payment_path_for_unknown_payment() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::OnRetry(final_value_msat / 2))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(PaymentId([1; 32]));
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 2);
-
-               invoice_payer.handle_event(Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
-               });
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 2);
-       }
-
-       #[test]
-       fn fails_paying_invoice_after_max_retry_counts() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
+       fn pays_invoice() {
+               let payment_id = PaymentId([42; 32]);
                let payment_preimage = PaymentPreimage([1; 32]);
                let invoice = invoice(payment_preimage);
                let final_value_msat = invoice.amount_milli_satoshis().unwrap();
 
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: true,
-                       path: TestRouter::path_for_value(final_value_msat),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 2);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat / 2),
-                       short_channel_id: None,
-                       retry: Some(RouteParameters {
-                               final_value_msat: final_value_msat / 2, ..TestRouter::retry_for_invoice(&invoice)
-                       }),
-               };
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 3);
-
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 3);
+               let payer = TestPayer::new().expect_send(Amount(final_value_msat));
+               pay_invoice_using_amount(&invoice, final_value_msat, payment_id, Retry::Attempts(0), &payer).unwrap();
        }
 
-       #[cfg(feature = "std")]
        #[test]
-       fn fails_paying_invoice_after_max_retry_timeout() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
+       fn pays_zero_value_invoice() {
+               let payment_id = PaymentId([42; 32]);
                let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               type InvoicePayerUsingSinceEpoch <P, R, L, E> = InvoicePayerUsingTime::<P, R, L, E, SinceEpoch>;
-
-               let invoice_payer =
-                       InvoicePayerUsingSinceEpoch::new(&payer, &router, &logger, event_handler, Retry::Timeout(Duration::from_secs(120)));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: true,
-                       path: TestRouter::path_for_value(final_value_msat),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 2);
-
-               SinceEpoch::advance(Duration::from_secs(121));
+               let invoice = zero_value_invoice(payment_preimage);
+               let amt_msat = 10_000;
 
-               invoice_payer.handle_event(event.clone());
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 2);
+               let payer = TestPayer::new().expect_send(Amount(amt_msat));
+               pay_invoice_using_amount(&invoice, amt_msat, payment_id, Retry::Attempts(0), &payer).unwrap();
        }
 
        #[test]
-       fn fails_paying_invoice_with_missing_retry_params() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
+       fn fails_paying_zero_value_invoice_with_amount() {
+               let chanmon_cfgs = create_chanmon_cfgs(1);
+               let node_cfgs = create_node_cfgs(1, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(1, &node_cfgs, &[None]);
+               let nodes = create_network(1, &node_cfgs, &node_chanmgrs);
 
                let payment_preimage = PaymentPreimage([1; 32]);
                let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: vec![],
-                       short_channel_id: None,
-                       retry: None,
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 1);
-       }
+               let amt_msat = 10_000;
 
-       // Expiration is checked only in an std environment
-       #[cfg(feature = "std")]
-       #[test]
-       fn fails_paying_invoice_after_expiration() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payer = TestPayer::new();
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = expired_invoice(payment_preimage);
-               if let PaymentError::Invoice(msg) = invoice_payer.pay_invoice(&invoice).unwrap_err() {
-                       assert_eq!(msg, "Invoice expired prior to send");
-               } else { panic!("Expected Invoice Error"); }
-       }
-
-       // Expiration is checked only in an std environment
-       #[cfg(feature = "std")]
-       #[test]
-       fn fails_retrying_invoice_after_expiration() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router,  &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let mut retry_data = TestRouter::retry_for_invoice(&invoice);
-               retry_data.payment_params.expiry_time = Some(SystemTime::now()
-                       .checked_sub(Duration::from_secs(2)).unwrap()
-                       .duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs());
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: vec![],
-                       short_channel_id: None,
-                       retry: Some(retry_data),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 1);
-       }
-
-       #[test]
-       fn fails_paying_invoice_after_retry_error() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .fails_on_attempt(2)
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat / 2),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 2);
-       }
-
-       #[test]
-       fn fails_paying_invoice_after_rejected_by_payee() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
-                       network_update: None,
-                       payment_failed_permanently: true,
-                       all_paths_failed: false,
-                       path: vec![],
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 1);
-       }
-
-       #[test]
-       fn fails_repaying_invoice_with_pending_payment() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(0));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-
-               // Cannot repay an invoice pending payment.
-               match invoice_payer.pay_invoice(&invoice) {
-                       Err(PaymentError::Invoice("payment pending")) => {},
-                       Err(_) => panic!("unexpected error"),
-                       Ok(_) => panic!("expected invoice error"),
-               }
-
-               // Can repay an invoice once cleared from cache.
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               invoice_payer.remove_cached_payment(&payment_hash);
-               assert!(invoice_payer.pay_invoice(&invoice).is_ok());
-
-               // Cannot retry paying an invoice if cleared from cache.
-               invoice_payer.remove_cached_payment(&payment_hash);
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: vec![],
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), true);
-       }
-
-       #[test]
-       fn fails_paying_invoice_with_routing_errors() {
-               let payer = TestPayer::new();
-               let router = FailingRouter {};
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, |_: Event| {}, Retry::Attempts(0));
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               match invoice_payer.pay_invoice(&invoice) {
-                       Err(PaymentError::Routing(_)) => {},
-                       Err(_) => panic!("unexpected error"),
-                       Ok(_) => panic!("expected routing error"),
-               }
-       }
-
-       #[test]
-       fn fails_paying_invoice_with_sending_errors() {
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .fails_on_attempt(1)
-                       .expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, |_: Event| {}, Retry::Attempts(0));
-
-               match invoice_payer.pay_invoice(&invoice) {
-                       Err(PaymentError::Sending(_)) => {},
-                       Err(_) => panic!("unexpected error"),
-                       Ok(_) => panic!("expected sending error"),
-               }
-       }
-
-       #[test]
-       fn pays_zero_value_invoice_using_amount() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = zero_value_invoice(payment_preimage);
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               let final_value_msat = 100;
-
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(0));
-
-               let payment_id =
-                       Some(invoice_payer.pay_zero_value_invoice(&invoice, final_value_msat).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               invoice_payer.handle_event(Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
-               });
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 1);
-       }
-
-       #[test]
-       fn fails_paying_zero_value_invoice_with_amount() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payer = TestPayer::new();
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router,  &logger, event_handler, Retry::Attempts(0));
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-
-               // Cannot repay an invoice pending payment.
-               match invoice_payer.pay_zero_value_invoice(&invoice, 100) {
+               match pay_zero_value_invoice(&invoice, amt_msat, Retry::Attempts(0), &nodes[0].node) {
                        Err(PaymentError::Invoice("amount unexpected")) => {},
-                       Err(_) => panic!("unexpected error"),
-                       Ok(_) => panic!("expected invoice error"),
-               }
-       }
-
-       #[test]
-       fn pays_pubkey_with_amount() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let pubkey = pubkey();
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
-               let final_value_msat = 100;
-               let final_cltv_expiry_delta = 42;
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::Spontaneous(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat));
-               let router = TestRouter::new(TestScorer::new());
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_pubkey(
-                               pubkey, payment_preimage, final_value_msat, final_cltv_expiry_delta
-                       ).unwrap());
-               assert_eq!(*payer.attempts.borrow(), 1);
-
-               let retry = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(pubkey),
-                       final_value_msat,
-                       final_cltv_expiry_delta,
-               };
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: vec![],
-                       short_channel_id: None,
-                       retry: Some(retry),
-               };
-               invoice_payer.handle_event(event);
-               assert_eq!(*event_handled.borrow(), false);
-               assert_eq!(*payer.attempts.borrow(), 2);
-
-               invoice_payer.handle_event(Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
-               });
-               assert_eq!(*event_handled.borrow(), true);
-               assert_eq!(*payer.attempts.borrow(), 2);
-       }
-
-       #[test]
-       fn scores_failed_channel() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-               let path = TestRouter::path_for_value(final_value_msat);
-               let short_channel_id = Some(path[0].short_channel_id);
-
-               // Expect that scorer is given short_channel_id upon handling the event.
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2));
-               let scorer = TestScorer::new().expect(TestResult::PaymentFailure {
-                       path: path.clone(), short_channel_id: path[0].short_channel_id,
-               });
-               let router = TestRouter::new(scorer);
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
-               let event = Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path,
-                       short_channel_id,
-                       retry: Some(TestRouter::retry_for_invoice(&invoice)),
-               };
-               invoice_payer.handle_event(event);
-       }
-
-       #[test]
-       fn scores_successful_channels() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let invoice = invoice(payment_preimage);
-               let payment_hash = Some(PaymentHash(invoice.payment_hash().clone().into_inner()));
-               let final_value_msat = invoice.amount_milli_satoshis().unwrap();
-               let route = TestRouter::route_for_value(final_value_msat);
-
-               // Expect that scorer is given short_channel_id upon handling the event.
-               let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
-               let scorer = TestScorer::new()
-                       .expect(TestResult::PaymentSuccess { path: route.paths[0].clone() })
-                       .expect(TestResult::PaymentSuccess { path: route.paths[1].clone() });
-               let router = TestRouter::new(scorer);
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               let payment_id = invoice_payer.pay_invoice(&invoice).unwrap();
-               let event = Event::PaymentPathSuccessful {
-                       payment_id, payment_hash, path: route.paths[0].clone()
-               };
-               invoice_payer.handle_event(event);
-               let event = Event::PaymentPathSuccessful {
-                       payment_id, payment_hash, path: route.paths[1].clone()
-               };
-               invoice_payer.handle_event(event);
-       }
-
-       #[test]
-       fn considers_inflight_htlcs_between_invoice_payments() {
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let payment_invoice = invoice(payment_preimage);
-               let final_value_msat = payment_invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::ForInvoice(final_value_msat));
-               let scorer = TestScorer::new()
-                       // 1st invoice, 1st path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 84, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 94, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // 1st invoice, 2nd path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 74, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // 2nd invoice, 1st path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 64, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 84, inflight_htlc_msat: 84, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 94, inflight_htlc_msat: 94, effective_capacity: EffectiveCapacity::Unknown } )
-                       // 2nd invoice, 2nd path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 64, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 74, inflight_htlc_msat: 74, effective_capacity: EffectiveCapacity::Unknown } );
-               let router = TestRouter::new(scorer);
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(0));
-
-               // Make first invoice payment.
-               invoice_payer.pay_invoice(&payment_invoice).unwrap();
-
-               // Let's pay a second invoice that will be using the same path. This should trigger the
-               // assertions that expect `ChannelUsage` values of the first invoice payment that is still
-               // in-flight.
-               let payment_preimage_2 = PaymentPreimage([2; 32]);
-               let payment_invoice_2 = invoice(payment_preimage_2);
-               invoice_payer.pay_invoice(&payment_invoice_2).unwrap();
-       }
-
-       #[test]
-       fn considers_inflight_htlcs_between_retries() {
-               // First, let's just send a payment through, but only make sure one of the path completes
-               let event_handled = core::cell::RefCell::new(false);
-               let event_handler = |_: Event| { *event_handled.borrow_mut() = true; };
-
-               let payment_preimage = PaymentPreimage([1; 32]);
-               let payment_invoice = invoice(payment_preimage);
-               let payment_hash = PaymentHash(payment_invoice.payment_hash().clone().into_inner());
-               let final_value_msat = payment_invoice.amount_milli_satoshis().unwrap();
-
-               let payer = TestPayer::new()
-                       .expect_send(Amount::ForInvoice(final_value_msat))
-                       .expect_send(Amount::OnRetry(final_value_msat / 2))
-                       .expect_send(Amount::OnRetry(final_value_msat / 4));
-               let final_value_msat = payment_invoice.amount_milli_satoshis().unwrap();
-               let scorer = TestScorer::new()
-                       // 1st invoice, 1st path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 84, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 94, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // 1st invoice, 2nd path
-                       .expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 74, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // Retry 1, 1st path
-                       .expect_usage(ChannelUsage { amount_msat: 32, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 52, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 62, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // Retry 1, 2nd path
-                       .expect_usage(ChannelUsage { amount_msat: 32, inflight_htlc_msat: 64, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 42, inflight_htlc_msat: 64 + 10, effective_capacity: EffectiveCapacity::Unknown } )
-                       // Retry 2, 1st path
-                       .expect_usage(ChannelUsage { amount_msat: 16, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 36, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 46, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
-                       // Retry 2, 2nd path
-                       .expect_usage(ChannelUsage { amount_msat: 16, inflight_htlc_msat: 64 + 32, effective_capacity: EffectiveCapacity::Unknown } )
-                       .expect_usage(ChannelUsage { amount_msat: 26, inflight_htlc_msat: 74 + 32 + 10, effective_capacity: EffectiveCapacity::Unknown } );
-               let router = TestRouter::new(scorer);
-               let logger = TestLogger::new();
-               let invoice_payer =
-                       InvoicePayer::new(&payer, &router, &logger, event_handler, Retry::Attempts(2));
-
-               // Fail 1st path, leave 2nd path inflight
-               let payment_id = Some(invoice_payer.pay_invoice(&payment_invoice).unwrap());
-               invoice_payer.payer.fail_path(&TestRouter::path_for_value(final_value_msat));
-               invoice_payer.handle_event(Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat),
-                       short_channel_id: None,
-                       retry: Some(TestRouter::retry_for_invoice(&payment_invoice)),
-               });
-
-               // Fails again the 1st path of our retry
-               invoice_payer.payer.fail_path(&TestRouter::path_for_value(final_value_msat / 2));
-               invoice_payer.handle_event(Event::PaymentPathFailed {
-                       payment_id,
-                       payment_hash,
-                       network_update: None,
-                       payment_failed_permanently: false,
-                       all_paths_failed: false,
-                       path: TestRouter::path_for_value(final_value_msat / 2),
-                       short_channel_id: None,
-                       retry: Some(RouteParameters {
-                               final_value_msat: final_value_msat / 4,
-                               ..TestRouter::retry_for_invoice(&payment_invoice)
-                       }),
-               });
-       }
-
-       struct TestRouter {
-               scorer: RefCell<TestScorer>,
-       }
-
-       impl TestRouter {
-               fn new(scorer: TestScorer) -> Self {
-                       TestRouter { scorer: RefCell::new(scorer) }
-               }
-
-               fn route_for_value(final_value_msat: u64) -> Route {
-                       Route {
-                               paths: vec![
-                                       vec![
-                                               RouteHop {
-                                                       pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
-                                                       channel_features: ChannelFeatures::empty(),
-                                                       node_features: NodeFeatures::empty(),
-                                                       short_channel_id: 0,
-                                                       fee_msat: 10,
-                                                       cltv_expiry_delta: 0
-                                               },
-                                               RouteHop {
-                                                       pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
-                                                       channel_features: ChannelFeatures::empty(),
-                                                       node_features: NodeFeatures::empty(),
-                                                       short_channel_id: 1,
-                                                       fee_msat: 20,
-                                                       cltv_expiry_delta: 0
-                                               },
-                                               RouteHop {
-                                                       pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
-                                                       channel_features: ChannelFeatures::empty(),
-                                                       node_features: NodeFeatures::empty(),
-                                                       short_channel_id: 2,
-                                                       fee_msat: final_value_msat / 2,
-                                                       cltv_expiry_delta: 0
-                                               },
-                                       ],
-                                       vec![
-                                               RouteHop {
-                                                       pubkey: PublicKey::from_slice(&hex::decode("029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255").unwrap()[..]).unwrap(),
-                                                       channel_features: ChannelFeatures::empty(),
-                                                       node_features: NodeFeatures::empty(),
-                                                       short_channel_id: 3,
-                                                       fee_msat: 10,
-                                                       cltv_expiry_delta: 144
-                                               },
-                                               RouteHop {
-                                                       pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
-                                                       channel_features: ChannelFeatures::empty(),
-                                                       node_features: NodeFeatures::empty(),
-                                                       short_channel_id: 4,
-                                                       fee_msat: final_value_msat / 2,
-                                                       cltv_expiry_delta: 144
-                                               }
-                                       ],
-                               ],
-                               payment_params: None,
-                       }
-               }
-
-               fn path_for_value(final_value_msat: u64) -> Vec<RouteHop> {
-                       TestRouter::route_for_value(final_value_msat).paths[0].clone()
-               }
-
-               fn retry_for_invoice(invoice: &Invoice) -> RouteParameters {
-                       let mut payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
-                               .with_expiry_time(expiry_time_from_unix_epoch(invoice).as_secs())
-                               .with_route_hints(invoice.route_hints());
-                       if let Some(features) = invoice.features() {
-                               payment_params = payment_params.with_features(features.clone());
-                       }
-                       let final_value_msat = invoice.amount_milli_satoshis().unwrap() / 2;
-                       RouteParameters {
-                               payment_params,
-                               final_value_msat,
-                               final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta() as u32,
-                       }
-               }
-       }
-
-       impl Router for TestRouter {
-               fn find_route(
-                       &self, payer: &PublicKey, route_params: &RouteParameters,
-                       _first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs
-               ) -> Result<Route, LightningError> {
-                       // Simulate calling the Scorer just as you would in find_route
-                       let route = Self::route_for_value(route_params.final_value_msat);
-                       let locked_scorer = self.scorer.lock();
-                       let scorer = ScorerAccountingForInFlightHtlcs::new(locked_scorer, inflight_htlcs);
-                       for path in route.paths {
-                               let mut aggregate_msat = 0u64;
-                               for (idx, hop) in path.iter().rev().enumerate() {
-                                       aggregate_msat += hop.fee_msat;
-                                       let usage = ChannelUsage {
-                                               amount_msat: aggregate_msat,
-                                               inflight_htlc_msat: 0,
-                                               effective_capacity: EffectiveCapacity::Unknown,
-                                       };
-
-                                       // Since the path is reversed, the last element in our iteration is the first
-                                       // hop.
-                                       if idx == path.len() - 1 {
-                                               scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage);
-                                       } else {
-                                               scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path[idx + 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage);
-                                       }
-                               }
-                       }
-
-                       Ok(Route {
-                               payment_params: Some(route_params.payment_params.clone()), ..Self::route_for_value(route_params.final_value_msat)
-                       })
-               }
-
-               fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
-                       self.scorer.lock().payment_path_failed(path, short_channel_id);
+                       _ => panic!()
                }
-
-               fn notify_payment_path_successful(&self, path: &[&RouteHop]) {
-                       self.scorer.lock().payment_path_successful(path);
-               }
-
-               fn notify_payment_probe_successful(&self, path: &[&RouteHop]) {
-                       self.scorer.lock().probe_successful(path);
-               }
-
-               fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
-                       self.scorer.lock().probe_failed(path, short_channel_id);
-               }
-       }
-
-       struct FailingRouter;
-
-       impl Router for FailingRouter {
-               fn find_route(
-                       &self, _payer: &PublicKey, _params: &RouteParameters, _first_hops: Option<&[&ChannelDetails]>,
-                       _inflight_htlcs: &InFlightHtlcs,
-               ) -> Result<Route, LightningError> {
-                       Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError })
-               }
-
-               fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-
-               fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {}
-
-               fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {}
-
-               fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-       }
-
-       struct TestScorer {
-               event_expectations: Option<VecDeque<TestResult>>,
-               scorer_expectations: RefCell<Option<VecDeque<ChannelUsage>>>,
-       }
-
-       #[derive(Debug)]
-       enum TestResult {
-               PaymentFailure { path: Vec<RouteHop>, short_channel_id: u64 },
-               PaymentSuccess { path: Vec<RouteHop> },
-       }
-
-       impl TestScorer {
-               fn new() -> Self {
-                       Self {
-                               event_expectations: None,
-                               scorer_expectations: RefCell::new(None),
-                       }
-               }
-
-               fn expect(mut self, expectation: TestResult) -> Self {
-                       self.event_expectations.get_or_insert_with(|| VecDeque::new()).push_back(expectation);
-                       self
-               }
-
-               fn expect_usage(self, expectation: ChannelUsage) -> Self {
-                       self.scorer_expectations.borrow_mut().get_or_insert_with(|| VecDeque::new()).push_back(expectation);
-                       self
-               }
-       }
-
-       #[cfg(c_bindings)]
-       impl lightning::util::ser::Writeable for TestScorer {
-               fn write<W: lightning::util::ser::Writer>(&self, _: &mut W) -> Result<(), lightning::io::Error> { unreachable!(); }
-       }
-
-       impl Score for TestScorer {
-               fn channel_penalty_msat(
-                       &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage
-               ) -> u64 {
-                       if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
-                               match scorer_expectations.pop_front() {
-                                       Some(expectation) => {
-                                               assert_eq!(expectation.amount_msat, usage.amount_msat);
-                                               assert_eq!(expectation.inflight_htlc_msat, usage.inflight_htlc_msat);
-                                       },
-                                       None => {},
-                               }
-                       }
-                       0
-               }
-
-               fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
-                       if let Some(expectations) = &mut self.event_expectations {
-                               match expectations.pop_front() {
-                                       Some(TestResult::PaymentFailure { path, short_channel_id }) => {
-                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
-                                               assert_eq!(actual_short_channel_id, short_channel_id);
-                                       },
-                                       Some(TestResult::PaymentSuccess { path }) => {
-                                               panic!("Unexpected successful payment path: {:?}", path)
-                                       },
-                                       None => panic!("Unexpected notify_payment_path_failed call: {:?}", actual_path),
-                               }
-                       }
-               }
-
-               fn payment_path_successful(&mut self, actual_path: &[&RouteHop]) {
-                       if let Some(expectations) = &mut self.event_expectations {
-                               match expectations.pop_front() {
-                                       Some(TestResult::PaymentFailure { path, .. }) => {
-                                               panic!("Unexpected payment path failure: {:?}", path)
-                                       },
-                                       Some(TestResult::PaymentSuccess { path }) => {
-                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
-                                       },
-                                       None => panic!("Unexpected notify_payment_path_successful call: {:?}", actual_path),
-                               }
-                       }
-               }
-
-               fn probe_failed(&mut self, actual_path: &[&RouteHop], _: u64) {
-                       if let Some(expectations) = &mut self.event_expectations {
-                               match expectations.pop_front() {
-                                       Some(TestResult::PaymentFailure { path, .. }) => {
-                                               panic!("Unexpected failed payment path: {:?}", path)
-                                       },
-                                       Some(TestResult::PaymentSuccess { path }) => {
-                                               panic!("Unexpected successful payment path: {:?}", path)
-                                       },
-                                       None => panic!("Unexpected notify_payment_path_failed call: {:?}", actual_path),
-                               }
-                       }
-               }
-               fn probe_successful(&mut self, actual_path: &[&RouteHop]) {
-                       if let Some(expectations) = &mut self.event_expectations {
-                               match expectations.pop_front() {
-                                       Some(TestResult::PaymentFailure { path, .. }) => {
-                                               panic!("Unexpected payment path failure: {:?}", path)
-                                       },
-                                       Some(TestResult::PaymentSuccess { path }) => {
-                                               panic!("Unexpected successful payment path: {:?}", path)
-                                       },
-                                       None => panic!("Unexpected notify_payment_path_successful call: {:?}", actual_path),
-                               }
-                       }
-               }
-       }
-
-       impl Drop for TestScorer {
-               fn drop(&mut self) {
-                       if std::thread::panicking() {
-                               return;
-                       }
-
-                       if let Some(event_expectations) = &self.event_expectations {
-                               if !event_expectations.is_empty() {
-                                       panic!("Unsatisfied event expectations: {:?}", event_expectations);
-                               }
-                       }
-
-                       if let Some(scorer_expectations) = self.scorer_expectations.borrow().as_ref() {
-                               if !scorer_expectations.is_empty() {
-                                       panic!("Unsatisfied scorer expectations: {:?}", scorer_expectations)
-                               }
-                       }
-               }
-       }
-
-       struct TestPayer {
-               expectations: core::cell::RefCell<VecDeque<Amount>>,
-               attempts: core::cell::RefCell<usize>,
-               failing_on_attempt: core::cell::RefCell<HashMap<usize, PaymentSendFailure>>,
-               inflight_htlcs_paths: core::cell::RefCell<Vec<Vec<RouteHop>>>,
-       }
-
-       #[derive(Clone, Debug, PartialEq, Eq)]
-       enum Amount {
-               ForInvoice(u64),
-               Spontaneous(u64),
-               OnRetry(u64),
-       }
-
-       struct OnAttempt(usize);
-
-       impl TestPayer {
-               fn new() -> Self {
-                       Self {
-                               expectations: core::cell::RefCell::new(VecDeque::new()),
-                               attempts: core::cell::RefCell::new(0),
-                               failing_on_attempt: core::cell::RefCell::new(HashMap::new()),
-                               inflight_htlcs_paths: core::cell::RefCell::new(Vec::new()),
-                       }
-               }
-
-               fn expect_send(self, value_msat: Amount) -> Self {
-                       self.expectations.borrow_mut().push_back(value_msat);
-                       self
-               }
-
-               fn fails_on_attempt(self, attempt: usize) -> Self {
-                       let failure = PaymentSendFailure::ParameterError(APIError::MonitorUpdateInProgress);
-                       self.fails_with(failure, OnAttempt(attempt))
-               }
-
-               fn fails_with_partial_failure(self, retry: RouteParameters, attempt: OnAttempt, results: Option<Vec<Result<(), APIError>>>) -> Self {
-                       self.fails_with(PaymentSendFailure::PartialFailure {
-                               results: results.unwrap_or(vec![]),
-                               failed_paths_retry: Some(retry),
-                               payment_id: PaymentId([1; 32]),
-                       }, attempt)
-               }
-
-               fn fails_with(self, failure: PaymentSendFailure, attempt: OnAttempt) -> Self {
-                       self.failing_on_attempt.borrow_mut().insert(attempt.0, failure);
-                       self
-               }
-
-               fn check_attempts(&self) -> Result<(), PaymentSendFailure> {
-                       let mut attempts = self.attempts.borrow_mut();
-                       *attempts += 1;
-
-                       match self.failing_on_attempt.borrow_mut().remove(&*attempts) {
-                               Some(failure) => Err(failure),
-                               None => Ok(())
-                       }
-               }
-
-               fn check_value_msats(&self, actual_value_msats: Amount) {
-                       let expected_value_msats = self.expectations.borrow_mut().pop_front();
-                       if let Some(expected_value_msats) = expected_value_msats {
-                               assert_eq!(actual_value_msats, expected_value_msats);
-                       } else {
-                               panic!("Unexpected amount: {:?}", actual_value_msats);
-                       }
-               }
-
-               fn track_inflight_htlcs(&self, route: &Route) {
-                       for path in &route.paths {
-                               self.inflight_htlcs_paths.borrow_mut().push(path.clone());
-                       }
-               }
-
-               fn fail_path(&self, path: &Vec<RouteHop>) {
-                       let path_idx = self.inflight_htlcs_paths.borrow().iter().position(|p| p == path);
-
-                       if let Some(idx) = path_idx {
-                               self.inflight_htlcs_paths.borrow_mut().swap_remove(idx);
-                       }
-               }
-       }
-
-       impl Drop for TestPayer {
-               fn drop(&mut self) {
-                       if std::thread::panicking() {
-                               return;
-                       }
-
-                       if !self.expectations.borrow().is_empty() {
-                               panic!("Unsatisfied payment expectations: {:?}", self.expectations.borrow());
-                       }
-               }
-       }
-
-       impl Payer for TestPayer {
-               fn node_id(&self) -> PublicKey {
-                       let secp_ctx = Secp256k1::new();
-                       PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
-               }
-
-               fn first_hops(&self) -> Vec<ChannelDetails> {
-                       Vec::new()
-               }
-
-               fn send_payment(
-                       &self, route: &Route, _payment_hash: PaymentHash,
-                       _payment_secret: &Option<PaymentSecret>, _payment_id: PaymentId,
-               ) -> Result<(), PaymentSendFailure> {
-                       self.check_value_msats(Amount::ForInvoice(route.get_total_amount()));
-                       self.track_inflight_htlcs(route);
-                       self.check_attempts()
-               }
-
-               fn send_spontaneous_payment(
-                       &self, route: &Route, _payment_preimage: PaymentPreimage, _payment_id: PaymentId,
-               ) -> Result<(), PaymentSendFailure> {
-                       self.check_value_msats(Amount::Spontaneous(route.get_total_amount()));
-                       self.check_attempts()
-               }
-
-               fn retry_payment(
-                       &self, route: &Route, _payment_id: PaymentId
-               ) -> Result<(), PaymentSendFailure> {
-                       self.check_value_msats(Amount::OnRetry(route.get_total_amount()));
-                       self.track_inflight_htlcs(route);
-                       self.check_attempts()
-               }
-
-               fn abandon_payment(&self, _payment_id: PaymentId) { }
-
-               fn inflight_htlcs(&self) -> InFlightHtlcs {
-                       let mut inflight_htlcs = InFlightHtlcs::new();
-                       for path in self.inflight_htlcs_paths.clone().into_inner() {
-                               inflight_htlcs.process_path(&path, self.node_id());
-                       }
-                       inflight_htlcs
-               }
-       }
-
-       // *** Full Featured Functional Tests with a Real ChannelManager ***
-       struct ManualRouter(RefCell<VecDeque<Result<Route, LightningError>>>);
-
-       impl Router for ManualRouter {
-               fn find_route(
-                       &self, _payer: &PublicKey, _params: &RouteParameters, _first_hops: Option<&[&ChannelDetails]>,
-                       _inflight_htlcs: &InFlightHtlcs
-               ) -> Result<Route, LightningError> {
-                       self.0.borrow_mut().pop_front().unwrap()
-               }
-
-               fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-
-               fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {}
-
-               fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {}
-
-               fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-       }
-       impl ManualRouter {
-               fn expect_find_route(&self, result: Result<Route, LightningError>) {
-                       self.0.borrow_mut().push_back(result);
-               }
-       }
-       impl Drop for ManualRouter {
-               fn drop(&mut self) {
-                       if std::thread::panicking() {
-                               return;
-                       }
-                       assert!(self.0.borrow_mut().is_empty());
-               }
-       }
-
-       #[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())),
-               };
-               let router = ManualRouter(RefCell::new(VecDeque::new()));
-               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;
-               router.expect_find_route(Ok(route.clone()));
-
-               let event_handler = |_: Event| { panic!(); };
-               let invoice_payer = InvoicePayer::new(nodes[0].node, &router, nodes[0].logger, event_handler, Retry::Attempts(1));
-
-               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, None).unwrap())
-                       .is_ok());
-               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())),
-               };
-               let router = ManualRouter(RefCell::new(VecDeque::new()));
-               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;
-               router.expect_find_route(Ok(route.clone()));
-
-               let event_handler = |_: Event| { panic!(); };
-               let invoice_payer = InvoicePayer::new(nodes[0].node, &router, nodes[0].logger, event_handler, Retry::Attempts(1));
-
-               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, None).unwrap())
-                       .is_ok());
-               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[2].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())),
-               };
-               let router = ManualRouter(RefCell::new(VecDeque::new()));
-               router.expect_find_route(Ok(route.clone()));
-               // On retry, we'll only be asked for one path
-               route.paths.remove(1);
-               router.expect_find_route(Ok(route.clone()));
-
-               let expected_events: RefCell<VecDeque<&dyn Fn(Event)>> = RefCell::new(VecDeque::new());
-               let event_handler = |event: Event| {
-                       let event_checker = expected_events.borrow_mut().pop_front().unwrap();
-                       event_checker(event);
-               };
-               let invoice_payer = InvoicePayer::new(nodes[0].node, &router, nodes[0].logger, event_handler, Retry::Attempts(1));
-
-               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, None).unwrap())
-                       .is_ok());
-               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.
-               expected_events.borrow_mut().push_back(&|ev: Event| {
-                       if let Event::PaymentPathFailed { payment_failed_permanently, all_paths_failed, .. } = ev {
-                               assert!(!payment_failed_permanently);
-                               assert!(all_paths_failed);
-                       } else { panic!("Unexpected event"); }
-               });
-               nodes[0].node.process_pending_events(&invoice_payer);
-               assert!(expected_events.borrow().is_empty());
-
-               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);
-
-               expected_events.borrow_mut().push_back(&|ev: Event| {
-                       if let Event::PaymentPathFailed { payment_failed_permanently, all_paths_failed, .. } = ev {
-                               assert!(!payment_failed_permanently);
-                               assert!(all_paths_failed);
-                       } else { panic!("Unexpected event"); }
-               });
-               expected_events.borrow_mut().push_back(&|ev: Event| {
-                       if let Event::PaymentFailed { .. } = ev {
-                       } else { panic!("Unexpected event"); }
-               });
-               nodes[0].node.process_pending_events(&invoice_payer);
-               assert!(expected_events.borrow().is_empty());
        }
 }
index 763e3a4f7b0bc301b4411aeacea1795b3ced104c..868f0b297b1162da0551c8923b4ced23ab880ccb 100644 (file)
@@ -1,7 +1,6 @@
 //! Convenient utilities to create an invoice.
 
 use crate::{CreationError, Currency, Invoice, InvoiceBuilder, SignOrCreationError};
-use crate::payment::Payer;
 
 use crate::{prelude::*, Description, InvoiceDescription, Sha256};
 use bech32::ToBase32;
@@ -9,12 +8,12 @@ use bitcoin_hashes::Hash;
 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_DELTA};
+use lightning::ln::{PaymentHash, PaymentSecret};
+use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, 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;
-use lightning::routing::router::{InFlightHtlcs, Route, RouteHint, RouteHintHop, Router};
+use lightning::routing::router::{RouteHint, RouteHintHop, Router};
 use lightning::util::logger::Logger;
 use secp256k1::PublicKey;
 use core::ops::Deref;
@@ -40,10 +39,7 @@ 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.
+/// `duration_since_epoch` is the current time since epoch in seconds.
 ///
 /// 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.
@@ -60,6 +56,9 @@ use core::time::Duration;
 /// [`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
+/// 
+/// This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not
+/// available and the current time is supplied by the caller.
 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,
@@ -100,10 +99,7 @@ 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.
+/// `duration_since_epoch` is the current time since epoch in seconds.
 ///
 /// Note that the provided `keys_manager`'s `NodeSigner` implementation must support phantom
 /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -114,6 +110,9 @@ where
 /// [`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
+/// 
+/// This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not
+/// available and the current time is supplied by the caller.
 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,
@@ -634,51 +633,6 @@ fn filter_channels<L: Deref>(
                .collect::<Vec<RouteHint>>()
 }
 
-impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> Payer for ChannelManager<M, T, ES, NS, SP, F, R, L>
-where
-       M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
-       T::Target: BroadcasterInterface,
-       ES::Target: EntropySource,
-       NS::Target: NodeSigner,
-       SP::Target: SignerProvider,
-       F::Target: FeeEstimator,
-       R::Target: Router,
-       L::Target: Logger,
-{
-       fn node_id(&self) -> PublicKey {
-               self.get_our_node_id()
-       }
-
-       fn first_hops(&self) -> Vec<ChannelDetails> {
-               self.list_usable_channels()
-       }
-
-       fn send_payment(
-               &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
-               payment_id: PaymentId
-       ) -> Result<(), PaymentSendFailure> {
-               self.send_payment(route, payment_hash, payment_secret, payment_id)
-       }
-
-       fn send_spontaneous_payment(
-               &self, route: &Route, payment_preimage: PaymentPreimage, payment_id: PaymentId,
-       ) -> Result<(), PaymentSendFailure> {
-               self.send_spontaneous_payment(route, Some(payment_preimage), payment_id).map(|_| ())
-       }
-
-       fn retry_payment(
-               &self, route: &Route, payment_id: PaymentId
-       ) -> Result<(), PaymentSendFailure> {
-               self.retry_payment(route, payment_id)
-       }
-
-       fn abandon_payment(&self, payment_id: PaymentId) {
-               self.abandon_payment(payment_id)
-       }
-
-       fn inflight_htlcs(&self) -> InFlightHtlcs { self.compute_inflight_htlcs() }
-}
-
 #[cfg(test)]
 mod test {
        use core::time::Duration;
@@ -725,7 +679,8 @@ mod test {
                assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat);
                assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat);
 
-               let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
+               let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key(),
+                               invoice.min_final_cltv_expiry_delta() as u32)
                        .with_features(invoice.features().unwrap().clone())
                        .with_route_hints(invoice.route_hints());
                let route_params = RouteParameters {
@@ -736,7 +691,7 @@ mod test {
                let first_hops = nodes[0].node.list_usable_channels();
                let network_graph = &node_cfgs[0].network_graph;
                let logger = test_utils::TestLogger::new();
-               let scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, &network_graph,
@@ -887,13 +842,13 @@ mod test {
 
                // With only one sufficient-value peer connected we should only get its hint
                scid_aliases.remove(&chan_b.0.short_channel_id_alias.unwrap());
-               nodes[0].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[2].node.get_our_node_id());
                match_invoice_routes(Some(1_000_000_000), &nodes[0], scid_aliases.clone());
 
                // If we don't have any sufficient-value peers connected we should get all hints with
                // sufficient value, even though there is a connected insufficient-value peer.
                scid_aliases.insert(chan_b.0.short_channel_id_alias.unwrap());
-               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
                match_invoice_routes(Some(1_000_000_000), &nodes[0], scid_aliases);
        }
 
@@ -1088,7 +1043,8 @@ mod test {
                assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
                assert!(!invoice.features().unwrap().supports_basic_mpp());
 
-               let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
+               let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key(),
+                               invoice.min_final_cltv_expiry_delta() as u32)
                        .with_features(invoice.features().unwrap().clone())
                        .with_route_hints(invoice.route_hints());
                let params = RouteParameters {
@@ -1099,7 +1055,7 @@ mod test {
                let first_hops = nodes[0].node.list_usable_channels();
                let network_graph = &node_cfgs[0].network_graph;
                let logger = test_utils::TestLogger::new();
-               let scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &params, &network_graph,
index c4a4bedad8f14f91e3efae01d1488de7428f3ee4..81e6157c656f6e39e76525e33ca09e1b55870325 100644 (file)
 //! 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 UtxoLookup = dyn lightning::routing::utxo::UtxoLookup + Send + Sync;
 //! type ChainFilter = dyn lightning::chain::Filter + Send + Sync;
 //! type DataPersister = dyn lightning::chain::chainmonitor::Persist<lightning::chain::keysinterface::InMemorySigner> + Send + Sync;
 //! type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor<lightning::chain::keysinterface::InMemorySigner, Arc<ChainFilter>, Arc<TxBroadcaster>, Arc<FeeEstimator>, Arc<Logger>, Arc<DataPersister>>;
 //! type ChannelManager = Arc<lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor, TxBroadcaster, FeeEstimator, Logger>>;
-//! type PeerManager = Arc<lightning::ln::peer_handler::SimpleArcPeerManager<lightning_net_tokio::SocketDescriptor, ChainMonitor, TxBroadcaster, FeeEstimator, ChainAccess, Logger>>;
+//! type PeerManager = Arc<lightning::ln::peer_handler::SimpleArcPeerManager<lightning_net_tokio::SocketDescriptor, ChainMonitor, TxBroadcaster, FeeEstimator, UtxoLookup, Logger>>;
 //!
 //! // Connect to node with pubkey their_node_id at addr:
 //! async fn connect_to_node(peer_manager: PeerManager, chain_monitor: Arc<ChainMonitor>, channel_manager: ChannelManager, their_node_id: PublicKey, addr: SocketAddr) {
@@ -176,8 +176,9 @@ impl Connection {
                let (event_waker, event_receiver) = mpsc::channel(1);
                tokio::spawn(Self::poll_event_process(peer_manager.clone(), event_receiver));
 
-               // 8KB is nice and big but also should never cause any issues with stack overflowing.
-               let mut buf = [0; 8192];
+               // 4KiB is nice and big without handling too many messages all at once, giving other peers
+               // a chance to do some work.
+               let mut buf = [0; 4096];
 
                let mut our_descriptor = SocketDescriptor::new(us.clone());
                // An enum describing why we did/are disconnecting:
@@ -584,6 +585,7 @@ mod tests {
        use lightning::ln::msgs::*;
        use lightning::ln::peer_handler::{MessageHandler, PeerManager};
        use lightning::ln::features::NodeFeatures;
+       use lightning::routing::gossip::NodeId;
        use lightning::util::events::*;
        use lightning::util::test_utils::TestNodeSigner;
        use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
@@ -614,14 +616,15 @@ mod tests {
                fn handle_channel_announcement(&self, _msg: &ChannelAnnouncement) -> Result<bool, LightningError> { Ok(false) }
                fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result<bool, LightningError> { Ok(false) }
                fn get_next_channel_announcement(&self, _starting_point: u64) -> Option<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> { None }
-               fn get_next_node_announcement(&self, _starting_point: Option<&PublicKey>) -> Option<NodeAnnouncement> { None }
-               fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &Init) -> Result<(), ()> { Ok(()) }
+               fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option<NodeAnnouncement> { None }
+               fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
                fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: ReplyChannelRange) -> Result<(), LightningError> { Ok(()) }
                fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) }
                fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: QueryChannelRange) -> Result<(), LightningError> { Ok(()) }
                fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) }
                fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
                fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() }
+               fn processing_queue_high(&self) -> bool { false }
        }
        impl ChannelMessageHandler for MsgHandler {
                fn handle_open_channel(&self, _their_node_id: &PublicKey, _msg: &OpenChannel) {}
@@ -640,13 +643,13 @@ mod tests {
                fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &UpdateFee) {}
                fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, _msg: &AnnouncementSignatures) {}
                fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &ChannelUpdate) {}
-               fn peer_disconnected(&self, their_node_id: &PublicKey, _no_connection_possible: bool) {
+               fn peer_disconnected(&self, their_node_id: &PublicKey) {
                        if *their_node_id == self.expected_pubkey {
                                self.disconnected_flag.store(true, Ordering::SeqCst);
                                self.pubkey_disconnected.clone().try_send(()).unwrap();
                        }
                }
-               fn peer_connected(&self, their_node_id: &PublicKey, _init_msg: &Init) -> Result<(), ()> {
+               fn peer_connected(&self, their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool) -> Result<(), ()> {
                        if *their_node_id == self.expected_pubkey {
                                self.pubkey_connected.clone().try_send(()).unwrap();
                        }
index 06ce7eb2075574df38c2b9cbf44813235e1fba1c..ff0e481b39711cdb41166f2627d23d322838064a 100644 (file)
@@ -126,14 +126,22 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
        /// Update network graph from binary data.
        /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
        ///
-       /// `network_graph`: network graph to be updated
-       ///
        /// `update_data`: `&[u8]` binary stream that comprises the update data
        pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
                let mut read_cursor = io::Cursor::new(update_data);
                self.update_network_graph_from_byte_stream(&mut read_cursor)
        }
 
+       /// Update network graph from binary data.
+       /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
+       ///
+       /// `update_data`: `&[u8]` binary stream that comprises the update data
+       /// `current_time_unix`: `Option<u64>` optional current timestamp to verify data age
+       pub fn update_network_graph_no_std(&self, update_data: &[u8], current_time_unix: Option<u64>) -> Result<u32, GraphSyncError> {
+               let mut read_cursor = io::Cursor::new(update_data);
+               self.update_network_graph_from_byte_stream_no_std(&mut read_cursor, current_time_unix)
+       }
+
        /// Gets a reference to the underlying [`NetworkGraph`] which was provided in
        /// [`RapidGossipSync::new`].
        ///
index 3e001ec45c4be1aa7becbaa6da9f9158f3d217fa..f84f205c9b56f324838240a1be7d07162655f32d 100644 (file)
@@ -16,6 +16,9 @@ use lightning::io;
 use crate::error::GraphSyncError;
 use crate::RapidGossipSync;
 
+#[cfg(all(feature = "std", not(test)))]
+use std::time::{SystemTime, UNIX_EPOCH};
+
 #[cfg(not(feature = "std"))]
 use alloc::{vec::Vec, borrow::ToOwned};
 
@@ -29,10 +32,30 @@ const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
 /// avoid malicious updates being able to trigger excessive memory allocation.
 const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000;
 
+/// We disallow gossip data that's more than two weeks old, per BOLT 7's
+/// suggestion.
+const STALE_RGS_UPDATE_AGE_LIMIT_SECS: u64 = 60 * 60 * 24 * 14;
+
 impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
        pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
+               &self,
+               read_cursor: &mut R,
+       ) -> Result<u32, GraphSyncError> {
+               #[allow(unused_mut)]
+               let mut current_time_unix = None;
+               #[cfg(all(feature = "std", not(test)))]
+               {
+                       // Note that many tests rely on being able to set arbitrarily old timestamps, thus we
+                       // disable this check during tests!
+                       current_time_unix = Some(SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs());
+               }
+               self.update_network_graph_from_byte_stream_no_std(read_cursor, current_time_unix)
+       }
+
+       pub(crate) fn update_network_graph_from_byte_stream_no_std<R: io::Read>(
                &self,
                mut read_cursor: &mut R,
+               current_time_unix: Option<u64>
        ) -> Result<u32, GraphSyncError> {
                let mut prefix = [0u8; 4];
                read_cursor.read_exact(&mut prefix)?;
@@ -43,6 +66,13 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
 
                let chain_hash: BlockHash = Readable::read(read_cursor)?;
                let latest_seen_timestamp: u32 = Readable::read(read_cursor)?;
+
+               if let Some(time) = current_time_unix {
+                       if (latest_seen_timestamp as u64) < time.saturating_sub(STALE_RGS_UPDATE_AGE_LIMIT_SECS) {
+                               return Err(LightningError{err: "Rapid Gossip Sync data is more than two weeks old".to_owned(), action: ErrorAction::IgnoreError}.into());
+                       }
+               }
+
                // backdate the applied timestamp by a week
                let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
 
@@ -215,8 +245,28 @@ mod tests {
        use lightning::util::test_utils::TestLogger;
 
        use crate::error::GraphSyncError;
+       use crate::processing::STALE_RGS_UPDATE_AGE_LIMIT_SECS;
        use crate::RapidGossipSync;
 
+       const VALID_RGS_BINARY: [u8; 300] = [
+               76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
+               79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
+               0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
+               187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
+               157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
+               88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
+               204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
+               181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
+               110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
+               76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
+               226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232,
+               0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
+               0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, 0, 0, 0, 0, 58, 85, 116, 216, 0, 29, 0,
+               0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
+               0, 0, 1,
+       ];
+       const VALID_BINARY_TIMESTAMP: u64 = 1642291930;
+
        #[test]
        fn network_graph_fails_to_update_from_clipped_input() {
                let block_hash = genesis_block(Network::Bitcoin).block_hash();
@@ -478,24 +528,6 @@ mod tests {
 
        #[test]
        fn full_update_succeeds() {
-               let valid_input = vec![
-                       76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
-                       79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
-                       0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
-                       187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
-                       157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
-                       88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
-                       204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
-                       181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
-                       110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
-                       76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
-                       226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232,
-                       0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
-                       0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, 0, 0, 0, 0, 58, 85, 116, 216, 0, 29, 0,
-                       0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
-                       0, 0, 1,
-               ];
-
                let block_hash = genesis_block(Network::Bitcoin).block_hash();
                let logger = TestLogger::new();
                let network_graph = NetworkGraph::new(block_hash, &logger);
@@ -503,7 +535,7 @@ mod tests {
                assert_eq!(network_graph.read_only().channels().len(), 0);
 
                let rapid_sync = RapidGossipSync::new(&network_graph);
-               let update_result = rapid_sync.update_network_graph(&valid_input[..]);
+               let update_result = rapid_sync.update_network_graph(&VALID_RGS_BINARY);
                if update_result.is_err() {
                        panic!("Unexpected update result: {:?}", update_result)
                }
@@ -526,6 +558,58 @@ mod tests {
                assert!(after.contains("783241506229452801"));
        }
 
+       #[test]
+       fn full_update_succeeds_at_the_beginning_of_the_unix_era() {
+               let block_hash = genesis_block(Network::Bitcoin).block_hash();
+               let logger = TestLogger::new();
+               let network_graph = NetworkGraph::new(block_hash, &logger);
+
+               assert_eq!(network_graph.read_only().channels().len(), 0);
+
+               let rapid_sync = RapidGossipSync::new(&network_graph);
+               // this is mostly for checking uint underflow issues before the fuzzer does
+               let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(0));
+               assert!(update_result.is_ok());
+               assert_eq!(network_graph.read_only().channels().len(), 2);
+       }
+
+       #[test]
+       fn timestamp_edge_cases_are_handled_correctly() {
+               // this is the timestamp encoded in the binary data of valid_input below
+               let block_hash = genesis_block(Network::Bitcoin).block_hash();
+               let logger = TestLogger::new();
+
+               let latest_succeeding_time = VALID_BINARY_TIMESTAMP + STALE_RGS_UPDATE_AGE_LIMIT_SECS;
+               let earliest_failing_time = latest_succeeding_time + 1;
+
+               {
+                       let network_graph = NetworkGraph::new(block_hash, &logger);
+                       assert_eq!(network_graph.read_only().channels().len(), 0);
+
+                       let rapid_sync = RapidGossipSync::new(&network_graph);
+                       let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_succeeding_time));
+                       assert!(update_result.is_ok());
+                       assert_eq!(network_graph.read_only().channels().len(), 2);
+               }
+
+               {
+                       let network_graph = NetworkGraph::new(block_hash, &logger);
+                       assert_eq!(network_graph.read_only().channels().len(), 0);
+
+                       let rapid_sync = RapidGossipSync::new(&network_graph);
+                       let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(earliest_failing_time));
+                       assert!(update_result.is_err());
+                       if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
+                               assert_eq!(
+                                       lightning_error.err,
+                                       "Rapid Gossip Sync data is more than two weeks old"
+                               );
+                       } else {
+                               panic!("Unexpected update result: {:?}", update_result)
+                       }
+               }
+       }
+
        #[test]
        pub fn update_fails_with_unknown_version() {
                let unknown_version_input = vec![
diff --git a/lightning-transaction-sync/Cargo.toml b/lightning-transaction-sync/Cargo.toml
new file mode 100644 (file)
index 0000000..ae29753
--- /dev/null
@@ -0,0 +1,33 @@
+[package]
+name = "lightning-transaction-sync"
+version = "0.0.113"
+authors = ["Elias Rohrer"]
+license = "MIT OR Apache-2.0"
+repository = "http://github.com/lightningdevkit/rust-lightning"
+description = """
+Utilities for syncing LDK via the transaction-based `Confirm` interface.
+"""
+edition = "2018"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+
+[features]
+default = []
+esplora-async = ["async-interface", "esplora-client/async", "futures"]
+esplora-blocking = ["esplora-client/blocking"]
+async-interface = []
+
+[dependencies]
+lightning = { version = "0.0.113", path = "../lightning" }
+bitcoin = "0.29.0"
+bdk-macros = "0.6"
+futures = { version = "0.3", optional = true }
+esplora-client = { version = "0.3.0", default-features = false, optional = true }
+
+[dev-dependencies]
+electrsd = { version = "0.22.0", features = ["legacy", "esplora_a33e97e1", "bitcoind_23_0"] }
+electrum-client = "0.12.0"
+once_cell = "1.16.0"
+tokio = { version = "1.14.0", features = ["full"] }
diff --git a/lightning-transaction-sync/src/common.rs b/lightning-transaction-sync/src/common.rs
new file mode 100644 (file)
index 0000000..a6ee61e
--- /dev/null
@@ -0,0 +1,75 @@
+use lightning::chain::WatchedOutput;
+use bitcoin::{Txid, BlockHash, Transaction, BlockHeader, OutPoint};
+
+use std::collections::{HashSet, HashMap};
+
+
+// Represents the current state.
+pub(crate) struct SyncState {
+       // Transactions that were previously processed, but must not be forgotten
+       // yet since they still need to be monitored for confirmation on-chain.
+       pub watched_transactions: HashSet<Txid>,
+       // Outputs that were previously processed, but must not be forgotten yet as
+       // as we still need to monitor any spends on-chain.
+       pub watched_outputs: HashMap<OutPoint, WatchedOutput>,
+       // The tip hash observed during our last sync.
+       pub last_sync_hash: Option<BlockHash>,
+       // Indicates whether we need to resync, e.g., after encountering an error.
+       pub pending_sync: bool,
+}
+
+impl SyncState {
+       pub fn new() -> Self {
+               Self {
+                       watched_transactions: HashSet::new(),
+                       watched_outputs: HashMap::new(),
+                       last_sync_hash: None,
+                       pending_sync: false,
+               }
+       }
+}
+
+
+// A queue that is to be filled by `Filter` and drained during the next syncing round.
+pub(crate) struct FilterQueue {
+       // Transactions that were registered via the `Filter` interface and have to be processed.
+       pub transactions: HashSet<Txid>,
+       // Outputs that were registered via the `Filter` interface and have to be processed.
+       pub outputs: HashMap<OutPoint, WatchedOutput>,
+}
+
+impl FilterQueue {
+       pub fn new() -> Self {
+               Self {
+                       transactions: HashSet::new(),
+                       outputs: HashMap::new(),
+               }
+       }
+
+       // Processes the transaction and output queues and adds them to the given [`SyncState`].
+       //
+       // Returns `true` if new items had been registered.
+       pub fn process_queues(&mut self, sync_state: &mut SyncState) -> bool {
+               let mut pending_registrations = false;
+
+               if !self.transactions.is_empty() {
+                       pending_registrations = true;
+
+                       sync_state.watched_transactions.extend(self.transactions.drain());
+               }
+
+               if !self.outputs.is_empty() {
+                       pending_registrations = true;
+
+                       sync_state.watched_outputs.extend(self.outputs.drain());
+               }
+               pending_registrations
+       }
+}
+
+pub(crate) struct ConfirmedTx {
+       pub tx: Transaction,
+       pub block_header: BlockHeader,
+       pub block_height: u32,
+       pub pos: usize,
+}
diff --git a/lightning-transaction-sync/src/error.rs b/lightning-transaction-sync/src/error.rs
new file mode 100644 (file)
index 0000000..0a529d0
--- /dev/null
@@ -0,0 +1,63 @@
+use std::fmt;
+
+#[derive(Debug)]
+/// An error that possibly needs to be handled by the user.
+pub enum TxSyncError {
+       /// A transaction sync failed and needs to be retried eventually.
+       Failed,
+}
+
+impl std::error::Error for TxSyncError {}
+
+impl fmt::Display for TxSyncError {
+       fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+               match *self {
+                       Self::Failed => write!(f, "Failed to conduct transaction sync."),
+               }
+       }
+}
+
+#[derive(Debug)]
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+pub(crate) enum InternalError {
+       /// A transaction sync failed and needs to be retried eventually.
+       Failed,
+       /// An inconsisteny was encounterd during transaction sync.
+       Inconsistency,
+}
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+impl fmt::Display for InternalError {
+       fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+               match *self {
+                       Self::Failed => write!(f, "Failed to conduct transaction sync."),
+                       Self::Inconsistency => {
+                               write!(f, "Encountered an inconsisteny during transaction sync.")
+                       }
+               }
+       }
+}
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+impl std::error::Error for InternalError {}
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+impl From<esplora_client::Error> for TxSyncError {
+       fn from(_e: esplora_client::Error) -> Self {
+               Self::Failed
+       }
+}
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+impl From<esplora_client::Error> for InternalError {
+       fn from(_e: esplora_client::Error) -> Self {
+               Self::Failed
+       }
+}
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+impl From<InternalError> for TxSyncError {
+       fn from(_e: InternalError) -> Self {
+               Self::Failed
+       }
+}
diff --git a/lightning-transaction-sync/src/esplora.rs b/lightning-transaction-sync/src/esplora.rs
new file mode 100644 (file)
index 0000000..807ef80
--- /dev/null
@@ -0,0 +1,383 @@
+use crate::error::{TxSyncError, InternalError};
+use crate::common::{SyncState, FilterQueue, ConfirmedTx};
+
+use lightning::util::logger::Logger;
+use lightning::{log_error, log_given_level, log_info, log_internal, log_debug, log_trace};
+use lightning::chain::WatchedOutput;
+use lightning::chain::{Confirm, Filter};
+
+use bitcoin::{BlockHash, Script, Txid};
+
+use esplora_client::Builder;
+#[cfg(feature = "async-interface")]
+use esplora_client::r#async::AsyncClient;
+#[cfg(not(feature = "async-interface"))]
+use esplora_client::blocking::BlockingClient;
+
+use std::collections::HashSet;
+use core::ops::Deref;
+
+/// Synchronizes LDK with a given [`Esplora`] server.
+///
+/// Needs to be registered with a [`ChainMonitor`] via the [`Filter`] interface to be informed of
+/// transactions and outputs to monitor for on-chain confirmation, unconfirmation, and
+/// reconfirmation.
+///
+/// Note that registration via [`Filter`] needs to happen before any calls to
+/// [`Watch::watch_channel`] to ensure we get notified of the items to monitor.
+///
+/// This uses and exposes either a blocking or async client variant dependent on whether the
+/// `esplora-blocking` or the `esplora-async` feature is enabled.
+///
+/// [`Esplora`]: https://github.com/Blockstream/electrs
+/// [`ChainMonitor`]: lightning::chain::chainmonitor::ChainMonitor
+/// [`Watch::watch_channel`]: lightning::chain::Watch::watch_channel
+/// [`Filter`]: lightning::chain::Filter
+pub struct EsploraSyncClient<L: Deref>
+where
+       L::Target: Logger,
+{
+       sync_state: MutexType<SyncState>,
+       queue: std::sync::Mutex<FilterQueue>,
+       client: EsploraClientType,
+       logger: L,
+}
+
+impl<L: Deref> EsploraSyncClient<L>
+where
+       L::Target: Logger,
+{
+       /// Returns a new [`EsploraSyncClient`] object.
+       pub fn new(server_url: String, logger: L) -> Self {
+               let builder = Builder::new(&server_url);
+               #[cfg(not(feature = "async-interface"))]
+               let client = builder.build_blocking().unwrap();
+               #[cfg(feature = "async-interface")]
+               let client = builder.build_async().unwrap();
+
+               EsploraSyncClient::from_client(client, logger)
+       }
+
+       /// Returns a new [`EsploraSyncClient`] object using the given Esplora client.
+       pub fn from_client(client: EsploraClientType, logger: L) -> Self {
+               let sync_state = MutexType::new(SyncState::new());
+               let queue = std::sync::Mutex::new(FilterQueue::new());
+               Self {
+                       sync_state,
+                       queue,
+                       client,
+                       logger,
+               }
+       }
+
+       /// Synchronizes the given `confirmables` via their [`Confirm`] interface implementations. This
+       /// method should be called regularly to keep LDK up-to-date with current chain data.
+       ///
+       /// For example, instances of [`ChannelManager`] and [`ChainMonitor`] can be informed about the
+       /// newest on-chain activity related to the items previously registered via the [`Filter`]
+       /// interface.
+       ///
+       /// [`Confirm`]: lightning::chain::Confirm
+       /// [`ChainMonitor`]: lightning::chain::chainmonitor::ChainMonitor
+       /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
+       /// [`Filter`]: lightning::chain::Filter
+       #[maybe_async]
+       pub fn sync(&self, confirmables: Vec<&(dyn Confirm + Sync + Send)>) -> Result<(), TxSyncError> {
+               // This lock makes sure we're syncing once at a time.
+               #[cfg(not(feature = "async-interface"))]
+               let mut sync_state = self.sync_state.lock().unwrap();
+               #[cfg(feature = "async-interface")]
+               let mut sync_state = self.sync_state.lock().await;
+
+               log_info!(self.logger, "Starting transaction sync.");
+
+               let mut tip_hash = maybe_await!(self.client.get_tip_hash())?;
+
+               loop {
+                       let pending_registrations = self.queue.lock().unwrap().process_queues(&mut sync_state);
+                       let tip_is_new = Some(tip_hash) != sync_state.last_sync_hash;
+
+                       // We loop until any registered transactions have been processed at least once, or the
+                       // tip hasn't been updated during the last iteration.
+                       if !sync_state.pending_sync && !pending_registrations && !tip_is_new {
+                               // Nothing to do.
+                               break;
+                       } else {
+                               // Update the known tip to the newest one.
+                               if tip_is_new {
+                                       // First check for any unconfirmed transactions and act on it immediately.
+                                       match maybe_await!(self.get_unconfirmed_transactions(&confirmables)) {
+                                               Ok(unconfirmed_txs) => {
+                                                       // Double-check the tip hash. If it changed, a reorg happened since
+                                                       // we started syncing and we need to restart last-minute.
+                                                       let check_tip_hash = maybe_await!(self.client.get_tip_hash())?;
+                                                       if check_tip_hash != tip_hash {
+                                                               tip_hash = check_tip_hash;
+                                                               continue;
+                                                       }
+
+                                                       self.sync_unconfirmed_transactions(&mut sync_state, &confirmables, unconfirmed_txs);
+                                               },
+                                               Err(err) => {
+                                                       // (Semi-)permanent failure, retry later.
+                                                       log_error!(self.logger, "Failed during transaction sync, aborting.");
+                                                       sync_state.pending_sync = true;
+                                                       return Err(TxSyncError::from(err));
+                                               }
+                                       }
+
+                                       match maybe_await!(self.sync_best_block_updated(&confirmables, &tip_hash)) {
+                                               Ok(()) => {}
+                                               Err(InternalError::Inconsistency) => {
+                                                       // Immediately restart syncing when we encounter any inconsistencies.
+                                                       log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting.");
+                                                       sync_state.pending_sync = true;
+                                                       continue;
+                                               }
+                                               Err(err) => {
+                                                       // (Semi-)permanent failure, retry later.
+                                                       sync_state.pending_sync = true;
+                                                       return Err(TxSyncError::from(err));
+                                               }
+                                       }
+                               }
+
+                               match maybe_await!(self.get_confirmed_transactions(&sync_state)) {
+                                       Ok(confirmed_txs) => {
+                                               // Double-check the tip hash. If it changed, a reorg happened since
+                                               // we started syncing and we need to restart last-minute.
+                                               let check_tip_hash = maybe_await!(self.client.get_tip_hash())?;
+                                               if check_tip_hash != tip_hash {
+                                                       tip_hash = check_tip_hash;
+                                                       continue;
+                                               }
+
+                                               self.sync_confirmed_transactions(
+                                                       &mut sync_state,
+                                                       &confirmables,
+                                                       confirmed_txs,
+                                               );
+                                       }
+                                       Err(InternalError::Inconsistency) => {
+                                               // Immediately restart syncing when we encounter any inconsistencies.
+                                               log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting.");
+                                               sync_state.pending_sync = true;
+                                               continue;
+                                       }
+                                       Err(err) => {
+                                               // (Semi-)permanent failure, retry later.
+                                               log_error!(self.logger, "Failed during transaction sync, aborting.");
+                                               sync_state.pending_sync = true;
+                                               return Err(TxSyncError::from(err));
+                                       }
+                               }
+                               sync_state.last_sync_hash = Some(tip_hash);
+                               sync_state.pending_sync = false;
+                       }
+               }
+               log_info!(self.logger, "Finished transaction sync.");
+               Ok(())
+       }
+
+       #[maybe_async]
+       fn sync_best_block_updated(
+               &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, tip_hash: &BlockHash,
+       ) -> Result<(), InternalError> {
+
+               // Inform the interface of the new block.
+               let tip_header = maybe_await!(self.client.get_header_by_hash(tip_hash))?;
+               let tip_status = maybe_await!(self.client.get_block_status(&tip_hash))?;
+               if tip_status.in_best_chain {
+                       if let Some(tip_height) = tip_status.height {
+                               for c in confirmables {
+                                       c.best_block_updated(&tip_header, tip_height);
+                               }
+                       }
+               } else {
+                       return Err(InternalError::Inconsistency);
+               }
+               Ok(())
+       }
+
+       fn sync_confirmed_transactions(
+               &self, sync_state: &mut SyncState, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, confirmed_txs: Vec<ConfirmedTx>,
+       ) {
+               for ctx in confirmed_txs {
+                       for c in confirmables {
+                               c.transactions_confirmed(
+                                       &ctx.block_header,
+                                       &[(ctx.pos, &ctx.tx)],
+                                       ctx.block_height,
+                               );
+                       }
+
+                       sync_state.watched_transactions.remove(&ctx.tx.txid());
+
+                       for input in &ctx.tx.input {
+                               sync_state.watched_outputs.remove(&input.previous_output);
+                       }
+               }
+       }
+
+       #[maybe_async]
+       fn get_confirmed_transactions(
+               &self, sync_state: &SyncState,
+       ) -> Result<Vec<ConfirmedTx>, InternalError> {
+
+               // First, check the confirmation status of registered transactions as well as the
+               // status of dependent transactions of registered outputs.
+
+               let mut confirmed_txs = Vec::new();
+
+               for txid in &sync_state.watched_transactions {
+                       if let Some(confirmed_tx) = maybe_await!(self.get_confirmed_tx(&txid, None, None))? {
+                               confirmed_txs.push(confirmed_tx);
+                       }
+               }
+
+               for (_, output) in &sync_state.watched_outputs {
+                       if let Some(output_status) = maybe_await!(self.client
+                               .get_output_status(&output.outpoint.txid, output.outpoint.index as u64))?
+                       {
+                               if let Some(spending_txid) = output_status.txid {
+                                       if let Some(spending_tx_status) = output_status.status {
+                                               if let Some(confirmed_tx) = maybe_await!(self
+                                                       .get_confirmed_tx(
+                                                               &spending_txid,
+                                                               spending_tx_status.block_hash,
+                                                               spending_tx_status.block_height,
+                                                       ))?
+                                               {
+                                                       confirmed_txs.push(confirmed_tx);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               // Sort all confirmed transactions first by block height, then by in-block
+               // position, and finally feed them to the interface in order.
+               confirmed_txs.sort_unstable_by(|tx1, tx2| {
+                       tx1.block_height.cmp(&tx2.block_height).then_with(|| tx1.pos.cmp(&tx2.pos))
+               });
+
+               Ok(confirmed_txs)
+       }
+
+       #[maybe_async]
+       fn get_confirmed_tx(
+               &self, txid: &Txid, expected_block_hash: Option<BlockHash>, known_block_height: Option<u32>,
+       ) -> Result<Option<ConfirmedTx>, InternalError> {
+               if let Some(merkle_block) = maybe_await!(self.client.get_merkle_block(&txid))? {
+                       let block_header = merkle_block.header;
+                       let block_hash = block_header.block_hash();
+                       if let Some(expected_block_hash) = expected_block_hash {
+                               if expected_block_hash != block_hash {
+                                       log_trace!(self.logger, "Inconsistency: Tx {} expected in block {}, but is confirmed in {}", txid, expected_block_hash, block_hash);
+                                       return Err(InternalError::Inconsistency);
+                               }
+                       }
+
+                       let mut matches = Vec::new();
+                       let mut indexes = Vec::new();
+                       let _ = merkle_block.txn.extract_matches(&mut matches, &mut indexes);
+                       if indexes.len() != 1 || matches.len() != 1 || matches[0] != *txid {
+                               log_error!(self.logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity.", txid);
+                               return Err(InternalError::Failed);
+                       }
+
+                       let pos = *indexes.get(0).ok_or(InternalError::Failed)? as usize;
+                       if let Some(tx) = maybe_await!(self.client.get_tx(&txid))? {
+                               if let Some(block_height) = known_block_height {
+                                       // We can take a shortcut here if a previous call already gave us the height.
+                                       return Ok(Some(ConfirmedTx { tx, block_header, pos, block_height }));
+                               }
+
+                               let block_status = maybe_await!(self.client.get_block_status(&block_hash))?;
+                               if let Some(block_height) = block_status.height {
+                                       return Ok(Some(ConfirmedTx { tx, block_header, pos, block_height }));
+                               } else {
+                                       // If any previously-confirmed block suddenly is no longer confirmed, we found
+                                       // an inconsistency and should start over.
+                                       log_trace!(self.logger, "Inconsistency: Tx {} was unconfirmed during syncing.", txid);
+                                       return Err(InternalError::Inconsistency);
+                               }
+                       }
+               }
+               Ok(None)
+       }
+
+       #[maybe_async]
+       fn get_unconfirmed_transactions(
+               &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
+       ) -> Result<Vec<Txid>, InternalError> {
+               // Query the interface for relevant txids and check whether the relevant blocks are still
+               // in the best chain, mark them unconfirmed otherwise
+               let relevant_txids = confirmables
+                       .iter()
+                       .flat_map(|c| c.get_relevant_txids())
+                       .collect::<HashSet<(Txid, Option<BlockHash>)>>();
+
+               let mut unconfirmed_txs = Vec::new();
+
+               for (txid, block_hash_opt) in relevant_txids {
+                       if let Some(block_hash) = block_hash_opt {
+                               let block_status = maybe_await!(self.client.get_block_status(&block_hash))?;
+                               if block_status.in_best_chain {
+                                       // Skip if the block in question is still confirmed.
+                                       continue;
+                               }
+
+                               unconfirmed_txs.push(txid);
+                       } else {
+                               log_error!(self.logger, "Untracked confirmation of funding transaction. Please ensure none of your channels had been created with LDK prior to version 0.0.113!");
+                               panic!("Untracked confirmation of funding transaction. Please ensure none of your channels had been created with LDK prior to version 0.0.113!");
+                       }
+               }
+               Ok(unconfirmed_txs)
+       }
+
+       fn sync_unconfirmed_transactions(
+               &self, sync_state: &mut SyncState, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, unconfirmed_txs: Vec<Txid>,
+       ) {
+               for txid in unconfirmed_txs {
+                       for c in confirmables {
+                               c.transaction_unconfirmed(&txid);
+                       }
+
+                       sync_state.watched_transactions.insert(txid);
+               }
+       }
+
+       /// Returns a reference to the underlying esplora client.
+       pub fn client(&self) -> &EsploraClientType {
+               &self.client
+       }
+}
+
+#[cfg(feature = "async-interface")]
+type MutexType<I> = futures::lock::Mutex<I>;
+#[cfg(not(feature = "async-interface"))]
+type MutexType<I> = std::sync::Mutex<I>;
+
+// The underlying client type.
+#[cfg(feature = "async-interface")]
+type EsploraClientType = AsyncClient;
+#[cfg(not(feature = "async-interface"))]
+type EsploraClientType = BlockingClient;
+
+
+impl<L: Deref> Filter for EsploraSyncClient<L>
+where
+       L::Target: Logger,
+{
+       fn register_tx(&self, txid: &Txid, _script_pubkey: &Script) {
+               let mut locked_queue = self.queue.lock().unwrap();
+               locked_queue.transactions.insert(*txid);
+       }
+
+       fn register_output(&self, output: WatchedOutput) {
+               let mut locked_queue = self.queue.lock().unwrap();
+               locked_queue.outputs.insert(output.outpoint.into_bitcoin_outpoint(), output);
+       }
+}
diff --git a/lightning-transaction-sync/src/lib.rs b/lightning-transaction-sync/src/lib.rs
new file mode 100644 (file)
index 0000000..791490d
--- /dev/null
@@ -0,0 +1,82 @@
+//! Provides utilities for syncing LDK via the transaction-based [`Confirm`] interface.
+//!
+//! The provided synchronization clients need to be registered with a [`ChainMonitor`] via the
+//! [`Filter`] interface. Then, the respective `fn sync` needs to be called with the [`Confirm`]
+//! implementations to be synchronized, i.e., usually instances of [`ChannelManager`] and
+//! [`ChainMonitor`].
+//!
+//! ## Features and Backend Support
+//!
+//!- `esplora_blocking` enables syncing against an Esplora backend based on a blocking client.
+//!- `esplora_async` enables syncing against an Esplora backend based on an async client.
+//!
+//! ## Version Compatibility
+//!
+//! Currently this crate is compatible with nodes that were created with LDK version 0.0.113 and above.
+//!
+//! ## Usage Example:
+//!
+//! ```ignore
+//! let tx_sync = Arc::new(EsploraSyncClient::new(
+//!    esplora_server_url,
+//!    Arc::clone(&some_logger),
+//! ));
+//!
+//! let chain_monitor = Arc::new(ChainMonitor::new(
+//!    Some(Arc::clone(&tx_sync)),
+//!    Arc::clone(&some_broadcaster),
+//!    Arc::clone(&some_logger),
+//!    Arc::clone(&some_fee_estimator),
+//!    Arc::clone(&some_persister),
+//! ));
+//!
+//! let channel_manager = Arc::new(ChannelManager::new(
+//!    Arc::clone(&some_fee_estimator),
+//!    Arc::clone(&chain_monitor),
+//!    Arc::clone(&some_broadcaster),
+//!    Arc::clone(&some_router),
+//!    Arc::clone(&some_logger),
+//!    Arc::clone(&some_entropy_source),
+//!    Arc::clone(&some_node_signer),
+//!    Arc::clone(&some_signer_provider),
+//!    user_config,
+//!    chain_params,
+//! ));
+//!
+//! let confirmables = vec![
+//!    &*channel_manager as &(dyn Confirm + Sync + Send),
+//!    &*chain_monitor as &(dyn Confirm + Sync + Send),
+//! ];
+//!
+//! tx_sync.sync(confirmables).unwrap();
+//! ```
+//!
+//! [`Confirm`]: lightning::chain::Confirm
+//! [`Filter`]: lightning::chain::Filter
+//! [`ChainMonitor`]: lightning::chain::chainmonitor::ChainMonitor
+//! [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
+
+// Prefix these with `rustdoc::` when we update our MSRV to be >= 1.52 to remove warnings.
+#![deny(broken_intra_doc_links)]
+#![deny(private_intra_doc_links)]
+
+#![deny(missing_docs)]
+#![deny(unsafe_code)]
+
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+#[macro_use]
+extern crate bdk_macros;
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+mod esplora;
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+mod common;
+
+mod error;
+pub use error::TxSyncError;
+
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+pub use esplora::EsploraSyncClient;
diff --git a/lightning-transaction-sync/tests/integration_tests.rs b/lightning-transaction-sync/tests/integration_tests.rs
new file mode 100644 (file)
index 0000000..5c5ee03
--- /dev/null
@@ -0,0 +1,335 @@
+#![cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+use lightning_transaction_sync::EsploraSyncClient;
+use lightning::chain::{Confirm, Filter};
+use lightning::chain::transaction::TransactionData;
+use lightning::util::logger::{Logger, Record};
+
+use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
+use bitcoin::{Amount, Txid, BlockHash, BlockHeader};
+use bitcoin::blockdata::constants::genesis_block;
+use bitcoin::network::constants::Network;
+use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
+use bitcoind::bitcoincore_rpc::RpcApi;
+use electrum_client::ElectrumApi;
+
+use once_cell::sync::OnceCell;
+
+use std::env;
+use std::sync::Mutex;
+use std::time::Duration;
+use std::collections::{HashMap, HashSet};
+
+static BITCOIND: OnceCell<BitcoinD> = OnceCell::new();
+static ELECTRSD: OnceCell<ElectrsD> = OnceCell::new();
+static PREMINE: OnceCell<()> = OnceCell::new();
+static MINER_LOCK: OnceCell<Mutex<()>> = OnceCell::new();
+
+fn get_bitcoind() -> &'static BitcoinD {
+       BITCOIND.get_or_init(|| {
+               let bitcoind_exe =
+                       env::var("BITCOIND_EXE").ok().or_else(|| bitcoind::downloaded_exe_path().ok()).expect(
+                               "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature",
+                               );
+               let mut conf = bitcoind::Conf::default();
+               conf.network = "regtest";
+               BitcoinD::with_conf(bitcoind_exe, &conf).unwrap()
+       })
+}
+
+fn get_electrsd() -> &'static ElectrsD {
+       ELECTRSD.get_or_init(|| {
+               let bitcoind = get_bitcoind();
+               let electrs_exe =
+                       env::var("ELECTRS_EXE").ok().or_else(electrsd::downloaded_exe_path).expect(
+                               "you need to provide env var ELECTRS_EXE or specify an electrsd version feature",
+                       );
+               let mut conf = electrsd::Conf::default();
+               conf.http_enabled = true;
+               conf.network = "regtest";
+               ElectrsD::with_conf(electrs_exe, &bitcoind, &conf).unwrap()
+       })
+}
+
+fn generate_blocks_and_wait(num: usize) {
+       let miner_lock = MINER_LOCK.get_or_init(|| Mutex::new(()));
+       let _miner = miner_lock.lock().unwrap();
+       let cur_height = get_bitcoind().client.get_block_count().unwrap();
+       let address = get_bitcoind().client.get_new_address(Some("test"), Some(AddressType::Legacy)).unwrap();
+       let _block_hashes = get_bitcoind().client.generate_to_address(num as u64, &address).unwrap();
+       wait_for_block(cur_height as usize + num);
+}
+
+fn wait_for_block(min_height: usize) {
+       let mut header = get_electrsd().client.block_headers_subscribe().unwrap();
+       loop {
+               if header.height >= min_height {
+                       break;
+               }
+               header = exponential_backoff_poll(|| {
+                       get_electrsd().trigger().unwrap();
+                       get_electrsd().client.ping().unwrap();
+                       get_electrsd().client.block_headers_pop().unwrap()
+               });
+       }
+}
+
+fn exponential_backoff_poll<T, F>(mut poll: F) -> T
+where
+       F: FnMut() -> Option<T>,
+{
+       let mut delay = Duration::from_millis(64);
+       let mut tries = 0;
+       loop {
+               match poll() {
+                       Some(data) => break data,
+                       None if delay.as_millis() < 512 => {
+                               delay = delay.mul_f32(2.0);
+                               tries += 1;
+                       }
+                       None if tries == 10 => panic!("Exceeded our maximum wait time."),
+                       None => tries += 1,
+               }
+
+               std::thread::sleep(delay);
+       }
+}
+
+fn premine() {
+       PREMINE.get_or_init(|| {
+               generate_blocks_and_wait(101);
+       });
+}
+
+#[derive(Debug)]
+enum TestConfirmableEvent {
+       Confirmed(Txid, BlockHash, u32),
+       Unconfirmed(Txid),
+       BestBlockUpdated(BlockHash, u32),
+}
+
+struct TestConfirmable {
+       pub confirmed_txs: Mutex<HashMap<Txid, (BlockHash, u32)>>,
+       pub unconfirmed_txs: Mutex<HashSet<Txid>>,
+       pub best_block: Mutex<(BlockHash, u32)>,
+       pub events: Mutex<Vec<TestConfirmableEvent>>,
+}
+
+impl TestConfirmable {
+       pub fn new() -> Self {
+               let genesis_hash = genesis_block(Network::Regtest).block_hash();
+               Self {
+                       confirmed_txs: Mutex::new(HashMap::new()),
+                       unconfirmed_txs: Mutex::new(HashSet::new()),
+                       best_block: Mutex::new((genesis_hash, 0)),
+                       events: Mutex::new(Vec::new()),
+               }
+       }
+}
+
+impl Confirm for TestConfirmable {
+       fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData<'_>, height: u32) {
+               for (_, tx) in txdata {
+                       let txid = tx.txid();
+                       let block_hash = header.block_hash();
+                       self.confirmed_txs.lock().unwrap().insert(txid, (block_hash, height));
+                       self.unconfirmed_txs.lock().unwrap().remove(&txid);
+                       self.events.lock().unwrap().push(TestConfirmableEvent::Confirmed(txid, block_hash, height));
+               }
+       }
+
+       fn transaction_unconfirmed(&self, txid: &Txid) {
+               self.unconfirmed_txs.lock().unwrap().insert(*txid);
+               self.confirmed_txs.lock().unwrap().remove(txid);
+               self.events.lock().unwrap().push(TestConfirmableEvent::Unconfirmed(*txid));
+       }
+
+       fn best_block_updated(&self, header: &BlockHeader, height: u32) {
+               let block_hash = header.block_hash();
+               *self.best_block.lock().unwrap() = (block_hash, height);
+               self.events.lock().unwrap().push(TestConfirmableEvent::BestBlockUpdated(block_hash, height));
+       }
+
+       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
+               self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, _))| (txid, Some(*hash))).collect::<Vec<_>>()
+       }
+}
+
+pub struct TestLogger {}
+
+impl Logger for TestLogger {
+       fn log(&self, record: &Record) {
+               println!("{} -- {}",
+                               record.level,
+                               record.args);
+       }
+}
+
+#[test]
+#[cfg(feature = "esplora-blocking")]
+fn test_esplora_syncs() {
+       premine();
+       let mut logger = TestLogger {};
+       let esplora_url = format!("http://{}", get_electrsd().esplora_url.as_ref().unwrap());
+       let tx_sync = EsploraSyncClient::new(esplora_url, &mut logger);
+       let confirmable = TestConfirmable::new();
+
+       // Check we pick up on new best blocks
+       let expected_height = 0u32;
+       assert_eq!(confirmable.best_block.lock().unwrap().1, expected_height);
+
+       tx_sync.sync(vec![&confirmable]).unwrap();
+
+       let expected_height = get_bitcoind().client.get_block_count().unwrap() as u32;
+       assert_eq!(confirmable.best_block.lock().unwrap().1, expected_height);
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 1);
+
+       // Check registered confirmed transactions are marked confirmed
+       let new_address = get_bitcoind().client.get_new_address(Some("test"), Some(AddressType::Legacy)).unwrap();
+       let txid = get_bitcoind().client.send_to_address(&new_address, Amount::from_sat(5000), None, None, None, None, None, None).unwrap();
+       tx_sync.register_tx(&txid, &new_address.script_pubkey());
+
+       tx_sync.sync(vec![&confirmable]).unwrap();
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 0);
+       assert!(confirmable.confirmed_txs.lock().unwrap().is_empty());
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       generate_blocks_and_wait(1);
+       tx_sync.sync(vec![&confirmable]).unwrap();
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 2);
+       assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       // Check previously confirmed transactions are marked unconfirmed when they are reorged.
+       let best_block_hash = get_bitcoind().client.get_best_block_hash().unwrap();
+       get_bitcoind().client.invalidate_block(&best_block_hash).unwrap();
+
+       // We're getting back to the previous height with a new tip, but best block shouldn't change.
+       generate_blocks_and_wait(1);
+       assert_ne!(get_bitcoind().client.get_best_block_hash().unwrap(), best_block_hash);
+       tx_sync.sync(vec![&confirmable]).unwrap();
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 0);
+
+       // Now we're surpassing previous height, getting new tip.
+       generate_blocks_and_wait(1);
+       assert_ne!(get_bitcoind().client.get_best_block_hash().unwrap(), best_block_hash);
+       tx_sync.sync(vec![&confirmable]).unwrap();
+
+       // Transaction still confirmed but under new tip.
+       assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       // Check we got unconfirmed, then reconfirmed in the meantime.
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 3);
+
+       match events[0] {
+               TestConfirmableEvent::Unconfirmed(t) => {
+                       assert_eq!(t, txid);
+               },
+               _ => panic!("Unexpected event"),
+       }
+
+       match events[1] {
+               TestConfirmableEvent::BestBlockUpdated(..) => {},
+               _ => panic!("Unexpected event"),
+       }
+
+       match events[2] {
+               TestConfirmableEvent::Confirmed(t, _, _) => {
+                       assert_eq!(t, txid);
+               },
+               _ => panic!("Unexpected event"),
+       }
+}
+
+#[tokio::test]
+#[cfg(feature = "esplora-async")]
+async fn test_esplora_syncs() {
+       premine();
+       let mut logger = TestLogger {};
+       let esplora_url = format!("http://{}", get_electrsd().esplora_url.as_ref().unwrap());
+       let tx_sync = EsploraSyncClient::new(esplora_url, &mut logger);
+       let confirmable = TestConfirmable::new();
+
+       // Check we pick up on new best blocks
+       let expected_height = 0u32;
+       assert_eq!(confirmable.best_block.lock().unwrap().1, expected_height);
+
+       tx_sync.sync(vec![&confirmable]).await.unwrap();
+
+       let expected_height = get_bitcoind().client.get_block_count().unwrap() as u32;
+       assert_eq!(confirmable.best_block.lock().unwrap().1, expected_height);
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 1);
+
+       // Check registered confirmed transactions are marked confirmed
+       let new_address = get_bitcoind().client.get_new_address(Some("test"), Some(AddressType::Legacy)).unwrap();
+       let txid = get_bitcoind().client.send_to_address(&new_address, Amount::from_sat(5000), None, None, None, None, None, None).unwrap();
+       tx_sync.register_tx(&txid, &new_address.script_pubkey());
+
+       tx_sync.sync(vec![&confirmable]).await.unwrap();
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 0);
+       assert!(confirmable.confirmed_txs.lock().unwrap().is_empty());
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       generate_blocks_and_wait(1);
+       tx_sync.sync(vec![&confirmable]).await.unwrap();
+
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 2);
+       assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       // Check previously confirmed transactions are marked unconfirmed when they are reorged.
+       let best_block_hash = get_bitcoind().client.get_best_block_hash().unwrap();
+       get_bitcoind().client.invalidate_block(&best_block_hash).unwrap();
+
+       // We're getting back to the previous height with a new tip, but best block shouldn't change.
+       generate_blocks_and_wait(1);
+       assert_ne!(get_bitcoind().client.get_best_block_hash().unwrap(), best_block_hash);
+       tx_sync.sync(vec![&confirmable]).await.unwrap();
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 0);
+
+       // Now we're surpassing previous height, getting new tip.
+       generate_blocks_and_wait(1);
+       assert_ne!(get_bitcoind().client.get_best_block_hash().unwrap(), best_block_hash);
+       tx_sync.sync(vec![&confirmable]).await.unwrap();
+
+       // Transaction still confirmed but under new tip.
+       assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
+       assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
+
+       // Check we got unconfirmed, then reconfirmed in the meantime.
+       let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
+       assert_eq!(events.len(), 3);
+
+       match events[0] {
+               TestConfirmableEvent::Unconfirmed(t) => {
+                       assert_eq!(t, txid);
+               },
+               _ => panic!("Unexpected event"),
+       }
+
+       match events[1] {
+               TestConfirmableEvent::BestBlockUpdated(..) => {},
+               _ => panic!("Unexpected event"),
+       }
+
+       match events[2] {
+               TestConfirmableEvent::Confirmed(t, _, _) => {
+                       assert_eq!(t, txid);
+               },
+               _ => panic!("Unexpected event"),
+       }
+}
index 3a2077209c4ea36ebf3b412a048f845e1b344c1f..9a74f891b1e985b371f2640ccf23f7c992e626ec 100644 (file)
@@ -796,7 +796,7 @@ mod tests {
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs::ChannelMessageHandler;
        use crate::util::errors::APIError;
-       use crate::util::events::{ClosureReason, MessageSendEvent, MessageSendEventsProvider};
+       use crate::util::events::{Event, ClosureReason, MessageSendEvent, MessageSendEventsProvider};
 
        #[test]
        fn test_async_ooo_offchain_updates() {
@@ -819,10 +819,8 @@ mod tests {
 
                nodes[1].node.claim_funds(payment_preimage_1);
                check_added_monitors!(nodes[1], 1);
-               expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
                nodes[1].node.claim_funds(payment_preimage_2);
                check_added_monitors!(nodes[1], 1);
-               expect_payment_claimed!(nodes[1], payment_hash_2, 1_000_000);
 
                let persistences = chanmon_cfgs[1].persister.offchain_monitor_updates.lock().unwrap().clone();
                assert_eq!(persistences.len(), 1);
@@ -850,8 +848,24 @@ mod tests {
                        .find(|(txo, _)| txo == funding_txo).unwrap().1.contains(&next_update));
                assert!(nodes[1].chain_monitor.release_pending_monitor_events().is_empty());
                assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+               assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
                nodes[1].chain_monitor.chain_monitor.channel_monitor_updated(*funding_txo, update_iter.next().unwrap().clone()).unwrap();
 
+               let claim_events = nodes[1].node.get_and_clear_pending_events();
+               assert_eq!(claim_events.len(), 2);
+               match claim_events[0] {
+                       Event::PaymentClaimed { ref payment_hash, amount_msat: 1_000_000, .. } => {
+                               assert_eq!(payment_hash_1, *payment_hash);
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+               match claim_events[1] {
+                       Event::PaymentClaimed { ref payment_hash, amount_msat: 1_000_000, .. } => {
+                               assert_eq!(payment_hash_2, *payment_hash);
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+
                // Now manually walk the commitment signed dance - because we claimed two payments
                // back-to-back it doesn't fit into the neat walk commitment_signed_dance does.
 
index 01eae488700605b2f23c50d5fdfdc0c2319859bc..cd11bc337eff97593c8f3b0640f54dcd6d2bf09f 100644 (file)
@@ -12,7 +12,6 @@
 use bitcoin::blockdata::block::{Block, BlockHeader};
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::script::Script;
-use bitcoin::blockdata::transaction::TxOut;
 use bitcoin::hash_types::{BlockHash, Txid};
 use bitcoin::network::constants::Network;
 use bitcoin::secp256k1::PublicKey;
@@ -60,26 +59,6 @@ impl BestBlock {
        pub fn height(&self) -> u32 { self.height }
 }
 
-/// An error when accessing the chain via [`Access`].
-#[derive(Clone, Debug)]
-pub enum AccessError {
-       /// The requested chain is unknown.
-       UnknownChain,
-
-       /// The requested transaction doesn't exist or hasn't confirmed.
-       UnknownTx,
-}
-
-/// The `Access` trait defines behavior for accessing chain data and state, such as blocks and
-/// UTXOs.
-pub trait Access {
-       /// Returns the transaction output of a funding transaction encoded by [`short_channel_id`].
-       /// Returns an error if `genesis_hash` is for a different chain or if such a transaction output
-       /// is unknown.
-       ///
-       /// [`short_channel_id`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#definition-of-short_channel_id
-       fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> Result<TxOut, AccessError>;
-}
 
 /// The `Listen` trait is used to notify when blocks have been connected or disconnected from the
 /// chain.
@@ -176,6 +155,9 @@ pub trait Confirm {
        /// Returns transactions that must be monitored for reorganization out of the chain along
        /// with the hash of the block as part of which it had been previously confirmed.
        ///
+       /// Note that the returned `Option<BlockHash>` might be `None` for channels created with LDK
+       /// 0.0.112 and prior, in which case you need to manually track previous confirmations.
+       ///
        /// Will include any transactions passed to [`transactions_confirmed`] that have insufficient
        /// confirmations to be safe from a chain reorganization. Will not include any transactions
        /// passed to [`transaction_unconfirmed`], unless later reconfirmed.
index 31881d05dfa1c1883e066f526d76dca20037df99..378b4d794ff495231f1fcc8a133530769bd8bd1a 100644 (file)
@@ -660,13 +660,17 @@ pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &Pub
        let broadcaster_funding_key = broadcaster.serialize();
        let countersignatory_funding_key = countersignatory.serialize();
 
+       make_funding_redeemscript_from_slices(&broadcaster_funding_key, &countersignatory_funding_key)
+}
+
+pub(crate) fn make_funding_redeemscript_from_slices(broadcaster_funding_key: &[u8], countersignatory_funding_key: &[u8]) -> Script {
        let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2);
        if broadcaster_funding_key[..] < countersignatory_funding_key[..] {
-               builder.push_slice(&broadcaster_funding_key)
-                       .push_slice(&countersignatory_funding_key)
+               builder.push_slice(broadcaster_funding_key)
+                       .push_slice(countersignatory_funding_key)
        } else {
-               builder.push_slice(&countersignatory_funding_key)
-                       .push_slice(&broadcaster_funding_key)
+               builder.push_slice(countersignatory_funding_key)
+                       .push_slice(broadcaster_funding_key)
        }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script()
 }
 
index 385f5b5353ca5f697880c441061de805cfbc2d28..1532884fa605c5ba363720aa6701b602c83d92a2 100644 (file)
@@ -143,7 +143,7 @@ fn test_monitor_and_persister_update_fail() {
                let mut node_0_per_peer_lock;
                let mut node_0_peer_state_lock;
                let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
-               if let Ok((_, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
+               if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
                        // Check that even though the persister is returning a InProgress,
                        // because the update is bogus, ultimately the error that's returned
                        // should be a PermanentFailure.
@@ -181,8 +181,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
        assert_eq!(nodes[0].node.list_channels().len(), 1);
 
        if disconnect {
-               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
                reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
        }
 
@@ -234,8 +234,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
        assert_eq!(nodes[0].node.list_channels().len(), 1);
 
        if disconnect {
-               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
                reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
        }
 
@@ -337,8 +337,8 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
        };
 
        if disconnect_count & !disconnect_flags > 0 {
-               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        }
 
        // Now fix monitor updating...
@@ -348,13 +348,13 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
        check_added_monitors!(nodes[0], 0);
 
        macro_rules! disconnect_reconnect_peers { () => { {
-               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
                assert_eq!(reestablish_1.len(), 1);
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
                assert_eq!(reestablish_2.len(), 1);
 
@@ -373,10 +373,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
                assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
                assert_eq!(reestablish_1.len(), 1);
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
                assert_eq!(reestablish_2.len(), 1);
 
@@ -935,7 +935,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
 
        // Note that the ordering of the events for different nodes is non-prescriptive, though the
        // ordering of the two events that both go to nodes[2] have to stay in the same order.
-       let (nodes_0_event, events_3) = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &events_3);
+       let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events_3);
        let messages_a = match nodes_0_event {
                MessageSendEvent::UpdateHTLCs { node_id, mut updates } => {
                        assert_eq!(node_id, nodes[0].node.get_our_node_id());
@@ -949,12 +949,12 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
                _ => panic!("Unexpected event type!"),
        };
 
-       let (nodes_2_event, events_3) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events_3);
+       let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3);
        let send_event_b = SendEvent::from_event(nodes_2_event);
        assert_eq!(send_event_b.node_id, nodes[2].node.get_our_node_id());
 
        let raa = if test_ignore_second_cs {
-               let (nodes_2_event, _events_3) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events_3);
+               let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3);
                match nodes_2_event {
                        MessageSendEvent::SendRevokeAndACK { node_id, msg } => {
                                assert_eq!(node_id, nodes[2].node.get_our_node_id());
@@ -1110,8 +1110,8 @@ fn test_monitor_update_fail_reestablish() {
 
        let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        nodes[2].node.claim_funds(payment_preimage);
        check_added_monitors!(nodes[2], 1);
@@ -1130,8 +1130,8 @@ fn test_monitor_update_fail_reestablish() {
        commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
 
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
 
        let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
@@ -1146,11 +1146,11 @@ fn test_monitor_update_fail_reestablish() {
        nodes[1].node.get_and_clear_pending_msg_events(); // Free the holding cell
        check_added_monitors!(nodes[1], 1);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
 
        assert_eq!(get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(), as_reestablish);
        assert_eq!(get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(), bs_reestablish);
@@ -1315,15 +1315,15 @@ fn claim_while_disconnected_monitor_update_fail() {
        // Forward a payment for B to claim
        let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        nodes[1].node.claim_funds(payment_preimage_1);
        check_added_monitors!(nodes[1], 1);
        expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
 
        let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
        let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
@@ -1451,11 +1451,11 @@ fn monitor_failed_no_reestablish_response() {
 
        // Now disconnect and immediately reconnect, delivering the channel_reestablish while nodes[1]
        // is still failing to update monitors.
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
 
        let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
        let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
@@ -1602,7 +1602,6 @@ fn test_monitor_update_fail_claim() {
 
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
        nodes[1].node.claim_funds(payment_preimage_1);
-       expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        check_added_monitors!(nodes[1], 1);
 
@@ -1628,6 +1627,7 @@ fn test_monitor_update_fail_claim() {
        let events = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 0);
        commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false, true);
+       expect_pending_htlcs_forwardable_ignore!(nodes[1]);
 
        let (_, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[0]);
        nodes[2].node.send_payment(&route, payment_hash_3, &Some(payment_secret_3), PaymentId(payment_hash_3.0)).unwrap();
@@ -1645,6 +1645,7 @@ fn test_monitor_update_fail_claim() {
        let channel_id = chan_1.2;
        let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
        nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(outpoint, latest_update);
+       expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
        check_added_monitors!(nodes[1], 0);
 
        let bs_fulfill_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
@@ -1653,7 +1654,7 @@ fn test_monitor_update_fail_claim() {
        expect_payment_sent!(nodes[0], payment_preimage_1);
 
        // Get the payment forwards, note that they were batched into one commitment update.
-       expect_pending_htlcs_forwardable!(nodes[1]);
+       nodes[1].node.process_pending_htlc_forwards();
        check_added_monitors!(nodes[1], 1);
        let bs_forward_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[0]);
@@ -1739,7 +1740,6 @@ fn test_monitor_update_on_pending_forwards() {
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
        expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
        check_added_monitors!(nodes[1], 1);
-       assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
        let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
@@ -1752,12 +1752,18 @@ fn test_monitor_update_on_pending_forwards() {
        commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false, true);
 
        let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 2);
-       if let Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } = events[0] {
+       assert_eq!(events.len(), 3);
+       if let Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } = events[1] {
                assert_eq!(payment_hash, payment_hash_1);
                assert!(payment_failed_permanently);
        } else { panic!("Unexpected event!"); }
-       match events[1] {
+       match events[2] {
+               Event::PaymentFailed { payment_hash, .. } => {
+                       assert_eq!(payment_hash, payment_hash_1);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       match events[0] {
                Event::PendingHTLCsForwardable { .. } => { },
                _ => panic!("Unexpected event"),
        };
@@ -1797,7 +1803,6 @@ fn monitor_update_claim_fail_no_response() {
 
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
        nodes[1].node.claim_funds(payment_preimage_1);
-       expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
        check_added_monitors!(nodes[1], 1);
 
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -1805,6 +1810,7 @@ fn monitor_update_claim_fail_no_response() {
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
        let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
        nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(outpoint, latest_update);
+       expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
        check_added_monitors!(nodes[1], 0);
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 
@@ -1873,8 +1879,8 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
        }
 
        // Make sure nodes[1] isn't stupid enough to re-send the ChannelReady on reconnect
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, confirm_a_first), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -2041,12 +2047,12 @@ fn test_pending_update_fee_ack_on_reconnect() {
        let bs_first_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
        // bs_first_raa is not delivered until it is re-generated after reconnect
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_connect_msg);
@@ -2169,12 +2175,12 @@ fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) {
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_connect_msg);
@@ -2284,7 +2290,6 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
        chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
        nodes[0].node.claim_funds(payment_preimage_0);
        check_added_monitors!(nodes[0], 1);
-       expect_payment_claimed!(nodes[0], payment_hash_0, 100_000);
 
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send.msgs[0]);
        nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &send.commitment_msg);
@@ -2303,15 +2308,15 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
                        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
                        reload_node!(nodes[0], &nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized);
                } else {
-                       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+                       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
                }
-               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
                // Now reconnect the two
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
                assert_eq!(reestablish_1.len(), 1);
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
                assert_eq!(reestablish_2.len(), 1);
 
@@ -2347,6 +2352,7 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
        chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
        let (funding_txo, mon_id, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone();
        nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(funding_txo, mon_id);
+       expect_payment_claimed!(nodes[0], payment_hash_0, 100_000);
 
        // New outbound messages should be generated immediately upon a call to
        // get_and_clear_pending_msg_events (but not before).
@@ -2493,8 +2499,8 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
                assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        }
 
-       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        if second_fails {
                reconnect_nodes(&nodes[1], &nodes[2], (false, false), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0), (false, false));
@@ -2600,7 +2606,15 @@ fn test_permanent_error_during_sending_shutdown() {
        chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
 
        assert!(nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).is_ok());
-       check_closed_broadcast!(nodes[0], true);
+
+       // We always send the `shutdown` response when initiating a shutdown, even if we immediately
+       // close the channel thereafter.
+       let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(msg_events.len(), 3);
+       if let MessageSendEvent::SendShutdown { .. } = msg_events[0] {} else { panic!(); }
+       if let MessageSendEvent::BroadcastChannelUpdate { .. } = msg_events[1] {} else { panic!(); }
+       if let MessageSendEvent::HandleError { .. } =  msg_events[2] {} else { panic!(); }
+
        check_added_monitors!(nodes[0], 2);
        check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() });
 }
@@ -2623,7 +2637,15 @@ fn test_permanent_error_during_handling_shutdown() {
        assert!(nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).is_ok());
        let shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &shutdown);
-       check_closed_broadcast!(nodes[1], true);
+
+       // We always send the `shutdown` response when receiving a shutdown, even if we immediately
+       // close the channel thereafter.
+       let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(msg_events.len(), 3);
+       if let MessageSendEvent::SendShutdown { .. } = msg_events[0] {} else { panic!(); }
+       if let MessageSendEvent::BroadcastChannelUpdate { .. } = msg_events[1] {} else { panic!(); }
+       if let MessageSendEvent::HandleError { .. } =  msg_events[2] {} else { panic!(); }
+
        check_added_monitors!(nodes[1], 2);
        check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() });
 }
@@ -2645,7 +2667,6 @@ fn double_temp_error() {
        // `claim_funds` results in a ChannelMonitorUpdate.
        nodes[1].node.claim_funds(payment_preimage_1);
        check_added_monitors!(nodes[1], 1);
-       expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
        let (funding_tx, latest_update_1, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
 
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
@@ -2653,7 +2674,6 @@ fn double_temp_error() {
        // which had some asserts that prevented it from being called twice.
        nodes[1].node.claim_funds(payment_preimage_2);
        check_added_monitors!(nodes[1], 1);
-       expect_payment_claimed!(nodes[1], payment_hash_2, 1_000_000);
        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
 
        let (_, latest_update_2, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
@@ -2662,11 +2682,24 @@ fn double_temp_error() {
        check_added_monitors!(nodes[1], 0);
        nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(funding_tx, latest_update_2);
 
-       // Complete the first HTLC.
-       let events = nodes[1].node.get_and_clear_pending_msg_events();
-       assert_eq!(events.len(), 1);
+       // Complete the first HTLC. Note that as a side-effect we handle the monitor update completions
+       // and get both PaymentClaimed events at once.
+       let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
+
+       let events = nodes[1].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 2);
+       match events[0] {
+               Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => assert_eq!(payment_hash, payment_hash_1),
+               _ => panic!("Unexpected Event: {:?}", events[0]),
+       }
+       match events[1] {
+               Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => assert_eq!(payment_hash, payment_hash_2),
+               _ => panic!("Unexpected Event: {:?}", events[1]),
+       }
+
+       assert_eq!(msg_events.len(), 1);
        let (update_fulfill_1, commitment_signed_b1, node_id) = {
-               match &events[0] {
+               match &msg_events[0] {
                        &MessageSendEvent::UpdateHTLCs { ref 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_eq!(update_fulfill_htlcs.len(), 1);
index d9ec57d5a7e773c410640c8be4e47b1d96a9a482..e3641a6204a96d6685098a86ba6fc9d67309e15d 100644 (file)
@@ -36,6 +36,7 @@ use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBounde
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
 use crate::chain::transaction::{OutPoint, TransactionData};
 use crate::chain::keysinterface::{WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
+use crate::routing::gossip::NodeId;
 use crate::util::events::ClosureReason;
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
 use crate::util::logger::Logger;
@@ -392,35 +393,21 @@ enum UpdateFulfillFetch {
 }
 
 /// The return type of get_update_fulfill_htlc_and_commit.
-pub enum UpdateFulfillCommitFetch {
+pub enum UpdateFulfillCommitFetch<'a> {
        /// Indicates the HTLC fulfill is new, and either generated an update_fulfill message, placed
        /// it in the holding cell, or re-generated the update_fulfill message after the same claim was
        /// previously placed in the holding cell (and has since been removed).
        NewClaim {
                /// The ChannelMonitorUpdate which places the new payment preimage in the channel monitor
-               monitor_update: ChannelMonitorUpdate,
+               monitor_update: &'a ChannelMonitorUpdate,
                /// The value of the HTLC which was claimed, in msat.
                htlc_value_msat: u64,
-               /// The update_fulfill message and commitment_signed message (if the claim was not placed
-               /// in the holding cell).
-               msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>,
        },
        /// Indicates the HTLC fulfill is duplicative and already existed either in the holding cell
        /// or has been forgotten (presumably previously claimed).
        DuplicateClaim {},
 }
 
-/// The return value of `revoke_and_ack` on success, primarily updates to other channels or HTLC
-/// state.
-pub(super) struct RAAUpdates {
-       pub commitment_update: Option<msgs::CommitmentUpdate>,
-       pub accepted_htlcs: Vec<(PendingHTLCInfo, u64)>,
-       pub failed_htlcs: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
-       pub finalized_claimed_htlcs: Vec<HTLCSource>,
-       pub monitor_update: ChannelMonitorUpdate,
-       pub holding_cell_failed_htlcs: Vec<(HTLCSource, PaymentHash)>,
-}
-
 /// The return value of `monitor_updating_restored`
 pub(super) struct MonitorRestoreUpdates {
        pub raa: Option<msgs::RevokeAndACK>,
@@ -557,6 +544,11 @@ pub(super) struct Channel<Signer: ChannelSigner> {
        monitor_pending_channel_ready: bool,
        monitor_pending_revoke_and_ack: bool,
        monitor_pending_commitment_signed: bool,
+
+       // TODO: If a channel is drop'd, we don't know whether the `ChannelMonitor` is ultimately
+       // responsible for some of the HTLCs here or not - we don't know whether the update in question
+       // completed or not. We currently ignore these fields entirely when force-closing a channel,
+       // but need to handle this somehow or we run the risk of losing HTLCs!
        monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>,
        monitor_pending_failures: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
        monitor_pending_finalized_fulfills: Vec<HTLCSource>,
@@ -742,6 +734,12 @@ pub(super) struct Channel<Signer: ChannelSigner> {
        /// The unique identifier used to re-derive the private key material for the channel through
        /// [`SignerProvider::derive_channel_signer`].
        channel_keys_id: [u8; 32],
+
+       /// When we generate [`ChannelMonitorUpdate`]s to persist, they may not be persisted immediately.
+       /// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
+       /// completes we still need to be able to complete the persistence. Thus, we have to keep a
+       /// copy of the [`ChannelMonitorUpdate`] here until it is complete.
+       pending_monitor_updates: Vec<ChannelMonitorUpdate>,
 }
 
 #[cfg(any(test, fuzzing))]
@@ -1111,6 +1109,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                        channel_type,
                        channel_keys_id,
+
+                       pending_monitor_updates: Vec::new(),
                })
        }
 
@@ -1457,6 +1457,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                        channel_type,
                        channel_keys_id,
+
+                       pending_monitor_updates: Vec::new(),
                };
 
                Ok(chan)
@@ -1963,22 +1965,30 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                }
        }
 
-       pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> Result<UpdateFulfillCommitFetch, (ChannelError, ChannelMonitorUpdate)> where L::Target: Logger {
+       pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
                match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
-                       UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(update_fulfill_htlc) } => {
-                               let (commitment, mut additional_update) = match self.send_commitment_no_status_check(logger) {
-                                       Err(e) => return Err((e, monitor_update)),
-                                       Ok(res) => res
-                               };
-                               // send_commitment_no_status_check may bump latest_monitor_id but we want them to be
+                       UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
+                               let mut additional_update = self.build_commitment_no_status_check(logger);
+                               // build_commitment_no_status_check may bump latest_monitor_id but we want them to be
                                // strictly increasing by one, so decrement it here.
                                self.latest_monitor_update_id = monitor_update.update_id;
                                monitor_update.updates.append(&mut additional_update.updates);
-                               Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, msgs: Some((update_fulfill_htlc, commitment)) })
+                               self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
+                               self.pending_monitor_updates.push(monitor_update);
+                               UpdateFulfillCommitFetch::NewClaim {
+                                       monitor_update: self.pending_monitor_updates.last().unwrap(),
+                                       htlc_value_msat,
+                               }
                        },
-                       UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } =>
-                               Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, msgs: None }),
-                       UpdateFulfillFetch::DuplicateClaim {} => Ok(UpdateFulfillCommitFetch::DuplicateClaim {}),
+                       UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
+                               self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
+                               self.pending_monitor_updates.push(monitor_update);
+                               UpdateFulfillCommitFetch::NewClaim {
+                                       monitor_update: self.pending_monitor_updates.last().unwrap(),
+                                       htlc_value_msat,
+                               }
+                       }
+                       UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
                }
        }
 
@@ -2258,9 +2268,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
        pub fn funding_created<SP: Deref, L: Deref>(
                &mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L
-       ) -> Result<(msgs::FundingSigned, ChannelMonitor<<SP::Target as SignerProvider>::Signer>, Option<msgs::ChannelReady>), ChannelError>
+       ) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>), ChannelError>
        where
-               SP::Target: SignerProvider,
+               SP::Target: SignerProvider<Signer = Signer>,
                L::Target: Logger
        {
                if self.is_outbound() {
@@ -2336,19 +2346,22 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                log_info!(logger, "Generated funding_signed for peer for channel {}", log_bytes!(self.channel_id()));
 
+               let need_channel_ready = self.check_get_channel_ready(0).is_some();
+               self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
+
                Ok((msgs::FundingSigned {
                        channel_id: self.channel_id,
                        signature
-               }, channel_monitor, self.check_get_channel_ready(0)))
+               }, channel_monitor))
        }
 
        /// Handles a funding_signed message from the remote end.
        /// If this call is successful, broadcast the funding transaction (and not before!)
        pub fn funding_signed<SP: Deref, L: Deref>(
                &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
-       ) -> Result<(ChannelMonitor<<SP::Target as SignerProvider>::Signer>, Transaction, Option<msgs::ChannelReady>), ChannelError>
+       ) -> Result<ChannelMonitor<Signer>, ChannelError>
        where
-               SP::Target: SignerProvider,
+               SP::Target: SignerProvider<Signer = Signer>,
                L::Target: Logger
        {
                if !self.is_outbound() {
@@ -2421,7 +2434,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                log_info!(logger, "Received funding_signed from peer for channel {}", log_bytes!(self.channel_id()));
 
-               Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap(), self.check_get_channel_ready(0)))
+               let need_channel_ready = self.check_get_channel_ready(0).is_some();
+               self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
+               Ok(channel_monitor)
        }
 
        /// Handles a channel_ready message from our peer. If we've already sent our channel_ready
@@ -3033,17 +3048,17 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                Ok(())
        }
 
-       pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, ChannelMonitorUpdate), (Option<ChannelMonitorUpdate>, ChannelError)>
+       pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
                where L::Target: Logger
        {
                if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
-                       return Err((None, ChannelError::Close("Got commitment signed message when channel was not in an operational state".to_owned())));
+                       return Err(ChannelError::Close("Got commitment signed message when channel was not in an operational state".to_owned()));
                }
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
-                       return Err((None, ChannelError::Close("Peer sent commitment_signed when we needed a channel_reestablish".to_owned())));
+                       return Err(ChannelError::Close("Peer sent commitment_signed when we needed a channel_reestablish".to_owned()));
                }
                if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK == BOTH_SIDES_SHUTDOWN_MASK && self.last_sent_closing_fee.is_some() {
-                       return Err((None, ChannelError::Close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned())));
+                       return Err(ChannelError::Close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
                }
 
                let funding_script = self.get_funding_redeemscript();
@@ -3061,7 +3076,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                log_bytes!(self.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction),
                                log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));
                        if let Err(_) = self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.counterparty_funding_pubkey()) {
-                               return Err((None, ChannelError::Close("Invalid commitment tx signature from peer".to_owned())));
+                               return Err(ChannelError::Close("Invalid commitment tx signature from peer".to_owned()));
                        }
                        bitcoin_tx.txid
                };
@@ -3076,7 +3091,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        debug_assert!(!self.is_outbound());
                        let counterparty_reserve_we_require_msat = self.holder_selected_channel_reserve_satoshis * 1000;
                        if commitment_stats.remote_balance_msat < commitment_stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
-                               return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
+                               return Err(ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned()));
                        }
                }
                #[cfg(any(test, fuzzing))]
@@ -3098,7 +3113,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                }
 
                if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs {
-                       return Err((None, ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs))));
+                       return Err(ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
                }
 
                // TODO: Sadly, we pass HTLCs twice to ChannelMonitor: once via the HolderCommitmentTransaction and once via the update
@@ -3116,7 +3131,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                        log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()),
                                        encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), log_bytes!(self.channel_id()));
                                if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) {
-                                       return Err((None, ChannelError::Close("Invalid HTLC tx signature from peer".to_owned())));
+                                       return Err(ChannelError::Close("Invalid HTLC tx signature from peer".to_owned()));
                                }
                                htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source));
                        } else {
@@ -3132,10 +3147,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        self.counterparty_funding_pubkey()
                );
 
-               let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number - 1, &self.secp_ctx);
                self.holder_signer.validate_holder_commitment(&holder_commitment_tx, commitment_stats.preimages)
-                       .map_err(|_| (None, ChannelError::Close("Failed to validate our commitment".to_owned())))?;
-               let per_commitment_secret = self.holder_signer.release_commitment_secret(self.cur_holder_commitment_transaction_number + 1);
+                       .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?;
 
                // Update state now that we've passed all the can-fail calls...
                let mut need_commitment = false;
@@ -3180,7 +3193,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                self.cur_holder_commitment_transaction_number -= 1;
                // Note that if we need_commitment & !AwaitingRemoteRevoke we'll call
-               // send_commitment_no_status_check() next which will reset this to RAAFirst.
+               // build_commitment_no_status_check() next which will reset this to RAAFirst.
                self.resend_order = RAACommitmentOrder::CommitmentFirst;
 
                if (self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0 {
@@ -3192,52 +3205,50 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                // the corresponding HTLC status updates so that get_last_commitment_update
                                // includes the right HTLCs.
                                self.monitor_pending_commitment_signed = true;
-                               let (_, mut additional_update) = self.send_commitment_no_status_check(logger).map_err(|e| (None, e))?;
-                               // send_commitment_no_status_check may bump latest_monitor_id but we want them to be
+                               let mut additional_update = self.build_commitment_no_status_check(logger);
+                               // build_commitment_no_status_check may bump latest_monitor_id but we want them to be
                                // strictly increasing by one, so decrement it here.
                                self.latest_monitor_update_id = monitor_update.update_id;
                                monitor_update.updates.append(&mut additional_update.updates);
                        }
                        log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
                                log_bytes!(self.channel_id));
-                       return Err((Some(monitor_update), ChannelError::Ignore("Previous monitor update failure prevented generation of RAA".to_owned())));
+                       self.pending_monitor_updates.push(monitor_update);
+                       return Ok(self.pending_monitor_updates.last().unwrap());
                }
 
-               let commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
+               let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
                        // If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok -
                        // we'll send one right away when we get the revoke_and_ack when we
                        // free_holding_cell_htlcs().
-                       let (msg, mut additional_update) = self.send_commitment_no_status_check(logger).map_err(|e| (None, e))?;
-                       // send_commitment_no_status_check may bump latest_monitor_id but we want them to be
+                       let mut additional_update = self.build_commitment_no_status_check(logger);
+                       // build_commitment_no_status_check may bump latest_monitor_id but we want them to be
                        // strictly increasing by one, so decrement it here.
                        self.latest_monitor_update_id = monitor_update.update_id;
                        monitor_update.updates.append(&mut additional_update.updates);
-                       Some(msg)
-               } else { None };
+                       true
+               } else { false };
 
                log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
-                       log_bytes!(self.channel_id()), if commitment_signed.is_some() { " our own commitment_signed and" } else { "" });
-
-               Ok((msgs::RevokeAndACK {
-                       channel_id: self.channel_id,
-                       per_commitment_secret,
-                       next_per_commitment_point,
-               }, commitment_signed, monitor_update))
+                       log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
+               self.pending_monitor_updates.push(monitor_update);
+               self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
+               return Ok(self.pending_monitor_updates.last().unwrap());
        }
 
        /// Public version of the below, checking relevant preconditions first.
        /// If we're not in a state where freeing the holding cell makes sense, this is a no-op and
        /// returns `(None, Vec::new())`.
-       pub fn maybe_free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> Result<(Option<(msgs::CommitmentUpdate, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash)>), ChannelError> where L::Target: Logger {
+       pub fn maybe_free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>) where L::Target: Logger {
                if self.channel_state >= ChannelState::ChannelReady as u32 &&
                   (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateInProgress as u32)) == 0 {
                        self.free_holding_cell_htlcs(logger)
-               } else { Ok((None, Vec::new())) }
+               } else { (None, Vec::new()) }
        }
 
        /// Frees any pending commitment updates in the holding cell, generating the relevant messages
        /// for our counterparty.
-       fn free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> Result<(Option<(msgs::CommitmentUpdate, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash)>), ChannelError> where L::Target: Logger {
+       fn free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>) where L::Target: Logger {
                assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, 0);
                if self.holding_cell_htlc_updates.len() != 0 || self.holding_cell_update_fee.is_some() {
                        log_trace!(logger, "Freeing holding cell with {} HTLC updates{} in channel {}", self.holding_cell_htlc_updates.len(),
@@ -3318,7 +3329,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                }
                        }
                        if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() && self.holding_cell_update_fee.is_none() {
-                               return Ok((None, htlcs_to_fail));
+                               return (None, htlcs_to_fail);
                        }
                        let update_fee = if let Some(feerate) = self.holding_cell_update_fee.take() {
                                self.send_update_fee(feerate, false, logger)
@@ -3326,8 +3337,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                None
                        };
 
-                       let (commitment_signed, mut additional_update) = self.send_commitment_no_status_check(logger)?;
-                       // send_commitment_no_status_check and get_update_fulfill_htlc may bump latest_monitor_id
+                       let mut additional_update = self.build_commitment_no_status_check(logger);
+                       // build_commitment_no_status_check and get_update_fulfill_htlc may bump latest_monitor_id
                        // but we want them to be strictly increasing by one, so reset it here.
                        self.latest_monitor_update_id = monitor_update.update_id;
                        monitor_update.updates.append(&mut additional_update.updates);
@@ -3336,16 +3347,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                log_bytes!(self.channel_id()), if update_fee.is_some() { "a fee update, " } else { "" },
                                update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());
 
-                       Ok((Some((msgs::CommitmentUpdate {
-                               update_add_htlcs,
-                               update_fulfill_htlcs,
-                               update_fail_htlcs,
-                               update_fail_malformed_htlcs: Vec::new(),
-                               update_fee,
-                               commitment_signed,
-                       }, monitor_update)), htlcs_to_fail))
+                       self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
+                       self.pending_monitor_updates.push(monitor_update);
+                       (Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
                } else {
-                       Ok((None, Vec::new()))
+                       (None, Vec::new())
                }
        }
 
@@ -3354,7 +3360,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
        /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
        /// generating an appropriate error *after* the channel state has been updated based on the
        /// revoke_and_ack message.
-       pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<RAAUpdates, ChannelError>
+       pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
                where L::Target: Logger,
        {
                if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
@@ -3541,8 +3547,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                // When the monitor updating is restored we'll call get_last_commitment_update(),
                                // which does not update state, but we're definitely now awaiting a remote revoke
                                // before we can step forward any more, so set it here.
-                               let (_, mut additional_update) = self.send_commitment_no_status_check(logger)?;
-                               // send_commitment_no_status_check may bump latest_monitor_id but we want them to be
+                               let mut additional_update = self.build_commitment_no_status_check(logger);
+                               // build_commitment_no_status_check may bump latest_monitor_id but we want them to be
                                // strictly increasing by one, so decrement it here.
                                self.latest_monitor_update_id = monitor_update.update_id;
                                monitor_update.updates.append(&mut additional_update.updates);
@@ -3551,71 +3557,41 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        self.monitor_pending_failures.append(&mut revoked_htlcs);
                        self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
                        log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
-                       return Ok(RAAUpdates {
-                               commitment_update: None, finalized_claimed_htlcs: Vec::new(),
-                               accepted_htlcs: Vec::new(), failed_htlcs: Vec::new(),
-                               monitor_update,
-                               holding_cell_failed_htlcs: Vec::new()
-                       });
+                       self.pending_monitor_updates.push(monitor_update);
+                       return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
                }
 
-               match self.free_holding_cell_htlcs(logger)? {
-                       (Some((mut commitment_update, mut additional_update)), htlcs_to_fail) => {
-                               commitment_update.update_fail_htlcs.reserve(update_fail_htlcs.len());
-                               for fail_msg in update_fail_htlcs.drain(..) {
-                                       commitment_update.update_fail_htlcs.push(fail_msg);
-                               }
-                               commitment_update.update_fail_malformed_htlcs.reserve(update_fail_malformed_htlcs.len());
-                               for fail_msg in update_fail_malformed_htlcs.drain(..) {
-                                       commitment_update.update_fail_malformed_htlcs.push(fail_msg);
-                               }
-
+               match self.free_holding_cell_htlcs(logger) {
+                       (Some(_), htlcs_to_fail) => {
+                               let mut additional_update = self.pending_monitor_updates.pop().unwrap();
                                // free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
                                // strictly increasing by one, so decrement it here.
                                self.latest_monitor_update_id = monitor_update.update_id;
                                monitor_update.updates.append(&mut additional_update.updates);
 
-                               Ok(RAAUpdates {
-                                       commitment_update: Some(commitment_update),
-                                       finalized_claimed_htlcs,
-                                       accepted_htlcs: to_forward_infos,
-                                       failed_htlcs: revoked_htlcs,
-                                       monitor_update,
-                                       holding_cell_failed_htlcs: htlcs_to_fail
-                               })
+                               self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
+                               self.pending_monitor_updates.push(monitor_update);
+                               Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
                        },
                        (None, htlcs_to_fail) => {
                                if require_commitment {
-                                       let (commitment_signed, mut additional_update) = self.send_commitment_no_status_check(logger)?;
+                                       let mut additional_update = self.build_commitment_no_status_check(logger);
 
-                                       // send_commitment_no_status_check may bump latest_monitor_id but we want them to be
+                                       // build_commitment_no_status_check may bump latest_monitor_id but we want them to be
                                        // strictly increasing by one, so decrement it here.
                                        self.latest_monitor_update_id = monitor_update.update_id;
                                        monitor_update.updates.append(&mut additional_update.updates);
 
                                        log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
                                                log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
-                                       Ok(RAAUpdates {
-                                               commitment_update: Some(msgs::CommitmentUpdate {
-                                                       update_add_htlcs: Vec::new(),
-                                                       update_fulfill_htlcs: Vec::new(),
-                                                       update_fail_htlcs,
-                                                       update_fail_malformed_htlcs,
-                                                       update_fee: None,
-                                                       commitment_signed
-                                               }),
-                                               finalized_claimed_htlcs,
-                                               accepted_htlcs: to_forward_infos, failed_htlcs: revoked_htlcs,
-                                               monitor_update, holding_cell_failed_htlcs: htlcs_to_fail
-                                       })
+                                       self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
+                                       self.pending_monitor_updates.push(monitor_update);
+                                       Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
                                } else {
                                        log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
-                                       Ok(RAAUpdates {
-                                               commitment_update: None,
-                                               finalized_claimed_htlcs,
-                                               accepted_htlcs: to_forward_infos, failed_htlcs: revoked_htlcs,
-                                               monitor_update, holding_cell_failed_htlcs: htlcs_to_fail
-                                       })
+                                       self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
+                                       self.pending_monitor_updates.push(monitor_update);
+                                       Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
                                }
                        }
                }
@@ -3767,15 +3743,17 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
        }
 
        /// Indicates that a ChannelMonitor update is in progress and has not yet been fully persisted.
-       /// This must be called immediately after the [`chain::Watch`] call which returned
-       /// [`ChannelMonitorUpdateStatus::InProgress`].
+       /// This must be called before we return the [`ChannelMonitorUpdate`] back to the
+       /// [`ChannelManager`], which will call [`Self::monitor_updating_restored`] once the monitor
+       /// update completes (potentially immediately).
        /// The messages which were generated with the monitor update must *not* have been sent to the
        /// remote end, and must instead have been dropped. They will be regenerated when
        /// [`Self::monitor_updating_restored`] is called.
        ///
+       /// [`ChannelManager`]: super::channelmanager::ChannelManager
        /// [`chain::Watch`]: crate::chain::Watch
        /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress
-       pub fn monitor_updating_paused(&mut self, resend_raa: bool, resend_commitment: bool,
+       fn monitor_updating_paused(&mut self, resend_raa: bool, resend_commitment: bool,
                resend_channel_ready: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
                mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
                mut pending_finalized_claimed_htlcs: Vec<HTLCSource>
@@ -3802,6 +3780,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
        {
                assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
                self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
+               self.pending_monitor_updates.clear();
 
                // If we're past (or at) the FundingSent stage on an outbound channel, try to
                // (re-)broadcast the funding transaction as we may have declined to broadcast it when we
@@ -4279,7 +4258,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
        pub fn shutdown<SP: Deref>(
                &mut self, signer_provider: &SP, their_features: &InitFeatures, msg: &msgs::Shutdown
-       ) -> Result<(Option<msgs::Shutdown>, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
+       ) -> Result<(Option<msgs::Shutdown>, Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
        where SP::Target: SignerProvider
        {
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
@@ -4335,12 +4314,15 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                let monitor_update = if update_shutdown_script {
                        self.latest_monitor_update_id += 1;
-                       Some(ChannelMonitorUpdate {
+                       let monitor_update = ChannelMonitorUpdate {
                                update_id: self.latest_monitor_update_id,
                                updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
                                        scriptpubkey: self.get_closing_scriptpubkey(),
                                }],
-                       })
+                       };
+                       self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
+                       self.pending_monitor_updates.push(monitor_update);
+                       Some(self.pending_monitor_updates.last().unwrap())
                } else { None };
                let shutdown = if send_shutdown {
                        Some(msgs::Shutdown {
@@ -4890,6 +4872,10 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                (self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
        }
 
+       pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
+               self.pending_monitor_updates.first()
+       }
+
        /// Returns true if funding_created was sent/received.
        pub fn is_funding_initiated(&self) -> bool {
                self.channel_state >= ChannelState::FundingSent as u32
@@ -5416,18 +5402,19 @@ impl<Signer: WriteableEcdsaChannelSigner> 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 node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node)
+                       .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?);
+               let counterparty_node_id = NodeId::from_pubkey(&self.get_counterparty_node_id());
+               let were_node_one = node_id.as_slice() < counterparty_node_id.as_slice();
 
                let msg = msgs::UnsignedChannelAnnouncement {
                        features: channelmanager::provided_channel_features(&user_config),
                        chain_hash,
                        short_channel_id: self.get_short_channel_id().unwrap(),
-                       node_id_1: if were_node_one { node_id } else { self.get_counterparty_node_id() },
-                       node_id_2: if were_node_one { self.get_counterparty_node_id() } else { node_id },
-                       bitcoin_key_1: if were_node_one { self.get_holder_pubkeys().funding_pubkey } else { self.counterparty_funding_pubkey().clone() },
-                       bitcoin_key_2: if were_node_one { self.counterparty_funding_pubkey().clone() } else { self.get_holder_pubkeys().funding_pubkey },
+                       node_id_1: if were_node_one { node_id } else { counterparty_node_id },
+                       node_id_2: if were_node_one { counterparty_node_id } else { node_id },
+                       bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.get_holder_pubkeys().funding_pubkey } else { self.counterparty_funding_pubkey() }),
+                       bitcoin_key_2: NodeId::from_pubkey(if were_node_one { self.counterparty_funding_pubkey() } else { &self.get_holder_pubkeys().funding_pubkey }),
                        excess_data: Vec::new(),
                };
 
@@ -5497,8 +5484,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                &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 our_node_key = node_signer.get_node_id(Recipient::Node)
-                               .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?;
+                       let our_node_key = NodeId::from_pubkey(&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 = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement))
@@ -5789,8 +5776,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                Ok(Some(res))
        }
 
-       /// Only fails in case of bad keys
-       fn send_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> Result<(msgs::CommitmentSigned, ChannelMonitorUpdate), ChannelError> where L::Target: Logger {
+       fn build_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger {
                log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
                // We can upgrade the status of some HTLCs that are waiting on a commitment, even if we
                // fail to generate this, we still are at least at a position where upgrading their status
@@ -5823,15 +5809,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                }
                self.resend_order = RAACommitmentOrder::RevokeAndACKFirst;
 
-               let (res, counterparty_commitment_txid, htlcs) = match self.send_commitment_no_state_update(logger) {
-                       Ok((res, (counterparty_commitment_tx, mut htlcs))) => {
-                               // Update state now that we've passed all the can-fail calls...
-                               let htlcs_no_ref: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)> =
-                                       htlcs.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect();
-                               (res, counterparty_commitment_tx, htlcs_no_ref)
-                       },
-                       Err(e) => return Err(e),
-               };
+               let (counterparty_commitment_txid, mut htlcs_ref) = self.build_commitment_no_state_update(logger);
+               let htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)> =
+                       htlcs_ref.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect();
 
                if self.announcement_sigs_state == AnnouncementSigsState::MessageSent {
                        self.announcement_sigs_state = AnnouncementSigsState::Committed;
@@ -5848,16 +5828,13 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        }]
                };
                self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
-               Ok((res, monitor_update))
+               monitor_update
        }
 
-       /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
-       /// when we shouldn't change HTLC/channel state.
-       fn send_commitment_no_state_update<L: Deref>(&self, logger: &L) -> Result<(msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> where L::Target: Logger {
+       fn build_commitment_no_state_update<L: Deref>(&self, logger: &L) -> (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>) where L::Target: Logger {
                let counterparty_keys = self.build_remote_transaction_keys();
                let commitment_stats = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
                let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
-               let (signature, htlc_signatures);
 
                #[cfg(any(test, fuzzing))]
                {
@@ -5877,6 +5854,21 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        }
                }
 
+               (counterparty_commitment_txid, commitment_stats.htlcs_included)
+       }
+
+       /// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed
+       /// generation when we shouldn't change HTLC/channel state.
+       fn send_commitment_no_state_update<L: Deref>(&self, logger: &L) -> Result<(msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> where L::Target: Logger {
+               // Get the fee tests from `build_commitment_no_state_update`
+               #[cfg(any(test, fuzzing))]
+               self.build_commitment_no_state_update(logger);
+
+               let counterparty_keys = self.build_remote_transaction_keys();
+               let commitment_stats = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
+               let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
+               let (signature, htlc_signatures);
+
                {
                        let mut htlcs = Vec::with_capacity(commitment_stats.htlcs_included.len());
                        for &(ref htlc, _) in commitment_stats.htlcs_included.iter() {
@@ -5909,16 +5901,20 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                }, (counterparty_commitment_txid, commitment_stats.htlcs_included)))
        }
 
-       /// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
-       /// to send to the remote peer in one go.
+       /// Adds a pending outbound HTLC to this channel, and builds a new remote commitment
+       /// transaction and generates the corresponding [`ChannelMonitorUpdate`] in one go.
        ///
        /// Shorthand for calling [`Self::send_htlc`] followed by a commitment update, see docs on
-       /// [`Self::send_htlc`] and [`Self::send_commitment_no_state_update`] for more info.
-       pub fn send_htlc_and_commit<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned, ChannelMonitorUpdate)>, ChannelError> where L::Target: Logger {
-               match self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger)? {
-                       Some(update_add_htlc) => {
-                               let (commitment_signed, monitor_update) = self.send_commitment_no_status_check(logger)?;
-                               Ok(Some((update_add_htlc, commitment_signed, monitor_update)))
+       /// [`Self::send_htlc`] and [`Self::build_commitment_no_state_update`] for more info.
+       pub fn send_htlc_and_commit<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError> where L::Target: Logger {
+               let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger);
+               if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } }
+               match send_res? {
+                       Some(_) => {
+                               let monitor_update = self.build_commitment_no_status_check(logger);
+                               self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
+                               self.pending_monitor_updates.push(monitor_update);
+                               Ok(Some(self.pending_monitor_updates.last().unwrap()))
                        },
                        None => Ok(None)
                }
@@ -5944,8 +5940,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
        /// Begins the shutdown process, getting a message for the remote peer and returning all
        /// holding cell HTLCs for payment failure.
-       pub fn get_shutdown<SP: Deref>(&mut self, signer_provider: &SP, their_features: &InitFeatures, target_feerate_sats_per_kw: Option<u32>)
-       -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
+       ///
+       /// May jump to the channel being fully shutdown (see [`Self::is_shutdown`]) in which case no
+       /// [`ChannelMonitorUpdate`] will be returned).
+       pub fn get_shutdown<SP: Deref>(&mut self, signer_provider: &SP, their_features: &InitFeatures,
+               target_feerate_sats_per_kw: Option<u32>)
+       -> Result<(msgs::Shutdown, Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
        where SP::Target: SignerProvider {
                for htlc in self.pending_outbound_htlcs.iter() {
                        if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
@@ -5965,9 +5965,16 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()});
                }
 
+               // If we haven't funded the channel yet, we don't need to bother ensuring the shutdown
+               // script is set, we just force-close and call it a day.
+               let mut chan_closed = false;
+               if self.channel_state < ChannelState::FundingSent as u32 {
+                       chan_closed = true;
+               }
+
                let update_shutdown_script = match self.shutdown_scriptpubkey {
                        Some(_) => false,
-                       None => {
+                       None if !chan_closed => {
                                let shutdown_scriptpubkey = signer_provider.get_shutdown_scriptpubkey();
                                if !shutdown_scriptpubkey.is_compatible(their_features) {
                                        return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() });
@@ -5975,6 +5982,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                                self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
                                true
                        },
+                       None => false,
                };
 
                // From here on out, we may not fail!
@@ -5988,12 +5996,15 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                let monitor_update = if update_shutdown_script {
                        self.latest_monitor_update_id += 1;
-                       Some(ChannelMonitorUpdate {
+                       let monitor_update = ChannelMonitorUpdate {
                                update_id: self.latest_monitor_update_id,
                                updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
                                        scriptpubkey: self.get_closing_scriptpubkey(),
                                }],
-                       })
+                       };
+                       self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
+                       self.pending_monitor_updates.push(monitor_update);
+                       Some(self.pending_monitor_updates.last().unwrap())
                } else { None };
                let shutdown = msgs::Shutdown {
                        channel_id: self.channel_id,
@@ -6014,6 +6025,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        }
                });
 
+               debug_assert!(!self.is_shutdown() || monitor_update.is_none(),
+                       "we can't both complete shutdown and return a monitor update");
+
                Ok((shutdown, monitor_update, dropped_outbound_htlcs))
        }
 
@@ -6875,6 +6889,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
 
                        channel_type: channel_type.unwrap(),
                        channel_keys_id,
+
+                       pending_monitor_updates: Vec::new(),
                })
        }
 }
@@ -7186,7 +7202,7 @@ mod tests {
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap();
-               let (funding_signed_msg, _, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).unwrap();
+               let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).unwrap();
 
                // Node B --> Node A: funding signed
                let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger);
index b2a23c7c1d44cbdf03137263c663acaa285774c1..577e0984448a257a2ff9a23f305aa2684ef968dc 100644 (file)
@@ -53,7 +53,7 @@ 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, PaymentAttempts, PendingOutboundPayment, Retry};
+use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment};
 use crate::ln::wire::Encode;
 use crate::chain::keysinterface::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, ChannelSigner};
 use crate::util::config::{UserConfig, ChannelConfig};
@@ -65,18 +65,20 @@ use crate::util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, Maybe
 use crate::util::logger::{Level, Logger};
 use crate::util::errors::APIError;
 
+use alloc::collections::BTreeMap;
+
 use crate::io;
 use crate::prelude::*;
 use core::{cmp, mem};
 use core::cell::RefCell;
 use crate::io::Read;
-use crate::sync::{Arc, Mutex, RwLock, RwLockReadGuard, FairRwLock};
+use crate::sync::{Arc, Mutex, RwLock, RwLockReadGuard, FairRwLock, LockTestExt, LockHeldState};
 use core::sync::atomic::{AtomicUsize, Ordering};
 use core::time::Duration;
 use core::ops::Deref;
 
 // Re-export this for use in the public API.
-pub use crate::ln::outbound_payment::PaymentSendFailure;
+pub use crate::ln::outbound_payment::{PaymentSendFailure, Retry, RetryableSendFailure};
 
 // We hold various information about HTLC relay in the HTLC objects in Channel itself:
 //
@@ -245,6 +247,10 @@ pub(crate) enum HTLCSource {
                first_hop_htlc_msat: u64,
                payment_id: PaymentId,
                payment_secret: Option<PaymentSecret>,
+               /// Note that this is now "deprecated" - we write it for forwards (and read it for
+               /// backwards) compatibility reasons, but prefer to use the data in the
+               /// [`super::outbound_payment`] module, which stores per-payment data once instead of in
+               /// each HTLC.
                payment_params: Option<PaymentParameters>,
        },
 }
@@ -339,17 +345,6 @@ impl MsgHandleErrInternal {
                }
        }
        #[inline]
-       fn ignore_no_close(err: String) -> Self {
-               Self {
-                       err: LightningError {
-                               err,
-                               action: msgs::ErrorAction::IgnoreError,
-                       },
-                       chan_id: None,
-                       shutdown_finish: None,
-               }
-       }
-       #[inline]
        fn from_no_close(err: msgs::LightningError) -> Self {
                Self { err, chan_id: None, shutdown_finish: None }
        }
@@ -460,6 +455,7 @@ enum BackgroundEvent {
        ClosingMonitorUpdate((OutPoint, ChannelMonitorUpdate)),
 }
 
+#[derive(Debug)]
 pub(crate) enum MonitorUpdateCompletionAction {
        /// Indicates that a payment ultimately destined for us was claimed and we should emit an
        /// [`events::Event::PaymentClaimed`] to the user if we haven't yet generated such an event for
@@ -470,6 +466,11 @@ pub(crate) enum MonitorUpdateCompletionAction {
        EmitEvent { event: events::Event },
 }
 
+impl_writeable_tlv_based_enum_upgradable!(MonitorUpdateCompletionAction,
+       (0, PaymentClaimed) => { (0, payment_hash, required) },
+       (2, EmitEvent) => { (0, event, ignorable) },
+);
+
 /// State we hold per-peer.
 pub(super) struct PeerState<Signer: ChannelSigner> {
        /// `temporary_channel_id` or `channel_id` -> `channel`.
@@ -483,6 +484,37 @@ pub(super) struct PeerState<Signer: ChannelSigner> {
        /// Messages to send to the peer - pushed to in the same lock that they are generated in (except
        /// for broadcast messages, where ordering isn't as strict).
        pub(super) pending_msg_events: Vec<MessageSendEvent>,
+       /// Map from a specific channel to some action(s) that should be taken when all pending
+       /// [`ChannelMonitorUpdate`]s for the channel complete updating.
+       ///
+       /// Note that because we generally only have one entry here a HashMap is pretty overkill. A
+       /// BTreeMap currently stores more than ten elements per leaf node, so even up to a few
+       /// channels with a peer this will just be one allocation and will amount to a linear list of
+       /// channels to walk, avoiding the whole hashing rigmarole.
+       ///
+       /// Note that the channel may no longer exist. For example, if a channel was closed but we
+       /// later needed to claim an HTLC which is pending on-chain, we may generate a monitor update
+       /// for a missing channel. While a malicious peer could construct a second channel with the
+       /// same `temporary_channel_id` (or final `channel_id` in the case of 0conf channels or prior
+       /// to funding appearing on-chain), the downstream `ChannelMonitor` set is required to ensure
+       /// duplicates do not occur, so such channels should fail without a monitor update completing.
+       monitor_update_blocked_actions: BTreeMap<[u8; 32], Vec<MonitorUpdateCompletionAction>>,
+       /// The peer is currently connected (i.e. we've seen a
+       /// [`ChannelMessageHandler::peer_connected`] and no corresponding
+       /// [`ChannelMessageHandler::peer_disconnected`].
+       is_connected: bool,
+}
+
+impl <Signer: ChannelSigner> PeerState<Signer> {
+       /// Indicates that a peer meets the criteria where we're ok to remove it from our storage.
+       /// If true is passed for `require_disconnected`, the function will return false if we haven't
+       /// disconnected from the node already, ie. `PeerState::is_connected` is set to `true`.
+       fn ok_to_remove(&self, require_disconnected: bool) -> bool {
+               if require_disconnected && self.is_connected {
+                       return false
+               }
+               self.channel_by_id.is_empty() && self.monitor_update_blocked_actions.is_empty()
+       }
 }
 
 /// Stores a PaymentSecret and any other data we may need to validate an inbound payment is
@@ -573,6 +605,15 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = C
 /// offline for a full minute. In order to track this, you must call
 /// timer_tick_occurred roughly once per minute, though it doesn't have to be perfect.
 ///
+/// To avoid trivial DoS issues, ChannelManager limits the number of inbound connections and
+/// inbound channels without confirmed funding transactions. This may result in nodes which we do
+/// not have a channel with being unable to connect to us or open new channels with us if we have
+/// many peers with unfunded channels.
+///
+/// Because it is an indication of trust, inbound channels which we've accepted as 0conf are
+/// exempted from the count of unfunded channels. Similarly, outbound channels and connections are
+/// never limited. Please ensure you limit the count of such channels yourself.
+///
 /// Rather than using a plain ChannelManager, it is preferable to use either a SimpleArcChannelManager
 /// a SimpleRefChannelManager, for conciseness. See their documentation for more details, but
 /// essentially you should default to using a SimpleRefChannelManager, and use a
@@ -759,9 +800,8 @@ where
        /// very far in the past, and can only ever be up to two hours in the future.
        highest_seen_timestamp: AtomicUsize,
 
-       /// The bulk of our storage will eventually be here (message queues and the like). Currently
-       /// the `per_peer_state` stores our channels on a per-peer basis, as well as the peer's latest
-       /// features.
+       /// The bulk of our storage. Currently the `per_peer_state` stores our channels on a per-peer
+       /// basis, as well as the peer's latest features.
        ///
        /// If we are connected to a peer we always at least have an entry here, even if no channels
        /// are currently open with that peer.
@@ -924,6 +964,19 @@ pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3;
 /// [`OutboundPayments::remove_stale_resolved_payments`].
 pub(crate) const IDEMPOTENCY_TIMEOUT_TICKS: u8 = 7;
 
+/// The maximum number of unfunded channels we can have per-peer before we start rejecting new
+/// (inbound) ones. The number of peers with unfunded channels is limited separately in
+/// [`MAX_UNFUNDED_CHANNEL_PEERS`].
+const MAX_UNFUNDED_CHANS_PER_PEER: usize = 4;
+
+/// The maximum number of peers from which we will allow pending unfunded channels. Once we reach
+/// this many peers we reject new (inbound) channels from peers with which we don't have a channel.
+const MAX_UNFUNDED_CHANNEL_PEERS: usize = 50;
+
+/// The maximum number of peers which we do not have a (funded) channel with. Once we reach this
+/// many peers we reject new (inbound) connections.
+const MAX_NO_CHANNEL_PEERS: usize = 250;
+
 /// Information needed for constructing an invoice route hint for this channel.
 #[derive(Clone, Debug, PartialEq)]
 pub struct CounterpartyForwardingInfo {
@@ -1150,6 +1203,36 @@ impl ChannelDetails {
        }
 }
 
+/// Used by [`ChannelManager::list_recent_payments`] to express the status of recent payments.
+/// These include payments that have yet to find a successful path, or have unresolved HTLCs.
+#[derive(Debug, PartialEq)]
+pub enum RecentPaymentDetails {
+       /// When a payment is still being sent and awaiting successful delivery.
+       Pending {
+               /// Hash of the payment that is currently being sent but has yet to be fulfilled or
+               /// abandoned.
+               payment_hash: PaymentHash,
+               /// Total amount (in msat, excluding fees) across all paths for this payment,
+               /// not just the amount currently inflight.
+               total_msat: u64,
+       },
+       /// When a pending payment is fulfilled, we continue tracking it until all pending HTLCs have
+       /// been resolved. Upon receiving [`Event::PaymentSent`], we delay for a few minutes before the
+       /// payment is removed from tracking.
+       Fulfilled {
+               /// Hash of the payment that was claimed. `None` for serializations of [`ChannelManager`]
+               /// made before LDK version 0.0.104.
+               payment_hash: Option<PaymentHash>,
+       },
+       /// After a payment's retries are exhausted per the provided [`Retry`], or it is explicitly
+       /// abandoned via [`ChannelManager::abandon_payment`], it is marked as abandoned until all
+       /// pending HTLCs for this payment resolve and an [`Event::PaymentFailed`] is generated.
+       Abandoned {
+               /// Hash of the payment that we have given up trying to send.
+               payment_hash: PaymentHash,
+       },
+}
+
 /// Route hints used in constructing invoices for [phantom node payents].
 ///
 /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
@@ -1169,13 +1252,10 @@ macro_rules! handle_error {
                match $internal {
                        Ok(msg) => Ok(msg),
                        Err(MsgHandleErrInternal { err, chan_id, shutdown_finish }) => {
-                               #[cfg(any(feature = "_test_utils", test))]
-                               {
-                                       // In testing, ensure there are no deadlocks where the lock is already held upon
-                                       // entering the macro.
-                                       debug_assert!($self.pending_events.try_lock().is_ok());
-                                       debug_assert!($self.per_peer_state.try_write().is_ok());
-                               }
+                               // In testing, ensure there are no deadlocks where the lock is already held upon
+                               // entering the macro.
+                               debug_assert_ne!($self.pending_events.held_by_thread(), LockHeldState::HeldByThread);
+                               debug_assert_ne!($self.per_peer_state.held_by_thread(), LockHeldState::HeldByThread);
 
                                let mut msg_events = Vec::with_capacity(2);
 
@@ -1209,26 +1289,6 @@ macro_rules! handle_error {
                                                let mut peer_state = peer_state_mutex.lock().unwrap();
                                                peer_state.pending_msg_events.append(&mut msg_events);
                                        }
-                                       #[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
-                                                       // has been passed to our message handling functions.
-                                                       let expected_error_str = format!("Can't find a peer matching the passed counterparty node_id {}", $counterparty_node_id);
-                                                       match err.action {
-                                                               msgs::ErrorAction::SendErrorMessage {
-                                                                       msg: msgs::ErrorMessage { ref channel_id, ref data }
-                                                               }
-                                                               => {
-                                                                       assert_eq!(*data, expected_error_str);
-                                                                       if let Some((err_channel_id, _user_channel_id)) = chan_id {
-                                                                               debug_assert_eq!(*channel_id, err_channel_id);
-                                                                       }
-                                                               }
-                                                               _ => debug_assert!(false, "Unexpected event"),
-                                                       }
-                                               }
-                                       }
                                }
 
                                // Return error in case higher-API need one
@@ -1319,78 +1379,6 @@ macro_rules! remove_channel {
        }
 }
 
-macro_rules! handle_monitor_update_res {
-       ($self: ident, $err: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_channel_ready: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
-               match $err {
-                       ChannelMonitorUpdateStatus::PermanentFailure => {
-                               log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateStatus::PermanentFailure", log_bytes!($chan_id[..]));
-                               update_maps_on_chan_removal!($self, $chan);
-                               // TODO: $failed_fails is dropped here, which will cause other channels to hit the
-                               // chain in a confused state! We need to move them into the ChannelMonitor which
-                               // will be responsible for failing backwards once things confirm on-chain.
-                               // It's ok that we drop $failed_forwards here - at this point we'd rather they
-                               // broadcast HTLC-Timeout and pay the associated fees to get their funds back than
-                               // us bother trying to claim it just to forward on to another peer. If we're
-                               // splitting hairs we'd prefer to claim payments that were to us, but we haven't
-                               // given up the preimage yet, so might as well just wait until the payment is
-                               // retried, avoiding the on-chain fees.
-                               let res: Result<(), _> = Err(MsgHandleErrInternal::from_finish_shutdown("ChannelMonitor storage failure".to_owned(), *$chan_id, $chan.get_user_id(),
-                                               $chan.force_shutdown(false), $self.get_channel_update_for_broadcast(&$chan).ok() ));
-                               (res, true)
-                       },
-                       ChannelMonitorUpdateStatus::InProgress => {
-                               log_info!($self.logger, "Disabling channel {} due to monitor update in progress. On restore will send {} and process {} forwards, {} fails, and {} fulfill finalizations",
-                                               log_bytes!($chan_id[..]),
-                                               if $resend_commitment && $resend_raa {
-                                                               match $action_type {
-                                                                       RAACommitmentOrder::CommitmentFirst => { "commitment then RAA" },
-                                                                       RAACommitmentOrder::RevokeAndACKFirst => { "RAA then commitment" },
-                                                               }
-                                                       } else if $resend_commitment { "commitment" }
-                                                       else if $resend_raa { "RAA" }
-                                                       else { "nothing" },
-                                               (&$failed_forwards as &Vec<(PendingHTLCInfo, u64)>).len(),
-                                               (&$failed_fails as &Vec<(HTLCSource, PaymentHash, HTLCFailReason)>).len(),
-                                               (&$failed_finalized_fulfills as &Vec<HTLCSource>).len());
-                               if !$resend_commitment {
-                                       debug_assert!($action_type == RAACommitmentOrder::RevokeAndACKFirst || !$resend_raa);
-                               }
-                               if !$resend_raa {
-                                       debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment);
-                               }
-                               $chan.monitor_updating_paused($resend_raa, $resend_commitment, $resend_channel_ready, $failed_forwards, $failed_fails, $failed_finalized_fulfills);
-                               (Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor".to_owned()), *$chan_id)), false)
-                       },
-                       ChannelMonitorUpdateStatus::Completed => {
-                               (Ok(()), false)
-                       },
-               }
-       };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_channel_ready: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { {
-               let (res, drop) = handle_monitor_update_res!($self, $err, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $resend_channel_ready, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
-               if drop {
-                       $entry.remove_entry();
-               }
-               res
-       } };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $chan_id: expr, COMMITMENT_UPDATE_ONLY) => { {
-               debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst);
-               handle_monitor_update_res!($self, $err, $entry, $action_type, false, true, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
-       } };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $chan_id: expr, NO_UPDATE) => {
-               handle_monitor_update_res!($self, $err, $entry, $action_type, false, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
-       };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $resend_channel_ready: expr, OPTIONALLY_RESEND_FUNDING_LOCKED) => {
-               handle_monitor_update_res!($self, $err, $entry, $action_type, false, false, $resend_channel_ready, Vec::new(), Vec::new(), Vec::new())
-       };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => {
-               handle_monitor_update_res!($self, $err, $entry, $action_type, $resend_raa, $resend_commitment, false, Vec::new(), Vec::new(), Vec::new())
-       };
-       ($self: ident, $err: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => {
-               handle_monitor_update_res!($self, $err, $entry, $action_type, $resend_raa, $resend_commitment, false, $failed_forwards, $failed_fails, Vec::new())
-       };
-}
-
 macro_rules! send_channel_ready {
        ($self: ident, $pending_msg_events: expr, $channel: expr, $channel_ready_msg: expr) => {{
                $pending_msg_events.push(events::MessageSendEvent::SendChannelReady {
@@ -1428,6 +1416,93 @@ macro_rules! emit_channel_ready_event {
        }
 }
 
+macro_rules! handle_monitor_update_completion {
+       ($self: ident, $update_id: expr, $peer_state_lock: expr, $peer_state: expr, $chan: expr) => { {
+               let mut updates = $chan.monitor_updating_restored(&$self.logger,
+                       &$self.node_signer, $self.genesis_hash, &$self.default_configuration,
+                       $self.best_block.read().unwrap().height());
+               let counterparty_node_id = $chan.get_counterparty_node_id();
+               let channel_update = if updates.channel_ready.is_some() && $chan.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
+                       // channel_update later through the announcement_signatures process for public
+                       // channels, but there's no reason not to just inform our counterparty of our fees
+                       // now.
+                       if let Ok(msg) = $self.get_channel_update_for_unicast($chan) {
+                               Some(events::MessageSendEvent::SendChannelUpdate {
+                                       node_id: counterparty_node_id,
+                                       msg,
+                               })
+                       } else { None }
+               } else { None };
+
+               let update_actions = $peer_state.monitor_update_blocked_actions
+                       .remove(&$chan.channel_id()).unwrap_or(Vec::new());
+
+               let htlc_forwards = $self.handle_channel_resumption(
+                       &mut $peer_state.pending_msg_events, $chan, updates.raa,
+                       updates.commitment_update, updates.order, updates.accepted_htlcs,
+                       updates.funding_broadcastable, updates.channel_ready,
+                       updates.announcement_sigs);
+               if let Some(upd) = channel_update {
+                       $peer_state.pending_msg_events.push(upd);
+               }
+
+               let channel_id = $chan.channel_id();
+               core::mem::drop($peer_state_lock);
+
+               $self.handle_monitor_update_completion_actions(update_actions);
+
+               if let Some(forwards) = htlc_forwards {
+                       $self.forward_htlcs(&mut [forwards][..]);
+               }
+               $self.finalize_claims(updates.finalized_claimed_htlcs);
+               for failure in updates.failed_htlcs.drain(..) {
+                       let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
+                       $self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver);
+               }
+       } }
+}
+
+macro_rules! handle_new_monitor_update {
+       ($self: ident, $update_res: expr, $update_id: expr, $peer_state_lock: expr, $peer_state: expr, $chan: expr, MANUALLY_REMOVING, $remove: expr) => { {
+               // update_maps_on_chan_removal needs to be able to take id_to_peer, so make sure we can in
+               // any case so that it won't deadlock.
+               debug_assert!($self.id_to_peer.try_lock().is_ok());
+               match $update_res {
+                       ChannelMonitorUpdateStatus::InProgress => {
+                               log_debug!($self.logger, "ChannelMonitor update for {} in flight, holding messages until the update completes.",
+                                       log_bytes!($chan.channel_id()[..]));
+                               Ok(())
+                       },
+                       ChannelMonitorUpdateStatus::PermanentFailure => {
+                               log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateStatus::PermanentFailure",
+                                       log_bytes!($chan.channel_id()[..]));
+                               update_maps_on_chan_removal!($self, $chan);
+                               let res: Result<(), _> = Err(MsgHandleErrInternal::from_finish_shutdown(
+                                       "ChannelMonitor storage failure".to_owned(), $chan.channel_id(),
+                                       $chan.get_user_id(), $chan.force_shutdown(false),
+                                       $self.get_channel_update_for_broadcast(&$chan).ok()));
+                               $remove;
+                               res
+                       },
+                       ChannelMonitorUpdateStatus::Completed => {
+                               if ($update_id == 0 || $chan.get_next_monitor_update()
+                                       .expect("We can't be processing a monitor update if it isn't queued")
+                                       .update_id == $update_id) &&
+                                       $chan.get_latest_monitor_update_id() == $update_id
+                               {
+                                       handle_monitor_update_completion!($self, $update_id, $peer_state_lock, $peer_state, $chan);
+                               }
+                               Ok(())
+                       },
+               }
+       } };
+       ($self: ident, $update_res: expr, $update_id: expr, $peer_state_lock: expr, $peer_state: expr, $chan_entry: expr) => {
+               handle_new_monitor_update!($self, $update_res, $update_id, $peer_state_lock, $peer_state, $chan_entry.get_mut(), MANUALLY_REMOVING, $chan_entry.remove_entry())
+       }
+}
+
 impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, L>
 where
        M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
@@ -1558,12 +1633,10 @@ where
 
                let per_peer_state = self.per_peer_state.read().unwrap();
 
-               let peer_state_mutex_opt = per_peer_state.get(&their_network_key);
-               if let None = peer_state_mutex_opt {
-                       return Err(APIError::APIMisuseError { err: format!("Not connected to node: {}", their_network_key) });
-               }
+               let peer_state_mutex = per_peer_state.get(&their_network_key)
+                       .ok_or_else(|| APIError::APIMisuseError{ err: format!("Not connected to node: {}", their_network_key) })?;
 
-               let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let mut peer_state = peer_state_mutex.lock().unwrap();
                let channel = {
                        let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
                        let their_features = &peer_state.latest_features;
@@ -1601,14 +1674,13 @@ where
        }
 
        fn list_channels_with_filter<Fn: FnMut(&(&[u8; 32], &Channel<<SP::Target as SignerProvider>::Signer>)) -> bool + Copy>(&self, f: Fn) -> Vec<ChannelDetails> {
-               let mut res = Vec::new();
                // Allocate our best estimate of the number of channels we have in the `res`
                // Vec. Sadly the `short_to_chan_info` map doesn't cover channels without
                // a scid or a scid alias, and the `id_to_peer` shouldn't be used outside
                // of the ChannelMonitor handling. Therefore reallocations may still occur, but is
                // unlikely as the `short_to_chan_info` map often contains 2 entries for
                // the same channel.
-               res.reserve(self.short_to_chan_info.read().unwrap().len());
+               let mut res = Vec::with_capacity(self.short_to_chan_info.read().unwrap().len());
                {
                        let best_block_height = self.best_block.read().unwrap().height();
                        let per_peer_state = self.per_peer_state.read().unwrap();
@@ -1687,6 +1759,34 @@ where
                self.list_channels_with_filter(|&(_, ref channel)| channel.is_live())
        }
 
+       /// Returns in an undefined order recent payments that -- if not fulfilled -- have yet to find a
+       /// successful path, or have unresolved HTLCs.
+       ///
+       /// This can be useful for payments that may have been prepared, but ultimately not sent, as a
+       /// result of a crash. If such a payment exists, is not listed here, and an
+       /// [`Event::PaymentSent`] has not been received, you may consider resending the payment.
+       ///
+       /// [`Event::PaymentSent`]: events::Event::PaymentSent
+       pub fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
+               self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
+                       .filter_map(|(_, pending_outbound_payment)| match pending_outbound_payment {
+                               PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
+                                       Some(RecentPaymentDetails::Pending {
+                                               payment_hash: *payment_hash,
+                                               total_msat: *total_msat,
+                                       })
+                               },
+                               PendingOutboundPayment::Abandoned { payment_hash, .. } => {
+                                       Some(RecentPaymentDetails::Abandoned { payment_hash: *payment_hash })
+                               },
+                               PendingOutboundPayment::Fulfilled { payment_hash, .. } => {
+                                       Some(RecentPaymentDetails::Fulfilled { payment_hash: *payment_hash })
+                               },
+                               PendingOutboundPayment::Legacy { .. } => None
+                       })
+                       .collect()
+       }
+
        /// Helper function that issues the channel close events
        fn issue_channel_close_events(&self, channel: &Channel<<SP::Target as SignerProvider>::Signer>, closure_reason: ClosureReason) {
                let mut pending_events_lock = self.pending_events.lock().unwrap();
@@ -1710,34 +1810,34 @@ where
                let result: Result<(), _> = loop {
                        let per_peer_state = self.per_peer_state.read().unwrap();
 
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(APIError::APIMisuseError { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) });
-                       }
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
 
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan_entry) => {
-                                       let (shutdown_msg, monitor_update, htlcs) = chan_entry.get_mut().get_shutdown(&self.signer_provider, &peer_state.latest_features, target_feerate_sats_per_1000_weight)?;
+                                       let funding_txo_opt = chan_entry.get().get_funding_txo();
+                                       let their_features = &peer_state.latest_features;
+                                       let (shutdown_msg, mut monitor_update_opt, htlcs) = chan_entry.get_mut()
+                                               .get_shutdown(&self.signer_provider, their_features, target_feerate_sats_per_1000_weight)?;
                                        failed_htlcs = htlcs;
 
-                                       // Update the monitor with the shutdown script if necessary.
-                                       if let Some(monitor_update) = monitor_update {
-                                               let update_res = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), &monitor_update);
-                                               let (result, is_permanent) =
-                                                       handle_monitor_update_res!(self, update_res, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
-                                               if is_permanent {
-                                                       remove_channel!(self, chan_entry);
-                                                       break result;
-                                               }
-                                       }
-
+                                       // We can send the `shutdown` message before updating the `ChannelMonitor`
+                                       // here as we don't need the monitor update to complete until we send a
+                                       // `shutdown_signed`, which we'll delay if we're pending a monitor update.
                                        peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
                                                node_id: *counterparty_node_id,
-                                               msg: shutdown_msg
+                                               msg: shutdown_msg,
                                        });
 
+                                       // Update the monitor with the shutdown script if necessary.
+                                       if let Some(monitor_update) = monitor_update_opt.take() {
+                                               let update_id = monitor_update.update_id;
+                                               let update_res = self.chain_monitor.update_channel(funding_txo_opt.unwrap(), monitor_update);
+                                               break handle_new_monitor_update!(self, update_res, update_id, peer_state_lock, peer_state, chan_entry);
+                                       }
+
                                        if chan_entry.get().is_shutdown() {
                                                let channel = remove_channel!(self, chan_entry);
                                                if let Ok(channel_update) = self.get_channel_update_for_broadcast(&channel) {
@@ -1831,12 +1931,10 @@ where
        fn force_close_channel_with_peer(&self, channel_id: &[u8; 32], peer_node_id: &PublicKey, peer_msg: Option<&String>, broadcast: bool)
        -> Result<PublicKey, APIError> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(peer_node_id);
+               let peer_state_mutex = per_peer_state.get(peer_node_id)
+                       .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", peer_node_id) })?;
                let mut chan = {
-                       if let None = peer_state_mutex_opt {
-                               return Err(APIError::APIMisuseError{ err: format!("Can't find a peer matching the passed counterparty node_id {}", peer_node_id) });
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        if let hash_map::Entry::Occupied(chan) = peer_state.channel_by_id.entry(channel_id.clone()) {
                                if let Some(peer_msg) = peer_msg {
@@ -1852,7 +1950,7 @@ where
                log_error!(self.logger, "Force-closing channel {}", log_bytes!(channel_id[..]));
                self.finish_force_close_channel(chan.force_shutdown(broadcast));
                if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
-                       let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let mut peer_state = peer_state_mutex.lock().unwrap();
                        peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                msg: update
                        });
@@ -2139,7 +2237,7 @@ where
                                        let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = forwarding_chan_info_opt {
                                                let per_peer_state = self.per_peer_state.read().unwrap();
                                                let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
-                                               if let None = peer_state_mutex_opt {
+                                               if peer_state_mutex_opt.is_none() {
                                                        break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
                                                }
                                                let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
@@ -2253,7 +2351,9 @@ where
        /// public, and thus should be called whenever the result is going to be passed out in a
        /// [`MessageSendEvent::BroadcastChannelUpdate`] event.
        ///
-       /// May be called with peer_state already locked!
+       /// Note that in `internal_closing_signed`, this function is called without the `peer_state`
+       /// corresponding to the channel's counterparty locked, as the channel been removed from the
+       /// storage and the `peer_state` lock has been dropped.
        fn get_channel_update_for_broadcast(&self, chan: &Channel<<SP::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
                if !chan.should_announce() {
                        return Err(LightningError {
@@ -2272,7 +2372,10 @@ where
        /// is public (only returning an Err if the channel does not yet have an assigned short_id),
        /// and thus MUST NOT be called unless the recipient of the resulting message has already
        /// provided evidence that they know about the existence of the channel.
-       /// May be called with peer_state already locked!
+       ///
+       /// Note that through `internal_closing_signed`, this function is called without the
+       /// `peer_state`  corresponding to the channel's counterparty locked, as the channel been
+       /// removed from the storage and the `peer_state` lock has been dropped.
        fn get_channel_update_for_unicast(&self, chan: &Channel<<SP::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
                log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.channel_id()));
                let short_channel_id = match chan.get_short_channel_id().or(chan.latest_inbound_scid_alias()) {
@@ -2333,61 +2436,40 @@ where
                        };
 
                        let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(APIError::InvalidRoute{err: "No peer matching the path's first hop found!" });
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(&counterparty_node_id)
+                               .ok_or_else(|| APIError::ChannelUnavailable{err: "No peer matching the path's first hop found!".to_owned() })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        if let hash_map::Entry::Occupied(mut chan) = peer_state.channel_by_id.entry(id) {
-                               match {
-                                       if !chan.get().is_live() {
-                                               return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!".to_owned()});
-                                       }
-                                       break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
-                                               htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
-                                                       path: path.clone(),
-                                                       session_priv: session_priv.clone(),
-                                                       first_hop_htlc_msat: htlc_msat,
-                                                       payment_id,
-                                                       payment_secret: payment_secret.clone(),
-                                                       payment_params: payment_params.clone(),
-                                               }, onion_packet, &self.logger),
-                                               chan)
-                               } {
-                                       Some((update_add, commitment_signed, monitor_update)) => {
-                                               let update_err = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update);
-                                               let chan_id = chan.get().channel_id();
-                                               match (update_err,
-                                                       handle_monitor_update_res!(self, update_err, chan,
-                                                               RAACommitmentOrder::CommitmentFirst, false, true))
-                                               {
-                                                       (ChannelMonitorUpdateStatus::PermanentFailure, Err(e)) => break Err(e),
-                                                       (ChannelMonitorUpdateStatus::Completed, Ok(())) => {},
-                                                       (ChannelMonitorUpdateStatus::InProgress, Err(_)) => {
-                                                               // Note that MonitorUpdateInProgress here indicates (per function
-                                                               // docs) that we will resend the commitment update once monitor
-                                                               // updating completes. Therefore, we must return an error
-                                                               // indicating that it is unsafe to retry the payment wholesale,
-                                                               // which we do in the send_payment check for
-                                                               // MonitorUpdateInProgress, below.
-                                                               return Err(APIError::MonitorUpdateInProgress);
-                                                       },
-                                                       _ => unreachable!(),
+                               if !chan.get().is_live() {
+                                       return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected".to_owned()});
+                               }
+                               let funding_txo = chan.get().get_funding_txo().unwrap();
+                               let send_res = chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(),
+                                       htlc_cltv, HTLCSource::OutboundRoute {
+                                               path: path.clone(),
+                                               session_priv: session_priv.clone(),
+                                               first_hop_htlc_msat: htlc_msat,
+                                               payment_id,
+                                               payment_secret: payment_secret.clone(),
+                                               payment_params: payment_params.clone(),
+                                       }, onion_packet, &self.logger);
+                               match break_chan_entry!(self, send_res, chan) {
+                                       Some(monitor_update) => {
+                                               let update_id = monitor_update.update_id;
+                                               let update_res = self.chain_monitor.update_channel(funding_txo, monitor_update);
+                                               if let Err(e) = handle_new_monitor_update!(self, update_res, update_id, peer_state_lock, peer_state, chan) {
+                                                       break Err(e);
+                                               }
+                                               if update_res == ChannelMonitorUpdateStatus::InProgress {
+                                                       // Note that MonitorUpdateInProgress here indicates (per function
+                                                       // docs) that we will resend the commitment update once monitor
+                                                       // updating completes. Therefore, we must return an error
+                                                       // indicating that it is unsafe to retry the payment wholesale,
+                                                       // which we do in the send_payment check for
+                                                       // MonitorUpdateInProgress, below.
+                                                       return Err(APIError::MonitorUpdateInProgress);
                                                }
-
-                                               log_debug!(self.logger, "Sending payment along path resulted in a commitment_signed for channel {}", log_bytes!(chan_id));
-                                               peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
-                                                       node_id: path.first().unwrap().pubkey,
-                                                       updates: msgs::CommitmentUpdate {
-                                                               update_add_htlcs: vec![update_add],
-                                                               update_fulfill_htlcs: Vec::new(),
-                                                               update_fail_htlcs: Vec::new(),
-                                                               update_fail_malformed_htlcs: Vec::new(),
-                                                               update_fee: None,
-                                                               commitment_signed,
-                                                       },
-                                               });
                                        },
                                        None => { },
                                }
@@ -2411,14 +2493,19 @@ where
 
        /// Sends a payment along a given route.
        ///
-       /// Value parameters are provided via the last hop in route, see documentation for RouteHop
+       /// Value parameters are provided via the last hop in route, see documentation for [`RouteHop`]
        /// fields for more info.
        ///
+       /// May generate SendHTLCs message(s) event on success, which should be relayed (e.g. via
+       /// [`PeerManager::process_events`]).
+       ///
+       /// # Avoiding Duplicate Payments
+       ///
        /// If a pending payment is currently in-flight with the same [`PaymentId`] provided, this
        /// method will error with an [`APIError::InvalidRoute`]. Note, however, that once a payment
        /// is no longer pending (either via [`ChannelManager::abandon_payment`], or handling of an
-       /// [`Event::PaymentSent`]) LDK will not stop you from sending a second payment with the same
-       /// [`PaymentId`].
+       /// [`Event::PaymentSent`] or [`Event::PaymentFailed`]) LDK will not stop you from sending a
+       /// second payment with the same [`PaymentId`].
        ///
        /// Thus, in order to ensure duplicate payments are not sent, you should implement your own
        /// tracking of payments, including state to indicate once a payment has completed. Because you
@@ -2426,12 +2513,16 @@ where
        /// consider using the [`PaymentHash`] as the key for tracking payments. In that case, the
        /// [`PaymentId`] should be a copy of the [`PaymentHash`] bytes.
        ///
-       /// May generate SendHTLCs message(s) event on success, which should be relayed (e.g. via
-       /// [`PeerManager::process_events`]).
+       /// Additionally, in the scenario where we begin the process of sending a payment, but crash
+       /// before `send_payment` returns (or prior to [`ChannelMonitorUpdate`] persistence if you're
+       /// using [`ChannelMonitorUpdateStatus::InProgress`]), the payment may be lost on restart. See
+       /// [`ChannelManager::list_recent_payments`] for more information.
+       ///
+       /// # Possible Error States on [`PaymentSendFailure`]
        ///
        /// Each path may have a different return value, and PaymentSendValue may return a Vec with
        /// each entry matching the corresponding-index entry in the route paths, see
-       /// PaymentSendFailure for more info.
+       /// [`PaymentSendFailure`] for more info.
        ///
        /// In general, a path may raise:
        ///  * [`APIError::InvalidRoute`] when an invalid route or forwarding parameter (cltv_delta, fee,
@@ -2446,18 +2537,22 @@ where
        /// irrevocably committed to on our end. In such a case, do NOT retry the payment with a
        /// different route unless you intend to pay twice!
        ///
-       /// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
-       /// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
-       /// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
-       /// must not contain multiple paths as multi-path payments require a recipient-provided
-       /// payment_secret.
+       /// # A caution on `payment_secret`
+       ///
+       /// `payment_secret` is unrelated to `payment_hash` (or [`PaymentPreimage`]) and exists to
+       /// authenticate the sender to the recipient and prevent payment-probing (deanonymization)
+       /// attacks. For newer nodes, it will be provided to you in the invoice. If you do not have one,
+       /// the [`Route`] must not contain multiple paths as multi-path payments require a
+       /// recipient-provided `payment_secret`.
        ///
-       /// If a payment_secret *is* provided, we assume that the invoice had the payment_secret feature
-       /// bit set (either as required or as available). If multiple paths are present in the Route,
-       /// we assume the invoice had the basic_mpp feature set.
+       /// If a `payment_secret` *is* provided, we assume that the invoice had the payment_secret
+       /// feature bit set (either as required or as available). If multiple paths are present in the
+       /// [`Route`], we assume the invoice had the basic_mpp feature set.
        ///
        /// [`Event::PaymentSent`]: events::Event::PaymentSent
+       /// [`Event::PaymentFailed`]: events::Event::PaymentFailed
        /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events
+       /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress
        pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, payment_id: PaymentId) -> Result<(), PaymentSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
                self.pending_outbound_payments
@@ -2468,12 +2563,13 @@ where
 
        /// 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> {
+       pub fn send_payment_with_retry(&self, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<(), RetryableSendFailure> {
                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,
+                               &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(),
+                               &self.entropy_source, &self.node_signer, best_block_height, &self.logger,
+                               &self.pending_events,
                                |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))
        }
@@ -2489,52 +2585,29 @@ 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, Retry::Attempts(0), &self.entropy_source, best_block_height)
+               self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, payment_secret, payment_id, route, None, &self.entropy_source, best_block_height)
        }
 
 
-       /// Retries a payment along the given [`Route`].
-       ///
-       /// Errors returned are a superset of those returned from [`send_payment`], so see
-       /// [`send_payment`] documentation for more details on errors. This method will also error if the
-       /// retry amount puts the payment more than 10% over the payment's total amount, if the payment
-       /// for the given `payment_id` cannot be found (likely due to timeout or success), or if
-       /// further retries have been disabled with [`abandon_payment`].
-       ///
-       /// [`send_payment`]: [`ChannelManager::send_payment`]
-       /// [`abandon_payment`]: [`ChannelManager::abandon_payment`]
-       pub fn retry_payment(&self, route: &Route, payment_id: PaymentId) -> Result<(), PaymentSendFailure> {
-               let best_block_height = self.best_block.read().unwrap().height();
-               self.pending_outbound_payments.retry_payment_with_route(route, payment_id, &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))
-       }
-
-       /// Signals that no further retries for the given payment will occur.
+       /// Signals that no further retries for the given payment should occur. Useful if you have a
+       /// pending outbound payment with retries remaining, but wish to stop retrying the payment before
+       /// retries are exhausted.
        ///
-       /// After this method returns, no future calls to [`retry_payment`] for the given `payment_id`
-       /// are allowed. If no [`Event::PaymentFailed`] event had been generated before, one will be
-       /// generated as soon as there are no remaining pending HTLCs for this payment.
+       /// If no [`Event::PaymentFailed`] event had been generated before, one will be generated as soon
+       /// as there are no remaining pending HTLCs for this payment.
        ///
        /// Note that calling this method does *not* prevent a payment from succeeding. You must still
        /// wait until you receive either a [`Event::PaymentFailed`] or [`Event::PaymentSent`] event to
        /// determine the ultimate status of a payment.
        ///
        /// If an [`Event::PaymentFailed`] event is generated and we restart without this
-       /// [`ChannelManager`] having been persisted, the payment may still be in the pending state
-       /// upon restart. This allows further calls to [`retry_payment`] (and requiring a second call
-       /// to [`abandon_payment`] to mark the payment as failed again). Otherwise, future calls to
-       /// [`retry_payment`] will fail with [`PaymentSendFailure::ParameterError`].
+       /// [`ChannelManager`] having been persisted, another [`Event::PaymentFailed`] may be generated.
        ///
-       /// [`abandon_payment`]: Self::abandon_payment
-       /// [`retry_payment`]: Self::retry_payment
        /// [`Event::PaymentFailed`]: events::Event::PaymentFailed
        /// [`Event::PaymentSent`]: events::Event::PaymentSent
        pub fn abandon_payment(&self, payment_id: PaymentId) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
-               if let Some(payment_failed_ev) = self.pending_outbound_payments.abandon_payment(payment_id) {
-                       self.pending_events.lock().unwrap().push(payment_failed_ev);
-               }
+               self.pending_outbound_payments.abandon_payment(payment_id, &self.pending_events);
        }
 
        /// Send a spontaneous payment, which is a payment that does not require the recipient to have
@@ -2554,7 +2627,26 @@ where
        /// [`send_payment`]: Self::send_payment
        pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId) -> Result<PaymentHash, PaymentSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
-               self.pending_outbound_payments.send_spontaneous_payment(route, payment_preimage, payment_id, &self.entropy_source, &self.node_signer, best_block_height,
+               self.pending_outbound_payments.send_spontaneous_payment_with_route(
+                       route, payment_preimage, payment_id, &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))
+       }
+
+       /// Similar to [`ChannelManager::send_spontaneous_payment`], but will automatically find a route
+       /// based on `route_params` and retry failed payment paths based on `retry_strategy`.
+       ///
+       /// See [`PaymentParameters::for_keysend`] for help in constructing `route_params` for spontaneous
+       /// payments.
+       ///
+       /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend
+       pub fn send_spontaneous_payment_with_retry(&self, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<PaymentHash, RetryableSendFailure> {
+               let best_block_height = self.best_block.read().unwrap().height();
+               self.pending_outbound_payments.send_spontaneous_payment(payment_preimage, 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,
+                       &self.logger, &self.pending_events,
                        |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))
        }
@@ -2582,12 +2674,10 @@ where
                &self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, funding_transaction: Transaction, find_funding_output: FundingOutput
        ) -> Result<(), APIError> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })
-               }
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
 
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                let (chan, msg) = {
                        let (res, chan) = {
@@ -2609,7 +2699,7 @@ where
                                        (chan, funding_msg)
                                },
                                Err(_) => { return Err(APIError::ChannelUnavailable {
-                                       err: "Error deriving keys or signing initial commitment transactions - either our RNG or our counterparty's RNG is broken or the Signer refused to sign".to_owned()
+                                       err: "Signer refused to sign the initial commitment transaction".to_owned()
                                }) },
                        }
                };
@@ -2753,11 +2843,9 @@ where
                        &self.total_consistency_lock, &self.persistence_notifier,
                );
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(APIError::APIMisuseError{ err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) });
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                for channel_id in channel_ids {
                        if !peer_state.channel_by_id.contains_key(channel_id) {
@@ -2810,24 +2898,22 @@ where
 
                let next_hop_scid = {
                        let peer_state_lock = self.per_peer_state.read().unwrap();
-                       if let Some(peer_state_mutex) = peer_state_lock.get(&next_node_id) {
-                               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
-                               let peer_state = &mut *peer_state_lock;
-                               match peer_state.channel_by_id.get(next_hop_channel_id) {
-                                       Some(chan) => {
-                                               if !chan.is_usable() {
-                                                       return Err(APIError::ChannelUnavailable {
-                                                               err: format!("Channel with id {} not fully established", log_bytes!(*next_hop_channel_id))
-                                                       })
-                                               }
-                                               chan.get_short_channel_id().unwrap_or(chan.outbound_scid_alias())
-                                       },
-                                       None => return Err(APIError::ChannelUnavailable {
-                                               err: format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!(*next_hop_channel_id), next_node_id)
-                                       })
-                               }
-                       } else {
-                               return Err(APIError::APIMisuseError{ err: format!("Can't find a peer matching the passed counterparty node_id {}", next_node_id) });
+                       let peer_state_mutex = peer_state_lock.get(&next_node_id)
+                               .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", next_node_id) })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
+                       let peer_state = &mut *peer_state_lock;
+                       match peer_state.channel_by_id.get(next_hop_channel_id) {
+                               Some(chan) => {
+                                       if !chan.is_usable() {
+                                               return Err(APIError::ChannelUnavailable {
+                                                       err: format!("Channel with id {} not fully established", log_bytes!(*next_hop_channel_id))
+                                               })
+                                       }
+                                       chan.get_short_channel_id().unwrap_or(chan.outbound_scid_alias())
+                               },
+                               None => return Err(APIError::ChannelUnavailable {
+                                       err: format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!(*next_hop_channel_id), next_node_id)
+                               })
                        }
                };
 
@@ -3007,7 +3093,7 @@ where
                                        };
                                        let per_peer_state = self.per_peer_state.read().unwrap();
                                        let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
-                                       if let None = peer_state_mutex_opt {
+                                       if peer_state_mutex_opt.is_none() {
                                                forwarding_channel_not_found!();
                                                continue;
                                        }
@@ -3294,7 +3380,8 @@ 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,
+                       || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height,
+                       &self.pending_events, &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));
 
@@ -3399,6 +3486,7 @@ where
        ///    the channel.
        ///  * Expiring a channel's previous `ChannelConfig` if necessary to only allow forwarding HTLCs
        ///    with the current `ChannelConfig`.
+       ///  * Removing peers which have disconnected but and no longer have any channels.
        ///
        /// Note that this may cause reentrancy through `chain::Watch::update_channel` calls or feerate
        /// estimate fetches.
@@ -3411,19 +3499,21 @@ where
 
                        let mut handle_errors: Vec<(Result<(), _>, _)> = Vec::new();
                        let mut timed_out_mpp_htlcs = Vec::new();
+                       let mut pending_peers_awaiting_removal = Vec::new();
                        {
                                let per_peer_state = self.per_peer_state.read().unwrap();
                                for (counterparty_node_id, peer_state_mutex) in per_peer_state.iter() {
                                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                        let peer_state = &mut *peer_state_lock;
                                        let pending_msg_events = &mut peer_state.pending_msg_events;
+                                       let counterparty_node_id = *counterparty_node_id;
                                        peer_state.channel_by_id.retain(|chan_id, chan| {
                                                let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate);
                                                if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
 
                                                if let Err(e) = chan.timer_check_closing_negotiation_progress() {
                                                        let (needs_close, err) = convert_chan_err!(self, e, chan, chan_id);
-                                                       handle_errors.push((Err(err), *counterparty_node_id));
+                                                       handle_errors.push((Err(err), counterparty_node_id));
                                                        if needs_close { return false; }
                                                }
 
@@ -3457,6 +3547,36 @@ where
 
                                                true
                                        });
+                                       if peer_state.ok_to_remove(true) {
+                                               pending_peers_awaiting_removal.push(counterparty_node_id);
+                                       }
+                               }
+                       }
+
+                       // When a peer disconnects but still has channels, the peer's `peer_state` entry in the
+                       // `per_peer_state` is not removed by the `peer_disconnected` function. If the channels
+                       // of to that peer is later closed while still being disconnected (i.e. force closed),
+                       // we therefore need to remove the peer from `peer_state` separately.
+                       // To avoid having to take the `per_peer_state` `write` lock once the channels are
+                       // closed, we instead remove such peers awaiting removal here on a timer, to limit the
+                       // negative effects on parallelism as much as possible.
+                       if pending_peers_awaiting_removal.len() > 0 {
+                               let mut per_peer_state = self.per_peer_state.write().unwrap();
+                               for counterparty_node_id in pending_peers_awaiting_removal {
+                                       match per_peer_state.entry(counterparty_node_id) {
+                                               hash_map::Entry::Occupied(entry) => {
+                                                       // Remove the entry if the peer is still disconnected and we still
+                                                       // have no channels to the peer.
+                                                       let remove_entry = {
+                                                               let peer_state = entry.get().lock().unwrap();
+                                                               peer_state.ok_to_remove(true)
+                                                       };
+                                                       if remove_entry {
+                                                               entry.remove_entry();
+                                                       }
+                                               },
+                                               hash_map::Entry::Vacant(_) => { /* The PeerState has already been removed */ }
+                                       }
                                }
                        }
 
@@ -3632,17 +3752,12 @@ 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(any(feature = "_test_utils", test))]
-               {
-                       // Ensure that no peer state channel storage lock is not held when calling this
-                       // function.
-                       // This ensures that future code doesn't introduce a lock_order requirement for
-                       // `forward_htlcs` to be locked after the `per_peer_state` peer locks, which calling
-                       // 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() {
-                               debug_assert!(peer.try_lock().is_ok());
-                       }
+               // Ensure that no peer state channel storage lock is held when calling this function.
+               // This ensures that future code doesn't introduce a lock-order requirement for
+               // `forward_htlcs` to be locked after the `per_peer_state` peer locks, which calling
+               // this function with any `per_peer_state` peer lock acquired would.
+               for (_, peer) in self.per_peer_state.read().unwrap().iter() {
+                       debug_assert_ne!(peer.held_by_thread(), LockHeldState::HeldByThread);
                }
 
                //TODO: There is a timing attack here where if a node fails an HTLC back to us they can
@@ -3655,16 +3770,19 @@ where
                // being fully configured. See the docs for `ChannelManagerReadArgs` for more.
                match source {
                        HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, ref payment_params, .. } => {
-                               self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path, session_priv, payment_id, payment_params, self.probing_cookie_secret, &self.secp_ctx, &self.pending_events, &self.logger);
+                               if self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
+                                       session_priv, payment_id, payment_params, self.probing_cookie_secret, &self.secp_ctx,
+                                       &self.pending_events, &self.logger)
+                               { self.push_pending_forwards_ev(); }
                        },
                        HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint }) => {
                                log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with {:?}", log_bytes!(payment_hash.0), onion_error);
                                let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret);
 
-                               let mut forward_event = None;
+                               let mut push_forward_ev = false;
                                let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
                                if forward_htlcs.is_empty() {
-                                       forward_event = Some(Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS));
+                                       push_forward_ev = true;
                                }
                                match forward_htlcs.entry(*short_channel_id) {
                                        hash_map::Entry::Occupied(mut entry) => {
@@ -3675,12 +3793,8 @@ where
                                        }
                                }
                                mem::drop(forward_htlcs);
+                               if push_forward_ev { self.push_pending_forwards_ev(); }
                                let mut pending_events = self.pending_events.lock().unwrap();
-                               if let Some(time) = forward_event {
-                                       pending_events.push(events::Event::PendingHTLCsForwardable {
-                                               time_forwardable: time
-                                       });
-                               }
                                pending_events.push(events::Event::HTLCHandlingFailed {
                                        prev_channel_id: outpoint.to_channel_id(),
                                        failed_next_destination: destination,
@@ -3757,7 +3871,7 @@ where
                let mut expected_amt_msat = None;
                let mut valid_mpp = true;
                let mut errs = Vec::new();
-               let mut per_peer_state = Some(self.per_peer_state.read().unwrap());
+               let per_peer_state = self.per_peer_state.read().unwrap();
                for htlc in sources.iter() {
                        let (counterparty_node_id, chan_id) = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
                                Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()),
@@ -3767,16 +3881,16 @@ where
                                }
                        };
 
-                       if let None = per_peer_state.as_ref().unwrap().get(&counterparty_node_id) {
+                       let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
+                       if peer_state_mutex_opt.is_none() {
                                valid_mpp = false;
                                break;
                        }
 
-                       let peer_state_mutex = per_peer_state.as_ref().unwrap().get(&counterparty_node_id).unwrap();
-                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
+                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
 
-                       if let None = peer_state.channel_by_id.get(&chan_id) {
+                       if peer_state.channel_by_id.get(&chan_id).is_none() {
                                valid_mpp = false;
                                break;
                        }
@@ -3802,14 +3916,13 @@ where
 
                        claimable_amt_msat += htlc.value;
                }
+               mem::drop(per_peer_state);
                if sources.is_empty() || expected_amt_msat.is_none() {
-                       mem::drop(per_peer_state);
                        self.claimable_payments.lock().unwrap().pending_claiming_payments.remove(&payment_hash);
                        log_info!(self.logger, "Attempted to claim an incomplete payment which no longer had any available HTLCs!");
                        return;
                }
                if claimable_amt_msat != expected_amt_msat.unwrap() {
-                       mem::drop(per_peer_state);
                        self.claimable_payments.lock().unwrap().pending_claiming_payments.remove(&payment_hash);
                        log_info!(self.logger, "Attempted to claim an incomplete payment, expected {} msat, had {} available to claim.",
                                expected_amt_msat.unwrap(), claimable_amt_msat);
@@ -3817,8 +3930,7 @@ where
                }
                if valid_mpp {
                        for htlc in sources.drain(..) {
-                               if per_peer_state.is_none() { per_peer_state = Some(self.per_peer_state.read().unwrap()); }
-                               if let Err((pk, err)) = self.claim_funds_from_hop(per_peer_state.take().unwrap(),
+                               if let Err((pk, err)) = self.claim_funds_from_hop(
                                        htlc.prev_hop, payment_preimage,
                                        |_| Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }))
                                {
@@ -3830,7 +3942,6 @@ where
                                }
                        }
                }
-               mem::drop(per_peer_state);
                if !valid_mpp {
                        for htlc in sources.drain(..) {
                                let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec();
@@ -3851,124 +3962,74 @@ where
        }
 
        fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
-               per_peer_state_lock: RwLockReadGuard<HashMap<PublicKey, Mutex<PeerState<<SP::Target as SignerProvider>::Signer>>>>,
                prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
        -> Result<(), (PublicKey, MsgHandleErrInternal)> {
                //TODO: Delay the claimed_funds relaying just like we do outbound relay!
 
+               let per_peer_state = self.per_peer_state.read().unwrap();
                let chan_id = prev_hop.outpoint.to_channel_id();
-
                let counterparty_node_id_opt = match self.short_to_chan_info.read().unwrap().get(&prev_hop.short_channel_id) {
                        Some((cp_id, _dup_chan_id)) => Some(cp_id.clone()),
                        None => None
                };
 
-               let (found_channel, mut peer_state_opt) = if counterparty_node_id_opt.is_some() && per_peer_state_lock.get(&counterparty_node_id_opt.unwrap()).is_some() {
-                       let peer_mutex = per_peer_state_lock.get(&counterparty_node_id_opt.unwrap()).unwrap();
-                       let peer_state = peer_mutex.lock().unwrap();
-                       let found_channel = peer_state.channel_by_id.contains_key(&chan_id);
-                       (found_channel, Some(peer_state))
-               }  else { (false, None) };
+               let mut peer_state_opt = counterparty_node_id_opt.as_ref().map(
+                       |counterparty_node_id| per_peer_state.get(counterparty_node_id).map(
+                               |peer_mutex| peer_mutex.lock().unwrap()
+                       )
+               ).unwrap_or(None);
 
-               if found_channel {
-                       let peer_state = &mut *peer_state_opt.as_mut().unwrap();
+               if let Some(mut peer_state_lock) = peer_state_opt.take() {
+                       let peer_state = &mut *peer_state_lock;
                        if let hash_map::Entry::Occupied(mut chan) = peer_state.channel_by_id.entry(chan_id) {
                                let counterparty_node_id = chan.get().get_counterparty_node_id();
-                               match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
-                                       Ok(msgs_monitor_option) => {
-                                               if let UpdateFulfillCommitFetch::NewClaim { msgs, htlc_value_msat, monitor_update } = msgs_monitor_option {
-                                                       match self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update) {
-                                                               ChannelMonitorUpdateStatus::Completed => {},
-                                                               e => {
-                                                                       log_given_level!(self.logger, if e == ChannelMonitorUpdateStatus::PermanentFailure { Level::Error } else { Level::Debug },
-                                                                               "Failed to update channel monitor with preimage {:?}: {:?}",
-                                                                               payment_preimage, e);
-                                                                       let err = handle_monitor_update_res!(self, e, chan, RAACommitmentOrder::CommitmentFirst, false, msgs.is_some()).unwrap_err();
-                                                                       mem::drop(peer_state_opt);
-                                                                       mem::drop(per_peer_state_lock);
-                                                                       self.handle_monitor_update_completion_actions(completion_action(Some(htlc_value_msat)));
-                                                                       return Err((counterparty_node_id, err));
-                                                               }
-                                                       }
-                                                       if let Some((msg, commitment_signed)) = msgs {
-                                                               log_debug!(self.logger, "Claiming funds for HTLC with preimage {} resulted in a commitment_signed for channel {}",
-                                                                       log_bytes!(payment_preimage.0), log_bytes!(chan.get().channel_id()));
-                                                               peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
-                                                                       node_id: counterparty_node_id,
-                                                                       updates: msgs::CommitmentUpdate {
-                                                                               update_add_htlcs: Vec::new(),
-                                                                               update_fulfill_htlcs: vec![msg],
-                                                                               update_fail_htlcs: Vec::new(),
-                                                                               update_fail_malformed_htlcs: Vec::new(),
-                                                                               update_fee: None,
-                                                                               commitment_signed,
-                                                                       }
-                                                               });
-                                                       }
-                                                       mem::drop(peer_state_opt);
-                                                       mem::drop(per_peer_state_lock);
-                                                       self.handle_monitor_update_completion_actions(completion_action(Some(htlc_value_msat)));
-                                                       Ok(())
-                                               } else {
-                                                       Ok(())
-                                               }
-                                       },
-                                       Err((e, monitor_update)) => {
-                                               match self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update) {
-                                                       ChannelMonitorUpdateStatus::Completed => {},
-                                                       e => {
-                                                               // TODO: This needs to be handled somehow - if we receive a monitor update
-                                                               // with a preimage we *must* somehow manage to propagate it to the upstream
-                                                               // channel, or we must have an ability to receive the same update and try
-                                                               // again on restart.
-                                                               log_given_level!(self.logger, if e == ChannelMonitorUpdateStatus::PermanentFailure { Level::Error } else { Level::Info },
-                                                                       "Failed to update channel monitor with preimage {:?} immediately prior to force-close: {:?}",
-                                                                       payment_preimage, e);
-                                                       },
-                                               }
-                                               let (drop, res) = convert_chan_err!(self, e, chan.get_mut(), &chan_id);
-                                               if drop {
-                                                       chan.remove_entry();
-                                               }
-                                               mem::drop(peer_state_opt);
-                                               mem::drop(per_peer_state_lock);
-                                               self.handle_monitor_update_completion_actions(completion_action(None));
-                                               Err((counterparty_node_id, res))
-                                       },
+                               let fulfill_res = chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger);
+
+                               if let UpdateFulfillCommitFetch::NewClaim { htlc_value_msat, monitor_update } = fulfill_res {
+                                       if let Some(action) = completion_action(Some(htlc_value_msat)) {
+                                               log_trace!(self.logger, "Tracking monitor update completion action for channel {}: {:?}",
+                                                       log_bytes!(chan_id), action);
+                                               peer_state.monitor_update_blocked_actions.entry(chan_id).or_insert(Vec::new()).push(action);
+                                       }
+                                       let update_id = monitor_update.update_id;
+                                       let update_res = self.chain_monitor.update_channel(prev_hop.outpoint, monitor_update);
+                                       let res = handle_new_monitor_update!(self, update_res, update_id, peer_state_lock,
+                                               peer_state, chan);
+                                       if let Err(e) = res {
+                                               // TODO: This is a *critical* error - we probably updated the outbound edge
+                                               // of the HTLC's monitor with a preimage. We should retry this monitor
+                                               // update over and over again until morale improves.
+                                               log_error!(self.logger, "Failed to update channel monitor with preimage {:?}", payment_preimage);
+                                               return Err((counterparty_node_id, e));
+                                       }
                                }
-                       } else {
-                               // We've held the peer_state mutex since finding the channel and setting
-                               // found_channel to true, so the channel can't have been dropped.
-                               unreachable!()
-                       }
-               } else {
-                       let preimage_update = ChannelMonitorUpdate {
-                               update_id: CLOSED_CHANNEL_UPDATE_ID,
-                               updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
-                                       payment_preimage,
-                               }],
-                       };
-                       // We update the ChannelMonitor on the backward link, after
-                       // receiving an `update_fulfill_htlc` from the forward link.
-                       let update_res = self.chain_monitor.update_channel(prev_hop.outpoint, &preimage_update);
-                       if update_res != ChannelMonitorUpdateStatus::Completed {
-                               // TODO: This needs to be handled somehow - if we receive a monitor update
-                               // with a preimage we *must* somehow manage to propagate it to the upstream
-                               // channel, or we must have an ability to receive the same event and try
-                               // again on restart.
-                               log_error!(self.logger, "Critical error: failed to update channel monitor with preimage {:?}: {:?}",
-                                       payment_preimage, update_res);
+                               return Ok(());
                        }
-                       mem::drop(peer_state_opt);
-                       mem::drop(per_peer_state_lock);
-                       // Note that we do process the completion action here. This totally could be a
-                       // duplicate claim, but we have no way of knowing without interrogating the
-                       // `ChannelMonitor` we've provided the above update to. Instead, note that `Event`s are
-                       // generally always allowed to be duplicative (and it's specifically noted in
-                       // `PaymentForwarded`).
-                       self.handle_monitor_update_completion_actions(completion_action(None));
-                       Ok(())
                }
+               let preimage_update = ChannelMonitorUpdate {
+                       update_id: CLOSED_CHANNEL_UPDATE_ID,
+                       updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
+                               payment_preimage,
+                       }],
+               };
+               // We update the ChannelMonitor on the backward link, after
+               // receiving an `update_fulfill_htlc` from the forward link.
+               let update_res = self.chain_monitor.update_channel(prev_hop.outpoint, &preimage_update);
+               if update_res != ChannelMonitorUpdateStatus::Completed {
+                       // TODO: This needs to be handled somehow - if we receive a monitor update
+                       // with a preimage we *must* somehow manage to propagate it to the upstream
+                       // channel, or we must have an ability to receive the same event and try
+                       // again on restart.
+                       log_error!(self.logger, "Critical error: failed to update channel monitor with preimage {:?}: {:?}",
+                               payment_preimage, update_res);
+               }
+               // Note that we do process the completion action here. This totally could be a
+               // duplicate claim, but we have no way of knowing without interrogating the
+               // `ChannelMonitor` we've provided the above update to. Instead, note that `Event`s are
+               // generally always allowed to be duplicative (and it's specifically noted in
+               // `PaymentForwarded`).
+               self.handle_monitor_update_completion_actions(completion_action(None));
+               Ok(())
        }
 
        fn finalize_claims(&self, sources: Vec<HTLCSource>) {
@@ -3982,7 +4043,7 @@ where
                        },
                        HTLCSource::PreviousHopData(hop_data) => {
                                let prev_outpoint = hop_data.outpoint;
-                               let res = self.claim_funds_from_hop(self.per_peer_state.read().unwrap(), hop_data, payment_preimage,
+                               let res = self.claim_funds_from_hop(hop_data, payment_preimage,
                                        |htlc_claim_value_msat| {
                                                if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat {
                                                        let fee_earned_msat = if let Some(claimed_htlc_value) = htlc_claim_value_msat {
@@ -4039,6 +4100,14 @@ where
                pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option<Transaction>,
                channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>)
        -> Option<(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)> {
+               log_trace!(self.logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {}broadcasting funding, {} channel ready, {} announcement",
+                       log_bytes!(channel.channel_id()),
+                       if raa.is_some() { "an" } else { "no" },
+                       if commitment_update.is_some() { "a" } else { "no" }, pending_forwards.len(),
+                       if funding_broadcastable.is_some() { "" } else { "not " },
+                       if channel_ready.is_some() { "sending" } else { "without" },
+                       if announcement_sigs.is_some() { "sending" } else { "without" });
+
                let mut htlc_forwards = None;
 
                let counterparty_node_id = channel.get_counterparty_node_id();
@@ -4097,65 +4166,36 @@ where
        fn channel_monitor_updated(&self, funding_txo: &OutPoint, highest_applied_update_id: u64, counterparty_node_id: Option<&PublicKey>) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
 
-               let htlc_forwards;
-               let (mut pending_failures, finalized_claims, counterparty_node_id) = {
-                       let counterparty_node_id = match counterparty_node_id {
-                               Some(cp_id) => cp_id.clone(),
-                               None => {
-                                       // TODO: Once we can rely on the counterparty_node_id from the
-                                       // monitor event, this and the id_to_peer map should be removed.
-                                       let id_to_peer = self.id_to_peer.lock().unwrap();
-                                       match id_to_peer.get(&funding_txo.to_channel_id()) {
-                                               Some(cp_id) => cp_id.clone(),
-                                               None => return,
-                                       }
-                               }
-                       };
-                       let per_peer_state = self.per_peer_state.read().unwrap();
-                       let mut peer_state_lock;
-                       let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
-                       if let None = peer_state_mutex_opt { return }
-                       peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
-                       let peer_state = &mut *peer_state_lock;
-                       let mut channel = {
-                               match peer_state.channel_by_id.entry(funding_txo.to_channel_id()){
-                                       hash_map::Entry::Occupied(chan) => chan,
-                                       hash_map::Entry::Vacant(_) => return,
+               let counterparty_node_id = match counterparty_node_id {
+                       Some(cp_id) => cp_id.clone(),
+                       None => {
+                               // TODO: Once we can rely on the counterparty_node_id from the
+                               // monitor event, this and the id_to_peer map should be removed.
+                               let id_to_peer = self.id_to_peer.lock().unwrap();
+                               match id_to_peer.get(&funding_txo.to_channel_id()) {
+                                       Some(cp_id) => cp_id.clone(),
+                                       None => return,
                                }
-                       };
-                       if !channel.get().is_awaiting_monitor_update() || channel.get().get_latest_monitor_update_id() != highest_applied_update_id {
-                               return;
                        }
-
-                       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
-                               // channel_update later through the announcement_signatures process for public
-                               // channels, but there's no reason not to just inform our counterparty of our fees
-                               // now.
-                               if let Ok(msg) = self.get_channel_update_for_unicast(channel.get()) {
-                                       Some(events::MessageSendEvent::SendChannelUpdate {
-                                               node_id: channel.get().get_counterparty_node_id(),
-                                               msg,
-                                       })
-                               } else { None }
-                       } else { None };
-                       htlc_forwards = self.handle_channel_resumption(&mut peer_state.pending_msg_events, channel.get_mut(), updates.raa, updates.commitment_update, updates.order, updates.accepted_htlcs, updates.funding_broadcastable, updates.channel_ready, updates.announcement_sigs);
-                       if let Some(upd) = channel_update {
-                               peer_state.pending_msg_events.push(upd);
+               };
+               let per_peer_state = self.per_peer_state.read().unwrap();
+               let mut peer_state_lock;
+               let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
+               if peer_state_mutex_opt.is_none() { return }
+               peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state = &mut *peer_state_lock;
+               let mut channel = {
+                       match peer_state.channel_by_id.entry(funding_txo.to_channel_id()){
+                               hash_map::Entry::Occupied(chan) => chan,
+                               hash_map::Entry::Vacant(_) => return,
                        }
-
-                       (updates.failed_htlcs, updates.finalized_claimed_htlcs, counterparty_node_id)
                };
-               if let Some(forwards) = htlc_forwards {
-                       self.forward_htlcs(&mut [forwards][..]);
-               }
-               self.finalize_claims(finalized_claims);
-               for failure in pending_failures.drain(..) {
-                       let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id: funding_txo.to_channel_id() };
-                       self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver);
+               log_trace!(self.logger, "ChannelMonitor updated to {}. Current highest is {}",
+                       highest_applied_update_id, channel.get().get_latest_monitor_update_id());
+               if !channel.get().is_awaiting_monitor_update() || channel.get().get_latest_monitor_update_id() != highest_applied_update_id {
+                       return;
                }
+               handle_monitor_update_completion!(self, highest_applied_update_id, peer_state_lock, peer_state, channel.get_mut());
        }
 
        /// Accepts a request to open a channel after a [`Event::OpenChannelRequest`].
@@ -4203,13 +4243,13 @@ where
        fn do_accept_inbound_channel(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, accept_0conf: bool, user_channel_id: u128) -> Result<(), APIError> {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
 
+               let peers_without_funded_channels = self.peers_without_funded_channels(|peer| !peer.channel_by_id.is_empty());
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(APIError::APIMisuseError { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) });
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
+               let is_only_peer_channel = peer_state.channel_by_id.len() == 1;
                match peer_state.channel_by_id.entry(temporary_channel_id.clone()) {
                        hash_map::Entry::Occupied(mut channel) => {
                                if !channel.get().inbound_is_awaiting_accept() {
@@ -4227,6 +4267,21 @@ where
                                        peer_state.pending_msg_events.push(send_msg_err_event);
                                        let _ = remove_channel!(self, channel);
                                        return Err(APIError::APIMisuseError { err: "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned() });
+                               } else {
+                                       // If this peer already has some channels, a new channel won't increase our number of peers
+                                       // with unfunded channels, so as long as we aren't over the maximum number of unfunded
+                                       // channels per-peer we can accept channels from a peer with existing ones.
+                                       if is_only_peer_channel && peers_without_funded_channels >= MAX_UNFUNDED_CHANNEL_PEERS {
+                                               let send_msg_err_event = events::MessageSendEvent::HandleError {
+                                                       node_id: channel.get().get_counterparty_node_id(),
+                                                       action: msgs::ErrorAction::SendErrorMessage{
+                                                               msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "Have too many peers with unfunded channels, not accepting new ones".to_owned(), }
+                                                       }
+                                               };
+                                               peer_state.pending_msg_events.push(send_msg_err_event);
+                                               let _ = remove_channel!(self, channel);
+                                               return Err(APIError::APIMisuseError { err: "Too many peers with unfunded channels, refusing to accept new ones".to_owned() });
+                                       }
                                }
 
                                peer_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
@@ -4241,6 +4296,43 @@ where
                Ok(())
        }
 
+       /// Gets the number of peers which match the given filter and do not have any funded, outbound,
+       /// or 0-conf channels.
+       ///
+       /// The filter is called for each peer and provided with the number of unfunded, inbound, and
+       /// non-0-conf channels we have with the peer.
+       fn peers_without_funded_channels<Filter>(&self, maybe_count_peer: Filter) -> usize
+       where Filter: Fn(&PeerState<<SP::Target as SignerProvider>::Signer>) -> bool {
+               let mut peers_without_funded_channels = 0;
+               let best_block_height = self.best_block.read().unwrap().height();
+               {
+                       let peer_state_lock = self.per_peer_state.read().unwrap();
+                       for (_, peer_mtx) in peer_state_lock.iter() {
+                               let peer = peer_mtx.lock().unwrap();
+                               if !maybe_count_peer(&*peer) { continue; }
+                               let num_unfunded_channels = Self::unfunded_channel_count(&peer, best_block_height);
+                               if num_unfunded_channels == peer.channel_by_id.len() {
+                                       peers_without_funded_channels += 1;
+                               }
+                       }
+               }
+               return peers_without_funded_channels;
+       }
+
+       fn unfunded_channel_count(
+               peer: &PeerState<<SP::Target as SignerProvider>::Signer>, best_block_height: u32
+       ) -> usize {
+               let mut num_unfunded_channels = 0;
+               for (_, chan) in peer.channel_by_id.iter() {
+                       if !chan.is_outbound() && chan.minimum_depth().unwrap_or(1) != 0 &&
+                               chan.get_funding_tx_confirmations(best_block_height) == 0
+                       {
+                               num_unfunded_channels += 1;
+                       }
+               }
+               num_unfunded_channels
+       }
+
        fn internal_open_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> {
                if msg.chain_hash != self.genesis_hash {
                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone()));
@@ -4253,18 +4345,44 @@ where
                let mut random_bytes = [0u8; 16];
                random_bytes.copy_from_slice(&self.entropy_source.get_secure_random_bytes()[..16]);
                let user_channel_id = u128::from_be_bytes(random_bytes);
-
                let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
+
+               // Get the number of peers with channels, but without funded ones. We don't care too much
+               // about peers that never open a channel, so we filter by peers that have at least one
+               // channel, and then limit the number of those with unfunded channels.
+               let channeled_peers_without_funding = self.peers_without_funded_channels(|node| !node.channel_by_id.is_empty());
+
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id.clone()))
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                   .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id.clone())
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
+
+               // If this peer already has some channels, a new channel won't increase our number of peers
+               // with unfunded channels, so as long as we aren't over the maximum number of unfunded
+               // channels per-peer we can accept channels from a peer with existing ones.
+               if peer_state.channel_by_id.is_empty() &&
+                       channeled_peers_without_funding >= MAX_UNFUNDED_CHANNEL_PEERS &&
+                       !self.default_configuration.manually_accept_inbound_channels
+               {
+                       return Err(MsgHandleErrInternal::send_err_msg_no_close(
+                               "Have too many peers with unfunded channels, not accepting new ones".to_owned(),
+                               msg.temporary_channel_id.clone()));
+               }
+
+               let best_block_height = self.best_block.read().unwrap().height();
+               if Self::unfunded_channel_count(peer_state, best_block_height) >= MAX_UNFUNDED_CHANS_PER_PEER {
+                       return Err(MsgHandleErrInternal::send_err_msg_no_close(
+                               format!("Refusing more than {} unfunded channels.", MAX_UNFUNDED_CHANS_PER_PEER),
+                               msg.temporary_channel_id.clone()));
+               }
+
                let mut channel = match Channel::new_from_req(&self.fee_estimator, &self.entropy_source, &self.signer_provider,
-                       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)
+                       counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id,
+                       &self.default_configuration, best_block_height, &self.logger, outbound_scid_alias)
                {
                        Err(e) => {
                                self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias);
@@ -4308,11 +4426,12 @@ where
        fn internal_accept_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel) -> Result<(), MsgHandleErrInternal> {
                let (value, output_script, user_id) = {
                        let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id))
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| {
+                                       debug_assert!(false);
+                                       MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id)
+                               })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.temporary_channel_id) {
                                hash_map::Entry::Occupied(mut chan) => {
@@ -4334,59 +4453,31 @@ where
        }
 
        fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
+               let best_block = *self.best_block.read().unwrap();
+
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id))
-               }
-               let ((funding_msg, monitor, mut channel_ready), mut chan) = {
-                       let best_block = *self.best_block.read().unwrap();
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
-                       let peer_state = &mut *peer_state_lock;
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id)
+                       })?;
+
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
+               let peer_state = &mut *peer_state_lock;
+               let ((funding_msg, monitor), chan) =
                        match peer_state.channel_by_id.entry(msg.temporary_channel_id) {
                                hash_map::Entry::Occupied(mut chan) => {
                                        (try_chan_entry!(self, chan.get_mut().funding_created(msg, best_block, &self.signer_provider, &self.logger), chan), chan.remove())
                                },
                                hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id))
-                       }
-               };
-               // Because we have exclusive ownership of the channel here we can release the peer_state
-               // lock before watch_channel
-               match self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor) {
-                       ChannelMonitorUpdateStatus::Completed => {},
-                       ChannelMonitorUpdateStatus::PermanentFailure => {
-                               // Note that we reply with the new channel_id in error messages if we gave up on the
-                               // channel, not the temporary_channel_id. This is compatible with ourselves, but the
-                               // spec is somewhat ambiguous here. Not a huge deal since we'll send error messages for
-                               // any messages referencing a previously-closed channel anyway.
-                               // We do not propagate the monitor update to the user as it would be for a monitor
-                               // that we didn't manage to store (and that we don't care about - we don't respond
-                               // with the funding_signed so the channel can never go on chain).
-                               let (_monitor_update, failed_htlcs) = chan.force_shutdown(false);
-                               assert!(failed_htlcs.is_empty());
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close("ChannelMonitor storage failure".to_owned(), funding_msg.channel_id));
-                       },
-                       ChannelMonitorUpdateStatus::InProgress => {
-                               // There's no problem signing a counterparty's funding transaction if our monitor
-                               // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
-                               // accepted payment from yet. We do, however, need to wait to send our channel_ready
-                               // until we have persisted our monitor.
-                               chan.monitor_updating_paused(false, false, channel_ready.is_some(), Vec::new(), Vec::new(), Vec::new());
-                               channel_ready = None; // Don't send the channel_ready now
-                       },
-               }
-               // It's safe to unwrap as we've held the `per_peer_state` read lock since checking that the
-               // peer exists, despite the inner PeerState potentially having no channels after removing
-               // the channel above.
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
-               let peer_state = &mut *peer_state_lock;
+                       };
+
                match peer_state.channel_by_id.entry(funding_msg.channel_id) {
                        hash_map::Entry::Occupied(_) => {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close("Already had channel with the new channel_id".to_owned(), funding_msg.channel_id))
+                               Err(MsgHandleErrInternal::send_err_msg_no_close("Already had channel with the new channel_id".to_owned(), funding_msg.channel_id))
                        },
                        hash_map::Entry::Vacant(e) => {
-                               let mut id_to_peer = self.id_to_peer.lock().unwrap();
-                               match id_to_peer.entry(chan.channel_id()) {
+                               match self.id_to_peer.lock().unwrap().entry(chan.channel_id()) {
                                        hash_map::Entry::Occupied(_) => {
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close(
                                                        "The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
@@ -4396,71 +4487,76 @@ where
                                                i_e.insert(chan.get_counterparty_node_id());
                                        }
                                }
+
+                               // There's no problem signing a counterparty's funding transaction if our monitor
+                               // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
+                               // accepted payment from yet. We do, however, need to wait to send our channel_ready
+                               // until we have persisted our monitor.
+                               let new_channel_id = funding_msg.channel_id;
                                peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingSigned {
                                        node_id: counterparty_node_id.clone(),
                                        msg: funding_msg,
                                });
-                               if let Some(msg) = channel_ready {
-                                       send_channel_ready!(self, peer_state.pending_msg_events, chan, msg);
+
+                               let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
+
+                               let chan = e.insert(chan);
+                               let mut res = handle_new_monitor_update!(self, monitor_res, 0, peer_state_lock, peer_state, chan, MANUALLY_REMOVING, { peer_state.channel_by_id.remove(&new_channel_id) });
+
+                               // Note that we reply with the new channel_id in error messages if we gave up on the
+                               // channel, not the temporary_channel_id. This is compatible with ourselves, but the
+                               // spec is somewhat ambiguous here. Not a huge deal since we'll send error messages for
+                               // any messages referencing a previously-closed channel anyway.
+                               // We do not propagate the monitor update to the user as it would be for a monitor
+                               // that we didn't manage to store (and that we don't care about - we don't respond
+                               // with the funding_signed so the channel can never go on chain).
+                               if let Err(MsgHandleErrInternal { shutdown_finish: Some((res, _)), .. }) = &mut res {
+                                       res.0 = None;
                                }
-                               e.insert(chan);
+                               res
                        }
                }
-               Ok(())
        }
 
        fn internal_funding_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> {
-               let funding_tx = {
-                       let best_block = *self.best_block.read().unwrap();
-                       let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-                       }
+               let best_block = *self.best_block.read().unwrap();
+               let per_peer_state = self.per_peer_state.read().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
 
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
-                       let peer_state = &mut *peer_state_lock;
-                       match peer_state.channel_by_id.entry(msg.channel_id) {
-                               hash_map::Entry::Occupied(mut chan) => {
-                                       let (monitor, funding_tx, channel_ready) = match chan.get_mut().funding_signed(&msg, best_block, &self.signer_provider, &self.logger) {
-                                               Ok(update) => update,
-                                               Err(e) => try_chan_entry!(self, Err(e), chan),
-                                       };
-                                       match self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
-                                               ChannelMonitorUpdateStatus::Completed => {},
-                                               e => {
-                                                       let mut res = handle_monitor_update_res!(self, e, chan, RAACommitmentOrder::RevokeAndACKFirst, channel_ready.is_some(), OPTIONALLY_RESEND_FUNDING_LOCKED);
-                                                       if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res {
-                                                               // We weren't able to watch the channel to begin with, so no updates should be made on
-                                                               // it. Previously, full_stack_target found an (unreachable) panic when the
-                                                               // monitor update contained within `shutdown_finish` was applied.
-                                                               if let Some((ref mut shutdown_finish, _)) = shutdown_finish {
-                                                                       shutdown_finish.0.take();
-                                                               }
-                                                       }
-                                                       return res
-                                               },
-                                       }
-                                       if let Some(msg) = channel_ready {
-                                               send_channel_ready!(self, peer_state.pending_msg_events, chan.get(), msg);
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
+               let peer_state = &mut *peer_state_lock;
+               match peer_state.channel_by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               let monitor = try_chan_entry!(self,
+                                       chan.get_mut().funding_signed(&msg, best_block, &self.signer_provider, &self.logger), chan);
+                               let update_res = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor);
+                               let mut res = handle_new_monitor_update!(self, update_res, 0, peer_state_lock, peer_state, chan);
+                               if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res {
+                                       // We weren't able to watch the channel to begin with, so no updates should be made on
+                                       // it. Previously, full_stack_target found an (unreachable) panic when the
+                                       // monitor update contained within `shutdown_finish` was applied.
+                                       if let Some((ref mut shutdown_finish, _)) = shutdown_finish {
+                                               shutdown_finish.0.take();
                                        }
-                                       funding_tx
-                               },
-                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
-                       }
-               };
-               log_info!(self.logger, "Broadcasting funding transaction with txid {}", funding_tx.txid());
-               self.tx_broadcaster.broadcast_transaction(&funding_tx);
-               Ok(())
+                               }
+                               res
+                       },
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
+               }
        }
 
        fn internal_channel_ready(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4499,11 +4595,12 @@ where
                let mut dropped_htlcs: Vec<(HTLCSource, PaymentHash)>;
                let result: Result<(), _> = loop {
                        let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| {
+                                       debug_assert!(false);
+                                       MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                               })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan_entry) => {
@@ -4514,27 +4611,27 @@ where
                                                        if chan_entry.get().sent_shutdown() { " after we initiated shutdown" } else { "" });
                                        }
 
-                                       let (shutdown, monitor_update, htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&self.signer_provider, &peer_state.latest_features, &msg), chan_entry);
+                                       let funding_txo_opt = chan_entry.get().get_funding_txo();
+                                       let (shutdown, monitor_update_opt, htlcs) = try_chan_entry!(self,
+                                               chan_entry.get_mut().shutdown(&self.signer_provider, &peer_state.latest_features, &msg), chan_entry);
                                        dropped_htlcs = htlcs;
 
-                                       // Update the monitor with the shutdown script if necessary.
-                                       if let Some(monitor_update) = monitor_update {
-                                               let update_res = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), &monitor_update);
-                                               let (result, is_permanent) =
-                                                       handle_monitor_update_res!(self, update_res, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
-                                               if is_permanent {
-                                                       remove_channel!(self, chan_entry);
-                                                       break result;
-                                               }
-                                       }
-
                                        if let Some(msg) = shutdown {
+                                               // We can send the `shutdown` message before updating the `ChannelMonitor`
+                                               // here as we don't need the monitor update to complete until we send a
+                                               // `shutdown_signed`, which we'll delay if we're pending a monitor update.
                                                peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
                                                        node_id: *counterparty_node_id,
                                                        msg,
                                                });
                                        }
 
+                                       // Update the monitor with the shutdown script if necessary.
+                                       if let Some(monitor_update) = monitor_update_opt {
+                                               let update_id = monitor_update.update_id;
+                                               let update_res = self.chain_monitor.update_channel(funding_txo_opt.unwrap(), monitor_update);
+                                               break handle_new_monitor_update!(self, update_res, update_id, peer_state_lock, peer_state, chan_entry);
+                                       }
                                        break Ok(());
                                },
                                hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
@@ -4546,18 +4643,18 @@ where
                        self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver);
                }
 
-               let _ = handle_error!(self, result, *counterparty_node_id);
-               Ok(())
+               result
        }
 
        fn internal_closing_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::ClosingSigned) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-               }
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
                let (tx, chan_option) = {
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan_entry) => {
@@ -4586,7 +4683,7 @@ where
                }
                if let Some(chan) = chan_option {
                        if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
-                               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
                                peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                        msg: update
@@ -4609,11 +4706,12 @@ where
 
                let pending_forward_info = self.decode_update_add_htlc_onion(msg);
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4650,11 +4748,12 @@ where
        fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
                let (htlc_source, forwarded_htlc_value) = {
                        let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| {
+                                       debug_assert!(false);
+                                       MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                               })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id) {
                                hash_map::Entry::Occupied(mut chan) => {
@@ -4669,11 +4768,12 @@ where
 
        fn internal_update_fail_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4686,11 +4786,12 @@ where
 
        fn internal_update_fail_malformed_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4707,48 +4808,21 @@ where
 
        fn internal_commitment_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
-                               let (revoke_and_ack, commitment_signed, monitor_update) =
-                                       match chan.get_mut().commitment_signed(&msg, &self.logger) {
-                                               Err((None, e)) => try_chan_entry!(self, Err(e), chan),
-                                               Err((Some(update), e)) => {
-                                                       assert!(chan.get().is_awaiting_monitor_update());
-                                                       let _ = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &update);
-                                                       try_chan_entry!(self, Err(e), chan);
-                                                       unreachable!();
-                                               },
-                                               Ok(res) => res
-                                       };
-                               let update_res = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update);
-                               if let Err(e) = handle_monitor_update_res!(self, update_res, chan, RAACommitmentOrder::RevokeAndACKFirst, true, commitment_signed.is_some()) {
-                                       return Err(e);
-                               }
-
-                               peer_state.pending_msg_events.push(events::MessageSendEvent::SendRevokeAndACK {
-                                       node_id: counterparty_node_id.clone(),
-                                       msg: revoke_and_ack,
-                               });
-                               if let Some(msg) = commitment_signed {
-                                       peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
-                                               node_id: counterparty_node_id.clone(),
-                                               updates: msgs::CommitmentUpdate {
-                                                       update_add_htlcs: Vec::new(),
-                                                       update_fulfill_htlcs: Vec::new(),
-                                                       update_fail_htlcs: Vec::new(),
-                                                       update_fail_malformed_htlcs: Vec::new(),
-                                                       update_fee: None,
-                                                       commitment_signed: msg,
-                                               },
-                                       });
-                               }
-                               Ok(())
+                               let funding_txo = chan.get().get_funding_txo();
+                               let monitor_update = try_chan_entry!(self, chan.get_mut().commitment_signed(&msg, &self.logger), chan);
+                               let update_res = self.chain_monitor.update_channel(funding_txo.unwrap(), monitor_update);
+                               let update_id = monitor_update.update_id;
+                               handle_new_monitor_update!(self, update_res, update_id, peer_state_lock,
+                                       peer_state, chan)
                        },
                        hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
                }
@@ -4757,7 +4831,7 @@ where
        #[inline]
        fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)]) {
                for &mut (prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards {
-                       let mut forward_event = None;
+                       let mut push_forward_event = false;
                        let mut new_intercept_events = Vec::new();
                        let mut failed_intercept_forwards = Vec::new();
                        if !pending_forwards.is_empty() {
@@ -4815,7 +4889,7 @@ where
                                                                // We don't want to generate a PendingHTLCsForwardable event if only intercepted
                                                                // payments are being processed.
                                                                if forward_htlcs_empty {
-                                                                       forward_event = Some(Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS));
+                                                                       push_forward_event = true;
                                                                }
                                                                entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
                                                                        prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, prev_user_channel_id, forward_info })));
@@ -4833,93 +4907,59 @@ where
                                let mut events = self.pending_events.lock().unwrap();
                                events.append(&mut new_intercept_events);
                        }
+                       if push_forward_event { self.push_pending_forwards_ev() }
+               }
+       }
 
-                       match forward_event {
-                               Some(time) => {
-                                       let mut pending_events = self.pending_events.lock().unwrap();
-                                       pending_events.push(events::Event::PendingHTLCsForwardable {
-                                               time_forwardable: time
-                                       });
-                               }
-                               None => {},
-                       }
+       // We only want to push a PendingHTLCsForwardable event if no others are queued.
+       fn push_pending_forwards_ev(&self) {
+               let mut pending_events = self.pending_events.lock().unwrap();
+               let forward_ev_exists = pending_events.iter()
+                       .find(|ev| if let events::Event::PendingHTLCsForwardable { .. } = ev { true } else { false })
+                       .is_some();
+               if !forward_ev_exists {
+                       pending_events.push(events::Event::PendingHTLCsForwardable {
+                               time_forwardable:
+                                       Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS),
+                       });
                }
        }
 
        fn internal_revoke_and_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result<(), MsgHandleErrInternal> {
-               let mut htlcs_to_fail = Vec::new();
-               let res = loop {
+               let (htlcs_to_fail, res) = {
                        let per_peer_state = self.per_peer_state.read().unwrap();
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               break Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id))
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| {
+                                       debug_assert!(false);
+                                       MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                               })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id) {
                                hash_map::Entry::Occupied(mut chan) => {
-                                       let was_paused_for_mon_update = chan.get().is_awaiting_monitor_update();
-                                       let raa_updates = break_chan_entry!(self,
-                                               chan.get_mut().revoke_and_ack(&msg, &self.logger), chan);
-                                       htlcs_to_fail = raa_updates.holding_cell_failed_htlcs;
-                                       let update_res = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &raa_updates.monitor_update);
-                                       if was_paused_for_mon_update {
-                                               assert!(update_res != ChannelMonitorUpdateStatus::Completed);
-                                               assert!(raa_updates.commitment_update.is_none());
-                                               assert!(raa_updates.accepted_htlcs.is_empty());
-                                               assert!(raa_updates.failed_htlcs.is_empty());
-                                               assert!(raa_updates.finalized_claimed_htlcs.is_empty());
-                                               break Err(MsgHandleErrInternal::ignore_no_close("Existing pending monitor update prevented responses to RAA".to_owned()));
-                                       }
-                                       if update_res != ChannelMonitorUpdateStatus::Completed {
-                                               if let Err(e) = handle_monitor_update_res!(self, update_res, chan,
-                                                               RAACommitmentOrder::CommitmentFirst, false,
-                                                               raa_updates.commitment_update.is_some(), false,
-                                                               raa_updates.accepted_htlcs, raa_updates.failed_htlcs,
-                                                               raa_updates.finalized_claimed_htlcs) {
-                                                       break Err(e);
-                                               } else { unreachable!(); }
-                                       }
-                                       if let Some(updates) = raa_updates.commitment_update {
-                                               peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
-                                                       node_id: counterparty_node_id.clone(),
-                                                       updates,
-                                               });
-                                       }
-                                       break Ok((raa_updates.accepted_htlcs, raa_updates.failed_htlcs,
-                                                       raa_updates.finalized_claimed_htlcs,
-                                                       chan.get().get_short_channel_id()
-                                                               .unwrap_or(chan.get().outbound_scid_alias()),
-                                                       chan.get().get_funding_txo().unwrap(),
-                                                       chan.get().get_user_id()))
+                                       let funding_txo = chan.get().get_funding_txo();
+                                       let (htlcs_to_fail, monitor_update) = try_chan_entry!(self, chan.get_mut().revoke_and_ack(&msg, &self.logger), chan);
+                                       let update_res = self.chain_monitor.update_channel(funding_txo.unwrap(), monitor_update);
+                                       let update_id = monitor_update.update_id;
+                                       let res = handle_new_monitor_update!(self, update_res, update_id, peer_state_lock,
+                                               peer_state, chan);
+                                       (htlcs_to_fail, res)
                                },
-                               hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
+                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
                        }
                };
                self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id, counterparty_node_id);
-               match res {
-                       Ok((pending_forwards, mut pending_failures, finalized_claim_htlcs,
-                               short_channel_id, channel_outpoint, user_channel_id)) =>
-                       {
-                               for failure in pending_failures.drain(..) {
-                                       let receiver = HTLCDestination::NextHopChannel { node_id: Some(*counterparty_node_id), channel_id: channel_outpoint.to_channel_id() };
-                                       self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver);
-                               }
-                               self.forward_htlcs(&mut [(short_channel_id, channel_outpoint, user_channel_id, pending_forwards)]);
-                               self.finalize_claims(finalized_claim_htlcs);
-                               Ok(())
-                       },
-                       Err(e) => Err(e)
-               }
+               res
        }
 
        fn internal_update_fee(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4932,11 +4972,12 @@ where
 
        fn internal_announcement_signatures(&self, counterparty_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), MsgHandleErrInternal> {
                let per_peer_state = self.per_peer_state.read().unwrap();
-               let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-               if let None = peer_state_mutex_opt {
-                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-               }
-               let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+               let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                       .ok_or_else(|| {
+                               debug_assert!(false);
+                               MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                       })?;
+               let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                match peer_state.channel_by_id.entry(msg.channel_id) {
                        hash_map::Entry::Occupied(mut chan) => {
@@ -4951,7 +4992,7 @@ where
                                        ), 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.
-                                       update_msg: self.get_channel_update_for_broadcast(chan.get()).unwrap(),
+                                       update_msg: Some(self.get_channel_update_for_broadcast(chan.get()).unwrap()),
                                });
                        },
                        hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
@@ -4970,7 +5011,7 @@ where
                };
                let per_peer_state = self.per_peer_state.read().unwrap();
                let peer_state_mutex_opt = per_peer_state.get(&chan_counterparty_node_id);
-               if let None = peer_state_mutex_opt {
+               if peer_state_mutex_opt.is_none() {
                        return Ok(NotifyOption::SkipPersist)
                }
                let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
@@ -5005,11 +5046,12 @@ where
                let need_lnd_workaround = {
                        let per_peer_state = self.per_peer_state.read().unwrap();
 
-                       let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                       if let None = peer_state_mutex_opt {
-                               return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id));
-                       }
-                       let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
+                       let peer_state_mutex = per_peer_state.get(counterparty_node_id)
+                               .ok_or_else(|| {
+                                       debug_assert!(false);
+                                       MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
+                               })?;
+                       let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id) {
                                hash_map::Entry::Occupied(mut chan) => {
@@ -5149,49 +5191,37 @@ where
                let mut has_monitor_update = false;
                let mut failed_htlcs = Vec::new();
                let mut handle_errors = Vec::new();
-               {
-                       let per_peer_state = self.per_peer_state.read().unwrap();
+               let per_peer_state = self.per_peer_state.read().unwrap();
 
-                       for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
+               for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
+                       'chan_loop: loop {
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
-                               let peer_state = &mut *peer_state_lock;
-                               let pending_msg_events = &mut peer_state.pending_msg_events;
-                               peer_state.channel_by_id.retain(|channel_id, chan| {
-                                       match chan.maybe_free_holding_cell_htlcs(&self.logger) {
-                                               Ok((commitment_opt, holding_cell_failed_htlcs)) => {
-                                                       if !holding_cell_failed_htlcs.is_empty() {
-                                                               failed_htlcs.push((
-                                                                       holding_cell_failed_htlcs,
-                                                                       *channel_id,
-                                                                       chan.get_counterparty_node_id()
-                                                               ));
-                                                       }
-                                                       if let Some((commitment_update, monitor_update)) = commitment_opt {
-                                                               match self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), &monitor_update) {
-                                                                       ChannelMonitorUpdateStatus::Completed => {
-                                                                               pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
-                                                                                       node_id: chan.get_counterparty_node_id(),
-                                                                                       updates: commitment_update,
-                                                                               });
-                                                                       },
-                                                                       e => {
-                                                                               has_monitor_update = true;
-                                                                               let (res, close_channel) = handle_monitor_update_res!(self, e, chan, RAACommitmentOrder::CommitmentFirst, channel_id, COMMITMENT_UPDATE_ONLY);
-                                                                               handle_errors.push((chan.get_counterparty_node_id(), res));
-                                                                               if close_channel { return false; }
-                                                                       },
-                                                               }
-                                                       }
-                                                       true
-                                               },
-                                               Err(e) => {
-                                                       let (close_channel, res) = convert_chan_err!(self, e, chan, channel_id);
-                                                       handle_errors.push((chan.get_counterparty_node_id(), Err(res)));
-                                                       // ChannelClosed event is generated by handle_error for us
-                                                       !close_channel
+                               let peer_state: &mut PeerState<_> = &mut *peer_state_lock;
+                               for (channel_id, chan) in peer_state.channel_by_id.iter_mut() {
+                                       let counterparty_node_id = chan.get_counterparty_node_id();
+                                       let funding_txo = chan.get_funding_txo();
+                                       let (monitor_opt, holding_cell_failed_htlcs) =
+                                               chan.maybe_free_holding_cell_htlcs(&self.logger);
+                                       if !holding_cell_failed_htlcs.is_empty() {
+                                               failed_htlcs.push((holding_cell_failed_htlcs, *channel_id, counterparty_node_id));
+                                       }
+                                       if let Some(monitor_update) = monitor_opt {
+                                               has_monitor_update = true;
+
+                                               let update_res = self.chain_monitor.update_channel(
+                                                       funding_txo.expect("channel is live"), monitor_update);
+                                               let update_id = monitor_update.update_id;
+                                               let channel_id: [u8; 32] = *channel_id;
+                                               let res = handle_new_monitor_update!(self, update_res, update_id,
+                                                       peer_state_lock, peer_state, chan, MANUALLY_REMOVING,
+                                                       peer_state.channel_by_id.remove(&channel_id));
+                                               if res.is_err() {
+                                                       handle_errors.push((counterparty_node_id, res));
                                                }
+                                               continue 'chan_loop;
                                        }
-                               });
+                               }
+                               break 'chan_loop;
                        }
                }
 
@@ -5325,7 +5355,8 @@ where
        /// [`PaymentHash`] and [`PaymentPreimage`] for you.
        ///
        /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`], which
-       /// will have the [`PaymentClaimable::payment_preimage`] field filled in. That should then be
+       /// will have the [`PaymentClaimable::purpose`] be [`PaymentPurpose::InvoicePayment`] with
+       /// its [`PaymentPurpose::InvoicePayment::payment_preimage`] field filled in. That should then be
        /// passed directly to [`claim_funds`].
        ///
        /// See [`create_inbound_payment_for_hash`] for detailed documentation on behavior and requirements.
@@ -5345,7 +5376,9 @@ where
        ///
        /// [`claim_funds`]: Self::claim_funds
        /// [`PaymentClaimable`]: events::Event::PaymentClaimable
-       /// [`PaymentClaimable::payment_preimage`]: events::Event::PaymentClaimable::payment_preimage
+       /// [`PaymentClaimable::purpose`]: events::Event::PaymentClaimable::purpose
+       /// [`PaymentPurpose::InvoicePayment`]: events::PaymentPurpose::InvoicePayment
+       /// [`PaymentPurpose::InvoicePayment::payment_preimage`]: events::PaymentPurpose::InvoicePayment::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,
                min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()> {
@@ -5520,6 +5553,12 @@ where
                events.into_inner()
        }
 
+       #[cfg(feature = "_test_utils")]
+       pub fn push_pending_event(&self, event: events::Event) {
+               let mut events = self.pending_events.lock().unwrap();
+               events.push(event);
+       }
+
        #[cfg(test)]
        pub fn pop_pending_event(&self) -> Option<events::Event> {
                let mut events = self.pending_events.lock().unwrap();
@@ -5618,9 +5657,7 @@ where
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
                                if peer_state.pending_msg_events.len() > 0 {
-                                       let mut peer_pending_events = Vec::new();
-                                       mem::swap(&mut peer_pending_events, &mut peer_state.pending_msg_events);
-                                       pending_events.append(&mut peer_pending_events);
+                                       pending_events.append(&mut peer_state.pending_msg_events);
                                }
                        }
 
@@ -5786,8 +5823,8 @@ where
                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        for chan in peer_state.channel_by_id.values() {
-                               if let (Some(funding_txo), block_hash) = (chan.get_funding_txo(), chan.get_funding_tx_confirmed_in()) {
-                                       res.push((funding_txo.txid, block_hash));
+                               if let (Some(funding_txo), Some(block_hash)) = (chan.get_funding_txo(), chan.get_funding_tx_confirmed_in()) {
+                                       res.push((funding_txo.txid, Some(block_hash)));
                                }
                        }
                }
@@ -5871,7 +5908,7 @@ where
                                                                                msg: announcement,
                                                                                // 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.
-                                                                               update_msg: self.get_channel_update_for_broadcast(channel).unwrap(),
+                                                                               update_msg: Some(self.get_channel_update_for_broadcast(channel).unwrap()),
                                                                        });
                                                                }
                                                        }
@@ -6148,14 +6185,13 @@ where
                let _ = handle_error!(self, self.internal_channel_reestablish(counterparty_node_id, msg), *counterparty_node_id);
        }
 
-       fn peer_disconnected(&self, counterparty_node_id: &PublicKey, no_connection_possible: bool) {
+       fn peer_disconnected(&self, counterparty_node_id: &PublicKey) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
                let mut failed_channels = Vec::new();
-               let mut no_channels_remain = true;
                let mut per_peer_state = self.per_peer_state.write().unwrap();
-               {
-                       log_debug!(self.logger, "Marking channels with {} disconnected and generating channel_updates. We believe we {} make future connections to this peer.",
-                               log_pubkey!(counterparty_node_id), if no_connection_possible { "cannot" } else { "can" });
+               let remove_peer = {
+                       log_debug!(self.logger, "Marking channels with {} disconnected and generating channel_updates.",
+                               log_pubkey!(counterparty_node_id));
                        if let Some(peer_state_mutex) = per_peer_state.get(counterparty_node_id) {
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
@@ -6166,8 +6202,6 @@ where
                                                update_maps_on_chan_removal!(self, chan);
                                                self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer);
                                                return false;
-                                       } else {
-                                               no_channels_remain = false;
                                        }
                                        true
                                });
@@ -6187,6 +6221,7 @@ where
                                                &events::MessageSendEvent::SendChannelAnnouncement { .. } => false,
                                                &events::MessageSendEvent::BroadcastChannelAnnouncement { .. } => true,
                                                &events::MessageSendEvent::BroadcastChannelUpdate { .. } => true,
+                                               &events::MessageSendEvent::BroadcastNodeAnnouncement { .. } => true,
                                                &events::MessageSendEvent::SendChannelUpdate { .. } => false,
                                                &events::MessageSendEvent::HandleError { .. } => false,
                                                &events::MessageSendEvent::SendChannelRangeQuery { .. } => false,
@@ -6195,9 +6230,12 @@ where
                                                &events::MessageSendEvent::SendGossipTimestampFilter { .. } => false,
                                        }
                                });
-                       }
-               }
-               if no_channels_remain {
+                               debug_assert!(peer_state.is_connected, "A disconnected peer cannot disconnect");
+                               peer_state.is_connected = false;
+                               peer_state.ok_to_remove(true)
+                       } else { debug_assert!(false, "Unconnected peer disconnected"); true }
+               };
+               if remove_peer {
                        per_peer_state.remove(counterparty_node_id);
                }
                mem::drop(per_peer_state);
@@ -6207,34 +6245,57 @@ where
                }
        }
 
-       fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init) -> Result<(), ()> {
+       fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init, inbound: bool) -> Result<(), ()> {
                if !init_msg.features.supports_static_remote_key() {
-                       log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(counterparty_node_id));
+                       log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting", log_pubkey!(counterparty_node_id));
                        return Err(());
                }
 
-               log_debug!(self.logger, "Generating channel_reestablish events for {}", log_pubkey!(counterparty_node_id));
-
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
 
+               // If we have too many peers connected which don't have funded channels, disconnect the
+               // peer immediately (as long as it doesn't have funded channels). If we have a bunch of
+               // unfunded channels taking up space in memory for disconnected peers, we still let new
+               // peers connect, but we'll reject new channels from them.
+               let connected_peers_without_funded_channels = self.peers_without_funded_channels(|node| node.is_connected);
+               let inbound_peer_limited = inbound && connected_peers_without_funded_channels >= MAX_NO_CHANNEL_PEERS;
+
                {
                        let mut peer_state_lock = self.per_peer_state.write().unwrap();
                        match peer_state_lock.entry(counterparty_node_id.clone()) {
                                hash_map::Entry::Vacant(e) => {
+                                       if inbound_peer_limited {
+                                               return Err(());
+                                       }
                                        e.insert(Mutex::new(PeerState {
                                                channel_by_id: HashMap::new(),
                                                latest_features: init_msg.features.clone(),
                                                pending_msg_events: Vec::new(),
+                                               monitor_update_blocked_actions: BTreeMap::new(),
+                                               is_connected: true,
                                        }));
                                },
                                hash_map::Entry::Occupied(e) => {
-                                       e.get().lock().unwrap().latest_features = init_msg.features.clone();
+                                       let mut peer_state = e.get().lock().unwrap();
+                                       peer_state.latest_features = init_msg.features.clone();
+
+                                       let best_block_height = self.best_block.read().unwrap().height();
+                                       if inbound_peer_limited &&
+                                               Self::unfunded_channel_count(&*peer_state, best_block_height) ==
+                                               peer_state.channel_by_id.len()
+                                       {
+                                               return Err(());
+                                       }
+
+                                       debug_assert!(!peer_state.is_connected, "A peer shouldn't be connected twice");
+                                       peer_state.is_connected = true;
                                },
                        }
                }
 
-               let per_peer_state = self.per_peer_state.read().unwrap();
+               log_debug!(self.logger, "Generating channel_reestablish events for {}", log_pubkey!(counterparty_node_id));
 
+               let per_peer_state = self.per_peer_state.read().unwrap();
                for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
@@ -6279,7 +6340,7 @@ where
                        let channel_ids: Vec<[u8; 32]> = {
                                let per_peer_state = self.per_peer_state.read().unwrap();
                                let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                               if let None = peer_state_mutex_opt { return; }
+                               if peer_state_mutex_opt.is_none() { return; }
                                let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
                                peer_state.channel_by_id.keys().cloned().collect()
@@ -6293,7 +6354,7 @@ where
                                // First check if we can advance the channel type and try again.
                                let per_peer_state = self.per_peer_state.read().unwrap();
                                let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id);
-                               if let None = peer_state_mutex_opt { return; }
+                               if peer_state_mutex_opt.is_none() { return; }
                                let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
                                if let Some(chan) = peer_state.channel_by_id.get_mut(&msg.channel_id) {
@@ -6787,6 +6848,7 @@ where
                        best_block.block_hash().write(writer)?;
                }
 
+               let mut serializable_peer_count: u64 = 0;
                {
                        let per_peer_state = self.per_peer_state.read().unwrap();
                        let mut unfunded_channels = 0;
@@ -6794,6 +6856,9 @@ where
                        for (_, peer_state_mutex) in per_peer_state.iter() {
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                let peer_state = &mut *peer_state_lock;
+                               if !peer_state.ok_to_remove(false) {
+                                       serializable_peer_count += 1;
+                               }
                                number_of_channels += peer_state.channel_by_id.len();
                                for (_, channel) in peer_state.channel_by_id.iter() {
                                        if !channel.is_funding_initiated() {
@@ -6844,11 +6909,27 @@ where
                        htlc_purposes.push(purpose);
                }
 
-               (per_peer_state.len() as u64).write(writer)?;
-               for (peer_pubkey, peer_state_mutex) in per_peer_state.iter() {
-                       peer_pubkey.write(writer)?;
-                       let peer_state = peer_state_mutex.lock().unwrap();
-                       peer_state.latest_features.write(writer)?;
+               let mut monitor_update_blocked_actions_per_peer = None;
+               let mut peer_states = Vec::new();
+               for (_, peer_state_mutex) in per_peer_state.iter() {
+                       peer_states.push(peer_state_mutex.lock().unwrap());
+               }
+
+               (serializable_peer_count).write(writer)?;
+               for ((peer_pubkey, _), peer_state) in per_peer_state.iter().zip(peer_states.iter()) {
+                       // Peers which we have no channels to should be dropped once disconnected. As we
+                       // disconnect all peers when shutting down and serializing the ChannelManager, we
+                       // consider all peers as disconnected here. There's therefore no need write peers with
+                       // no channels.
+                       if !peer_state.ok_to_remove(false) {
+                               peer_pubkey.write(writer)?;
+                               peer_state.latest_features.write(writer)?;
+                               if !peer_state.monitor_update_blocked_actions.is_empty() {
+                                       monitor_update_blocked_actions_per_peer
+                                               .get_or_insert_with(Vec::new)
+                                               .push((*peer_pubkey, &peer_state.monitor_update_blocked_actions));
+                               }
+                       }
                }
 
                let events = self.pending_events.lock().unwrap();
@@ -6925,8 +7006,6 @@ where
                        // LDK versions prior to 0.0.113 do not know how to read the pending claimed payments
                        // map. Thus, if there are no entries we skip writing a TLV for it.
                        pending_claiming_payments = None;
-               } else {
-                       debug_assert!(false, "While we have code to serialize pending_claiming_payments, the map should always be empty until a later PR");
                }
 
                write_tlv_fields!(writer, {
@@ -6935,6 +7014,7 @@ where
                        (3, pending_outbound_payments, required),
                        (4, pending_claiming_payments, option),
                        (5, self.our_network_pubkey, required),
+                       (6, monitor_update_blocked_actions_per_peer, option),
                        (7, self.fake_scid_rand_bytes, required),
                        (9, htlc_purposes, vec_type),
                        (11, self.probing_cookie_secret, required),
@@ -7247,6 +7327,8 @@ where
                                channel_by_id: peer_channels.remove(&peer_pubkey).unwrap_or(HashMap::new()),
                                latest_features: Readable::read(reader)?,
                                pending_msg_events: Vec::new(),
+                               monitor_update_blocked_actions: BTreeMap::new(),
+                               is_connected: false,
                        };
                        per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
                }
@@ -7302,12 +7384,14 @@ where
                let mut probing_cookie_secret: Option<[u8; 32]> = None;
                let mut claimable_htlc_purposes = None;
                let mut pending_claiming_payments = Some(HashMap::new());
+               let mut monitor_update_blocked_actions_per_peer = Some(Vec::new());
                read_tlv_fields!(reader, {
                        (1, pending_outbound_payments_no_retry, option),
                        (2, pending_intercepted_htlcs, option),
                        (3, pending_outbound_payments, option),
                        (4, pending_claiming_payments, option),
                        (5, received_network_pubkey, option),
+                       (6, monitor_update_blocked_actions_per_peer, option),
                        (7, fake_scid_rand_bytes, option),
                        (9, claimable_htlc_purposes, vec_type),
                        (11, probing_cookie_secret, option),
@@ -7357,12 +7441,13 @@ where
                                                                hash_map::Entry::Vacant(entry) => {
                                                                        let path_fee = path.get_path_fees();
                                                                        entry.insert(PendingOutboundPayment::Retryable {
-                                                                               retry_strategy: Retry::Attempts(0),
+                                                                               retry_strategy: None,
                                                                                attempts: PaymentAttempts::new(),
-                                                                               route_params: None,
+                                                                               payment_params: None,
                                                                                session_privs: [session_priv_bytes].iter().map(|a| *a).collect(),
                                                                                payment_hash: htlc.payment_hash,
                                                                                payment_secret,
+                                                                               keysend_preimage: None, // only used for retries, and we'll never retry on startup
                                                                                pending_amt_msat: path_amt,
                                                                                pending_fee_msat: Some(path_fee),
                                                                                total_msat: path_amt,
@@ -7415,7 +7500,8 @@ where
                        }
                }
 
-               if !forward_htlcs.is_empty() {
+               let pending_outbounds = OutboundPayments { pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()), retry_lock: Mutex::new(()) };
+               if !forward_htlcs.is_empty() || pending_outbounds.needs_abandon() {
                        // If we have pending HTLCs to forward, assume we either dropped a
                        // `PendingHTLCsForwardable` or the user received it but never processed it as they
                        // shut down before the timer hit. Either way, set the time_forwardable to a small
@@ -7572,6 +7658,15 @@ where
                        }
                }
 
+               for (node_id, monitor_update_blocked_actions) in monitor_update_blocked_actions_per_peer.unwrap() {
+                       if let Some(peer_state) = per_peer_state.get_mut(&node_id) {
+                               peer_state.lock().unwrap().monitor_update_blocked_actions = monitor_update_blocked_actions;
+                       } else {
+                               log_error!(args.logger, "Got blocked actions without a per-peer-state for {}", node_id);
+                               return Err(DecodeError::InvalidValue);
+                       }
+               }
+
                let channel_manager = ChannelManager {
                        genesis_hash,
                        fee_estimator: bounded_fee_estimator,
@@ -7583,7 +7678,7 @@ where
 
                        inbound_payment_key: expanded_inbound_key,
                        pending_inbound_payments: Mutex::new(pending_inbound_payments),
-                       pending_outbound_payments: OutboundPayments { pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()) },
+                       pending_outbound_payments: pending_outbounds,
                        pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()),
 
                        forward_htlcs: Mutex::new(forward_htlcs),
@@ -7633,19 +7728,14 @@ where
 mod tests {
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::sha256::Hash as Sha256;
-       use bitcoin::hashes::hex::FromHex;
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
-       use bitcoin::secp256k1::ecdsa::Signature;
-       use bitcoin::secp256k1::ffi::Signature as FFISignature;
-       use bitcoin::blockdata::script::Script;
-       use bitcoin::Txid;
        use core::time::Duration;
        use core::sync::atomic::Ordering;
        use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::channelmanager::{inbound_payment, PaymentId, PaymentSendFailure, InterceptId};
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs;
-       use crate::ln::msgs::{ChannelMessageHandler, OptionalField};
+       use crate::ln::msgs::ChannelMessageHandler;
        use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
        use crate::util::errors::APIError;
        use crate::util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
@@ -7862,7 +7952,7 @@ mod tests {
                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 scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
 
                // To start (1), send a regular payment but don't claim it.
@@ -7871,7 +7961,7 @@ mod tests {
 
                // Next, attempt a keysend payment and make sure it fails.
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id()),
+                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV),
                        final_value_msat: 100_000,
                        final_cltv_expiry_delta: TEST_FINAL_CLTV,
                };
@@ -7959,18 +8049,16 @@ mod tests {
 
                let payer_pubkey = nodes[0].node.get_our_node_id();
                let payee_pubkey = nodes[1].node.get_our_node_id();
-               nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-               nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey),
+                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
                        final_value_msat: 10_000,
                        final_cltv_expiry_delta: 40,
                };
                let network_graph = nodes[0].network_graph.clone();
                let first_hops = nodes[0].node.list_usable_channels();
-               let scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
@@ -8004,18 +8092,16 @@ mod tests {
 
                let payer_pubkey = nodes[0].node.get_our_node_id();
                let payee_pubkey = nodes[1].node.get_our_node_id();
-               nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-               nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey),
+                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
                        final_value_msat: 10_000,
                        final_cltv_expiry_delta: 40,
                };
                let network_graph = nodes[0].network_graph.clone();
                let first_hops = nodes[0].node.list_usable_channels();
-               let scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
@@ -8070,6 +8156,40 @@ mod tests {
                }
        }
 
+       #[test]
+       fn test_drop_disconnected_peers_when_removing_channels() {
+               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 chan = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+
+               nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
+               check_closed_broadcast!(nodes[0], true);
+               check_added_monitors!(nodes[0], 1);
+               check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed);
+
+               {
+                       // Assert that nodes[1] is awaiting removal for nodes[0] once nodes[1] has been
+                       // disconnected and the channel between has been force closed.
+                       let nodes_0_per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
+                       // Assert that nodes[1] isn't removed before `timer_tick_occurred` has been executed.
+                       assert_eq!(nodes_0_per_peer_state.len(), 1);
+                       assert!(nodes_0_per_peer_state.get(&nodes[1].node.get_our_node_id()).is_some());
+               }
+
+               nodes[0].node.timer_tick_occurred();
+
+               {
+                       // Assert that nodes[1] has now been removed.
+                       assert_eq!(nodes[0].node.per_peer_state.read().unwrap().len(), 0);
+               }
+       }
+
        #[test]
        fn bad_inbound_payment_hash() {
                // Add coverage for checking that a user-provided payment hash matches the payment secret.
@@ -8214,19 +8334,22 @@ mod tests {
 
        fn check_not_connected_to_peer_error<T>(res_err: Result<T, APIError>, expected_public_key: PublicKey) {
                let expected_message = format!("Not connected to node: {}", expected_public_key);
-               check_api_misuse_error_message(expected_message, res_err)
+               check_api_error_message(expected_message, res_err)
        }
 
        fn check_unkown_peer_error<T>(res_err: Result<T, APIError>, expected_public_key: PublicKey) {
                let expected_message = format!("Can't find a peer matching the passed counterparty node_id {}", expected_public_key);
-               check_api_misuse_error_message(expected_message, res_err)
+               check_api_error_message(expected_message, res_err)
        }
 
-       fn check_api_misuse_error_message<T>(expected_err_message: String, res_err: Result<T, APIError>) {
+       fn check_api_error_message<T>(expected_err_message: String, res_err: Result<T, APIError>) {
                match res_err {
                        Err(APIError::APIMisuseError { err }) => {
                                assert_eq!(err, expected_err_message);
                        },
+                       Err(APIError::ChannelUnavailable { err }) => {
+                               assert_eq!(err, expected_err_message);
+                       },
                        Ok(_) => panic!("Unexpected Ok"),
                        Err(_) => panic!("Unexpected Error"),
                }
@@ -8234,170 +8357,240 @@ mod tests {
 
        #[test]
        fn test_api_calls_with_unkown_counterparty_node() {
-               // Tests that our API functions and message handlers that expects a `counterparty_node_id`
-               // as input, behaves as expected if the `counterparty_node_id` is an unkown peer in the
+               // Tests that our API functions that expects a `counterparty_node_id` as input, behaves as
+               // expected if the `counterparty_node_id` is an unkown peer in the
                // `ChannelManager::per_peer_state` map.
                let chanmon_cfg = create_chanmon_cfgs(2);
                let node_cfg = create_node_cfgs(2, &chanmon_cfg);
                let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[None, None]);
                let nodes = create_network(2, &node_cfg, &node_chanmgr);
 
-               // Boilerplate code to produce `open_channel` and `accept_channel` msgs more densly than
-               // creating dummy ones.
-               nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
-               let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
-               nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
-               let accept_channel_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
-
                // Dummy values
                let channel_id = [4; 32];
-               let signature = Signature::from(unsafe { FFISignature::new() });
                let unkown_public_key = PublicKey::from_secret_key(&Secp256k1::signing_only(), &SecretKey::from_slice(&[42; 32]).unwrap());
                let intercept_id = InterceptId([0; 32]);
 
-               // Dummy msgs
-               let funding_created_msg = msgs::FundingCreated {
-                       temporary_channel_id: open_channel_msg.temporary_channel_id,
-                       funding_txid: Txid::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(),
-                       funding_output_index: 0,
-                       signature: signature,
-               };
-
-               let funding_signed_msg = msgs::FundingSigned {
-                       channel_id: channel_id,
-                       signature: signature,
-               };
-
-               let channel_ready_msg = msgs::ChannelReady {
-                       channel_id: channel_id,
-                       next_per_commitment_point: unkown_public_key,
-                       short_channel_id_alias: None,
-               };
-
-               let announcement_signatures_msg = msgs::AnnouncementSignatures {
-                       channel_id: channel_id,
-                       short_channel_id: 0,
-                       node_signature: signature,
-                       bitcoin_signature: signature,
-               };
-
-               let channel_reestablish_msg = msgs::ChannelReestablish {
-                       channel_id: channel_id,
-                       next_local_commitment_number: 0,
-                       next_remote_commitment_number: 0,
-                       data_loss_protect: OptionalField::Absent,
-               };
-
-               let closing_signed_msg = msgs::ClosingSigned {
-                       channel_id: channel_id,
-                       fee_satoshis: 1000,
-                       signature: signature,
-                       fee_range: None,
-               };
-
-               let shutdown_msg = msgs::Shutdown {
-                       channel_id: channel_id,
-                       scriptpubkey: Script::new(),
-               };
-
-               let onion_routing_packet = msgs::OnionPacket {
-                       version: 255,
-                       public_key: Ok(unkown_public_key),
-                       hop_data: [1; 20*65],
-                       hmac: [2; 32]
-               };
-
-               let update_add_htlc_msg = msgs::UpdateAddHTLC {
-                       channel_id: channel_id,
-                       htlc_id: 0,
-                       amount_msat: 1000000,
-                       payment_hash: PaymentHash([1; 32]),
-                       cltv_expiry: 821716,
-                       onion_routing_packet
-               };
-
-               let commitment_signed_msg = msgs::CommitmentSigned {
-                       channel_id: channel_id,
-                       signature: signature,
-                       htlc_signatures: Vec::new(),
-               };
+               // Test the API functions.
+               check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None), unkown_public_key);
 
-               let update_fee_msg = msgs::UpdateFee {
-                       channel_id: channel_id,
-                       feerate_per_kw: 1000,
-               };
+               check_unkown_peer_error(nodes[0].node.accept_inbound_channel(&channel_id, &unkown_public_key, 42), unkown_public_key);
 
-               let malformed_update_msg = msgs::UpdateFailMalformedHTLC{
-                       channel_id: channel_id,
-                       htlc_id: 0,
-                       sha256_of_onion: [1; 32],
-                       failure_code: 0x8000,
-               };
+               check_unkown_peer_error(nodes[0].node.close_channel(&channel_id, &unkown_public_key), unkown_public_key);
 
-               let fulfill_update_msg = msgs::UpdateFulfillHTLC{
-                       channel_id: channel_id,
-                       htlc_id: 0,
-                       payment_preimage: PaymentPreimage([1; 32]),
-               };
+               check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key), unkown_public_key);
 
-               let fail_update_msg = msgs::UpdateFailHTLC{
-                       channel_id: channel_id,
-                       htlc_id: 0,
-                       reason: msgs::OnionErrorPacket { data: Vec::new()},
-               };
+               check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), unkown_public_key);
 
-               let revoke_and_ack_msg = msgs::RevokeAndACK {
-                       channel_id: channel_id,
-                       per_commitment_secret: [1; 32],
-                       next_per_commitment_point: unkown_public_key,
-               };
+               check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key);
 
-               // Test the API functions and message handlers.
-               check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None), unkown_public_key);
+               check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, &[channel_id], &ChannelConfig::default()), unkown_public_key);
+       }
 
-               nodes[1].node.handle_open_channel(&unkown_public_key, &open_channel_msg);
+       #[test]
+       fn test_connection_limiting() {
+               // Test that we limit un-channel'd peers and un-funded channels properly.
+               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);
 
-               nodes[0].node.handle_accept_channel(&unkown_public_key, &accept_channel_msg);
+               // Note that create_network connects the nodes together for us
 
-               check_unkown_peer_error(nodes[0].node.accept_inbound_channel(&open_channel_msg.temporary_channel_id, &unkown_public_key, 42), unkown_public_key);
+               nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
+               let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
 
-               nodes[1].node.handle_funding_created(&unkown_public_key, &funding_created_msg);
+               let mut funding_tx = None;
+               for idx in 0..super::MAX_UNFUNDED_CHANS_PER_PEER {
+                       nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+                       let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
 
-               nodes[0].node.handle_funding_signed(&unkown_public_key, &funding_signed_msg);
+                       if idx == 0 {
+                               nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel);
+                               let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42);
+                               funding_tx = Some(tx.clone());
+                               nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx).unwrap();
+                               let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
 
-               nodes[0].node.handle_channel_ready(&unkown_public_key, &channel_ready_msg);
+                               nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
+                               check_added_monitors!(nodes[1], 1);
+                               let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
 
-               nodes[1].node.handle_announcement_signatures(&unkown_public_key, &announcement_signatures_msg);
+                               nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
+                               check_added_monitors!(nodes[0], 1);
+                       }
+                       open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
+               }
 
-               check_unkown_peer_error(nodes[0].node.close_channel(&channel_id, &unkown_public_key), unkown_public_key);
+               // A MAX_UNFUNDED_CHANS_PER_PEER + 1 channel will be summarily rejected
+               open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
+               nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+               assert_eq!(get_err_msg!(nodes[1], nodes[0].node.get_our_node_id()).channel_id,
+                       open_channel_msg.temporary_channel_id);
+
+               // Further, because all of our channels with nodes[0] are inbound, and none of them funded,
+               // it doesn't count as a "protected" peer, i.e. it counts towards the MAX_NO_CHANNEL_PEERS
+               // limit.
+               let mut peer_pks = Vec::with_capacity(super::MAX_NO_CHANNEL_PEERS);
+               for _ in 1..super::MAX_NO_CHANNEL_PEERS {
+                       let random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
+                               &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
+                       peer_pks.push(random_pk);
+                       nodes[1].node.peer_connected(&random_pk, &msgs::Init {
+                               features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+               }
+               let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
+                       &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
+               nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap_err();
+
+               // Also importantly, because nodes[0] isn't "protected", we will refuse a reconnection from
+               // them if we have too many un-channel'd peers.
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+               let chan_closed_events = nodes[1].node.get_and_clear_pending_events();
+               assert_eq!(chan_closed_events.len(), super::MAX_UNFUNDED_CHANS_PER_PEER - 1);
+               for ev in chan_closed_events {
+                       if let Event::ChannelClosed { .. } = ev { } else { panic!(); }
+               }
+               nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap_err();
+
+               // but of course if the connection is outbound its allowed...
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+
+               // Now nodes[0] is disconnected but still has a pending, un-funded channel lying around.
+               // Even though we accept one more connection from new peers, we won't actually let them
+               // open channels.
+               assert!(peer_pks.len() > super::MAX_UNFUNDED_CHANNEL_PEERS - 1);
+               for i in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 {
+                       nodes[1].node.handle_open_channel(&peer_pks[i], &open_channel_msg);
+                       get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, peer_pks[i]);
+                       open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
+               }
+               nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
+               assert_eq!(get_err_msg!(nodes[1], last_random_pk).channel_id,
+                       open_channel_msg.temporary_channel_id);
+
+               // Of course, however, outbound channels are always allowed
+               nodes[1].node.create_channel(last_random_pk, 100_000, 0, 42, None).unwrap();
+               get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, last_random_pk);
+
+               // If we fund the first channel, nodes[0] has a live on-chain channel with us, it is now
+               // "protected" and can connect again.
+               mine_transaction(&nodes[1], funding_tx.as_ref().unwrap());
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+               get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+
+               // Further, because the first channel was funded, we can open another channel with
+               // last_random_pk.
+               nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
+               get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, last_random_pk);
+       }
 
-               check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key), unkown_public_key);
+       #[test]
+       fn test_outbound_chans_unlimited() {
+               // Test that we never refuse an outbound channel even if a peer is unfuned-channel-limited
+               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);
 
-               check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), unkown_public_key);
+               // Note that create_network connects the nodes together for us
 
-               check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key);
+               nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
+               let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
 
-               check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, &[channel_id], &ChannelConfig::default()), unkown_public_key);
+               for _ in 0..super::MAX_UNFUNDED_CHANS_PER_PEER {
+                       nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+                       get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
+                       open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
+               }
 
-               nodes[0].node.handle_shutdown(&unkown_public_key, &shutdown_msg);
+               // Once we have MAX_UNFUNDED_CHANS_PER_PEER unfunded channels, new inbound channels will be
+               // rejected.
+               nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+               assert_eq!(get_err_msg!(nodes[1], nodes[0].node.get_our_node_id()).channel_id,
+                       open_channel_msg.temporary_channel_id);
 
-               nodes[1].node.handle_closing_signed(&unkown_public_key, &closing_signed_msg);
+               // but we can still open an outbound channel.
+               nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
+               get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
 
-               nodes[0].node.handle_channel_reestablish(&unkown_public_key, &channel_reestablish_msg);
+               // but even with such an outbound channel, additional inbound channels will still fail.
+               nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
+               assert_eq!(get_err_msg!(nodes[1], nodes[0].node.get_our_node_id()).channel_id,
+                       open_channel_msg.temporary_channel_id);
+       }
 
-               nodes[1].node.handle_update_add_htlc(&unkown_public_key, &update_add_htlc_msg);
+       #[test]
+       fn test_0conf_limiting() {
+               // Tests that we properly limit inbound channels when we have the manual-channel-acceptance
+               // flag set and (sometimes) accept channels as 0conf.
+               let chanmon_cfgs = create_chanmon_cfgs(2);
+               let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+               let mut settings = test_default_channel_config();
+               settings.manually_accept_inbound_channels = true;
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(settings)]);
+               let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
-               nodes[1].node.handle_commitment_signed(&unkown_public_key, &commitment_signed_msg);
+               // Note that create_network connects the nodes together for us
 
-               nodes[1].node.handle_update_fail_malformed_htlc(&unkown_public_key, &malformed_update_msg);
+               nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
+               let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
 
-               nodes[1].node.handle_update_fail_htlc(&unkown_public_key, &fail_update_msg);
+               // First, get us up to MAX_UNFUNDED_CHANNEL_PEERS so we can test at the edge
+               for _ in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 {
+                       let random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
+                               &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
+                       nodes[1].node.peer_connected(&random_pk, &msgs::Init {
+                               features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
 
-               nodes[1].node.handle_update_fulfill_htlc(&unkown_public_key, &fulfill_update_msg);
+                       nodes[1].node.handle_open_channel(&random_pk, &open_channel_msg);
+                       let events = nodes[1].node.get_and_clear_pending_events();
+                       match events[0] {
+                               Event::OpenChannelRequest { temporary_channel_id, .. } => {
+                                       nodes[1].node.accept_inbound_channel(&temporary_channel_id, &random_pk, 23).unwrap();
+                               }
+                               _ => panic!("Unexpected event"),
+                       }
+                       get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, random_pk);
+                       open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
+               }
 
-               nodes[1].node.handle_revoke_and_ack(&unkown_public_key, &revoke_and_ack_msg);
+               // If we try to accept a channel from another peer non-0conf it will fail.
+               let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
+                       &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
+               nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
+                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+               nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
+               let events = nodes[1].node.get_and_clear_pending_events();
+               match events[0] {
+                       Event::OpenChannelRequest { temporary_channel_id, .. } => {
+                               match nodes[1].node.accept_inbound_channel(&temporary_channel_id, &last_random_pk, 23) {
+                                       Err(APIError::APIMisuseError { err }) =>
+                                               assert_eq!(err, "Too many peers with unfunded channels, refusing to accept new ones"),
+                                       _ => panic!(),
+                               }
+                       }
+                       _ => panic!("Unexpected event"),
+               }
+               assert_eq!(get_err_msg!(nodes[1], last_random_pk).channel_id,
+                       open_channel_msg.temporary_channel_id);
 
-               nodes[1].node.handle_update_fee(&unkown_public_key, &update_fee_msg);
+               // ...however if we accept the same channel 0conf it should work just fine.
+               nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
+               let events = nodes[1].node.get_and_clear_pending_events();
+               match events[0] {
+                       Event::OpenChannelRequest { temporary_channel_id, .. } => {
+                               nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &last_random_pk, 23).unwrap();
+                       }
+                       _ => panic!("Unexpected event"),
+               }
+               get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, last_random_pk);
        }
 
        #[cfg(anchors)]
@@ -8485,7 +8678,8 @@ pub mod bench {
                let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))};
                let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) };
                let logger_a = test_utils::TestLogger::with_id("node a".to_owned());
-               let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(genesis_hash, &logger_a)));
+               let scorer = Mutex::new(test_utils::TestScorer::new());
+               let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(genesis_hash, &logger_a)), &scorer);
 
                let mut config: UserConfig = Default::default();
                config.channel_handshake_config.minimum_depth = 1;
@@ -8509,8 +8703,8 @@ pub mod bench {
                });
                let node_b_holder = NodeHolder { node: &node_b };
 
-               node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: node_b.init_features(), remote_network_address: None }).unwrap();
-               node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: node_a.init_features(), remote_network_address: None }).unwrap();
+               node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: node_b.init_features(), remote_network_address: None }, true).unwrap();
+               node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: node_a.init_features(), remote_network_address: None }, false).unwrap();
                node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap();
                node_b.handle_open_channel(&node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id()));
                node_a.handle_accept_channel(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));
@@ -8574,9 +8768,9 @@ pub mod bench {
                macro_rules! send_payment {
                        ($node_a: expr, $node_b: expr) => {
                                let usable_channels = $node_a.list_usable_channels();
-                               let payment_params = PaymentParameters::from_node_id($node_b.get_our_node_id())
+                               let payment_params = PaymentParameters::from_node_id($node_b.get_our_node_id(), TEST_FINAL_CLTV)
                                        .with_features($node_b.invoice_features());
-                               let scorer = test_utils::TestScorer::with_penalty(0);
+                               let scorer = test_utils::TestScorer::new();
                                let seed = [3u8; 32];
                                let keys_manager = KeysManager::new(&seed, 42, 42);
                                let random_seed_bytes = keys_manager.get_secure_random_bytes();
index 868b38e3fdaf30d44b766286ca280208a4d36d9d..fd867bc6ab7e07287c0572ae1cdb577e9e290ab8 100644 (file)
@@ -305,6 +305,7 @@ pub struct TestChanMonCfg {
        pub persister: test_utils::TestPersister,
        pub logger: test_utils::TestLogger,
        pub keys_manager: test_utils::TestKeysInterface,
+       pub scorer: Mutex<test_utils::TestScorer>,
 }
 
 pub struct NodeCfg<'a> {
@@ -350,6 +351,19 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
        }
 }
 
+/// If we need an unsafe pointer to a `Node` (ie to reference it in a thread
+/// pre-std::thread::scope), this provides that with `Sync`. Note that accessing some of the fields
+/// in the `Node` are not safe to use (i.e. the ones behind an `Rc`), but that's left to the caller
+/// to figure out.
+pub struct NodePtr(pub *const Node<'static, 'static, 'static>);
+impl NodePtr {
+       pub fn from_node<'a, 'b: 'a, 'c: 'b>(node: &Node<'a, 'b, 'c>) -> Self {
+               Self((node as *const Node<'a, 'b, 'c>).cast())
+       }
+}
+unsafe impl Send for NodePtr {}
+unsafe impl Sync for NodePtr {}
+
 impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
        fn drop(&mut self) {
                if !panicking() {
@@ -427,6 +441,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
                                        channel_monitors.insert(monitor.get_funding_txo().0, monitor);
                                }
 
+                               let scorer = Mutex::new(test_utils::TestScorer::new());
                                let mut w = test_utils::TestVecWriter(Vec::new());
                                self.node.write(&mut w).unwrap();
                                <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>)>::read(&mut io::Cursor::new(w.0), ChannelManagerReadArgs {
@@ -435,7 +450,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
                                        node_signer: self.keys_manager,
                                        signer_provider: self.keys_manager,
                                        fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
-                                       router: &test_utils::TestRouter::new(Arc::new(network_graph)),
+                                       router: &test_utils::TestRouter::new(Arc::new(network_graph), &scorer),
                                        chain_monitor: self.chain_monitor,
                                        tx_broadcaster: &broadcaster,
                                        logger: &self.logger,
@@ -572,12 +587,12 @@ macro_rules! get_htlc_update_msgs {
 }
 
 /// Fetches the first `msg_event` to the passed `node_id` in the passed `msg_events` vec.
-/// Returns the `msg_event`, along with an updated `msg_events` vec with the message removed.
+/// Returns the `msg_event`.
 ///
 /// Note that even though `BroadcastChannelAnnouncement` and `BroadcastChannelUpdate`
 /// `msg_events` are stored under specific peers, this function does not fetch such `msg_events` as
 /// such messages are intended to all peers.
-pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &Vec<MessageSendEvent>) -> (MessageSendEvent, Vec<MessageSendEvent>) {
+pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut Vec<MessageSendEvent>) -> MessageSendEvent {
        let ev_index = msg_events.iter().position(|e| { match e {
                MessageSendEvent::SendAcceptChannel { node_id, .. } => {
                        node_id == msg_node_id
@@ -621,6 +636,9 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &Vec<
                MessageSendEvent::BroadcastChannelUpdate { .. } => {
                        false
                },
+               MessageSendEvent::BroadcastNodeAnnouncement { .. } => {
+                       false
+               },
                MessageSendEvent::SendChannelUpdate { node_id, .. } => {
                        node_id == msg_node_id
                },
@@ -641,9 +659,7 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &Vec<
                },
        }});
        if ev_index.is_some() {
-               let mut updated_msg_events = msg_events.to_vec();
-               let ev = updated_msg_events.remove(ev_index.unwrap());
-               (ev, updated_msg_events)
+               msg_events.remove(ev_index.unwrap())
        } else {
                panic!("Couldn't find any MessageSendEvent to the node!")
        }
@@ -1010,7 +1026,7 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b,
        assert_eq!(events_7.len(), 1);
        let (announcement, bs_update) = match events_7[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
-                       (msg, update_msg)
+                       (msg, update_msg.clone().unwrap())
                },
                _ => panic!("Unexpected event"),
        };
@@ -1021,6 +1037,7 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b,
        let as_update = match events_8[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
                        assert!(*announcement == *msg);
+                       let update_msg = update_msg.clone().unwrap();
                        assert_eq!(update_msg.contents.short_channel_id, announcement.contents.short_channel_id);
                        assert_eq!(update_msg.contents.short_channel_id, bs_update.contents.short_channel_id);
                        update_msg
@@ -1031,7 +1048,7 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b,
        *node_a.network_chan_count.borrow_mut() += 1;
 
        expect_channel_ready_event(&node_b, &node_a.node.get_our_node_id());
-       ((*announcement).clone(), (*as_update).clone(), (*bs_update).clone())
+       ((*announcement).clone(), as_update, bs_update)
 }
 
 pub fn create_announced_chan_between_nodes<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) {
@@ -1344,157 +1361,6 @@ impl SendEvent {
        }
 }
 
-#[macro_export]
-/// Performs the "commitment signed dance" - the series of message exchanges which occur after a
-/// commitment update.
-macro_rules! commitment_signed_dance {
-       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */) => {
-               {
-                       check_added_monitors!($node_a, 0);
-                       assert!($node_a.node.get_and_clear_pending_msg_events().is_empty());
-                       $node_a.node.handle_commitment_signed(&$node_b.node.get_our_node_id(), &$commitment_signed);
-                       check_added_monitors!($node_a, 1);
-                       commitment_signed_dance!($node_a, $node_b, (), $fail_backwards, true, false);
-               }
-       };
-       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, true /* return extra message */, true /* return last RAA */) => {
-               {
-                       let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!($node_a, $node_b.node.get_our_node_id());
-                       check_added_monitors!($node_b, 0);
-                       assert!($node_b.node.get_and_clear_pending_msg_events().is_empty());
-                       $node_b.node.handle_revoke_and_ack(&$node_a.node.get_our_node_id(), &as_revoke_and_ack);
-                       assert!($node_b.node.get_and_clear_pending_msg_events().is_empty());
-                       check_added_monitors!($node_b, 1);
-                       $node_b.node.handle_commitment_signed(&$node_a.node.get_our_node_id(), &as_commitment_signed);
-                       let (bs_revoke_and_ack, extra_msg_option) = {
-                               let events = $node_b.node.get_and_clear_pending_msg_events();
-                               assert!(events.len() <= 2);
-                               let (node_a_event, events) = remove_first_msg_event_to_node(&$node_a.node.get_our_node_id(), &events);
-                               (match node_a_event {
-                                       MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
-                                               assert_eq!(*node_id, $node_a.node.get_our_node_id());
-                                               (*msg).clone()
-                                       },
-                                       _ => panic!("Unexpected event"),
-                               }, events.get(0).map(|e| e.clone()))
-                       };
-                       check_added_monitors!($node_b, 1);
-                       if $fail_backwards {
-                               assert!($node_a.node.get_and_clear_pending_events().is_empty());
-                               assert!($node_a.node.get_and_clear_pending_msg_events().is_empty());
-                       }
-                       (extra_msg_option, bs_revoke_and_ack)
-               }
-       };
-       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */, false /* return extra message */, true /* return last RAA */) => {
-               {
-                       check_added_monitors!($node_a, 0);
-                       assert!($node_a.node.get_and_clear_pending_msg_events().is_empty());
-                       $node_a.node.handle_commitment_signed(&$node_b.node.get_our_node_id(), &$commitment_signed);
-                       check_added_monitors!($node_a, 1);
-                       let (extra_msg_option, bs_revoke_and_ack) = commitment_signed_dance!($node_a, $node_b, (), $fail_backwards, true, true, true);
-                       assert!(extra_msg_option.is_none());
-                       bs_revoke_and_ack
-               }
-       };
-       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, true /* return extra message */) => {
-               {
-                       let (extra_msg_option, bs_revoke_and_ack) = commitment_signed_dance!($node_a, $node_b, (), $fail_backwards, true, true, true);
-                       $node_a.node.handle_revoke_and_ack(&$node_b.node.get_our_node_id(), &bs_revoke_and_ack);
-                       check_added_monitors!($node_a, 1);
-                       extra_msg_option
-               }
-       };
-       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, false /* no extra message */) => {
-               {
-                       assert!(commitment_signed_dance!($node_a, $node_b, (), $fail_backwards, true, true).is_none());
-               }
-       };
-       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr) => {
-               {
-                       commitment_signed_dance!($node_a, $node_b, $commitment_signed, $fail_backwards, true);
-                       if $fail_backwards {
-                               expect_pending_htlcs_forwardable_and_htlc_handling_failed!($node_a, vec![$crate::util::events::HTLCDestination::NextHopChannel{ node_id: Some($node_b.node.get_our_node_id()), channel_id: $commitment_signed.channel_id }]);
-                               check_added_monitors!($node_a, 1);
-
-                               let node_a_per_peer_state = $node_a.node.per_peer_state.read().unwrap();
-                               let mut number_of_msg_events = 0;
-                               for (cp_id, peer_state_mutex) in node_a_per_peer_state.iter() {
-                                       let peer_state = peer_state_mutex.lock().unwrap();
-                                       let cp_pending_msg_events = &peer_state.pending_msg_events;
-                                       number_of_msg_events += cp_pending_msg_events.len();
-                                       if cp_pending_msg_events.len() == 1 {
-                                               if let MessageSendEvent::UpdateHTLCs { .. } = cp_pending_msg_events[0] {
-                                                       assert_ne!(*cp_id, $node_b.node.get_our_node_id());
-                                               } else { panic!("Unexpected event"); }
-                                       }
-                               }
-                               // Expecting the failure backwards event to the previous hop (not `node_b`)
-                               assert_eq!(number_of_msg_events, 1);
-                       } else {
-                               assert!($node_a.node.get_and_clear_pending_msg_events().is_empty());
-                       }
-               }
-       }
-}
-
-/// Get a payment preimage and hash.
-#[macro_export]
-macro_rules! get_payment_preimage_hash {
-       ($dest_node: expr) => {
-               {
-                       get_payment_preimage_hash!($dest_node, None)
-               }
-       };
-       ($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();
-                       let payment_preimage = $crate::ln::PaymentPreimage([*payment_count; 32]);
-                       *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, $min_final_cltv_expiry_delta).unwrap();
-                       (payment_preimage, payment_hash, payment_secret)
-               }
-       };
-}
-
-#[macro_export]
-macro_rules! get_route {
-       ($send_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
-               use $crate::chain::keysinterface::EntropySource;
-               let scorer = $crate::util::test_utils::TestScorer::with_penalty(0);
-               let keys_manager = $crate::util::test_utils::TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
-               let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               $crate::routing::router::get_route(
-                       &$send_node.node.get_our_node_id(), &$payment_params, &$send_node.network_graph.read_only(),
-                       Some(&$send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
-                       $recv_value, $cltv, $send_node.logger, &scorer, &random_seed_bytes
-               )
-       }}
-}
-
-#[cfg(test)]
-#[macro_export]
-macro_rules! get_route_and_payment_hash {
-       ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
-               let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id())
-                       .with_features($recv_node.node.invoice_features());
-               $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, TEST_FINAL_CLTV)
-       }};
-       ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
-               let (payment_preimage, payment_hash, payment_secret) = $crate::get_payment_preimage_hash!($recv_node, Some($recv_value));
-               let route = $crate::get_route!($send_node, $payment_params, $recv_value, $cltv);
-               (route.unwrap(), payment_hash, payment_preimage, payment_secret)
-       }}
-}
-
 #[macro_export]
 macro_rules! expect_pending_htlcs_forwardable_conditions {
        ($node: expr, $expected_failures: expr) => {{
@@ -1585,6 +1451,164 @@ macro_rules! expect_pending_htlcs_forwardable_from_events {
                }
        }}
 }
+
+#[macro_export]
+/// Performs the "commitment signed dance" - the series of message exchanges which occur after a
+/// commitment update.
+macro_rules! commitment_signed_dance {
+       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */) => {
+               $crate::ln::functional_test_utils::do_commitment_signed_dance(&$node_a, &$node_b, &$commitment_signed, $fail_backwards, true);
+       };
+       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, true /* return extra message */, true /* return last RAA */) => {
+               $crate::ln::functional_test_utils::do_main_commitment_signed_dance(&$node_a, &$node_b, $fail_backwards)
+       };
+       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */, false /* return extra message */, true /* return last RAA */) => {
+               {
+                       check_added_monitors!($node_a, 0);
+                       assert!($node_a.node.get_and_clear_pending_msg_events().is_empty());
+                       $node_a.node.handle_commitment_signed(&$node_b.node.get_our_node_id(), &$commitment_signed);
+                       check_added_monitors!($node_a, 1);
+                       let (extra_msg_option, bs_revoke_and_ack) = $crate::ln::functional_test_utils::do_main_commitment_signed_dance(&$node_a, &$node_b, $fail_backwards);
+                       assert!(extra_msg_option.is_none());
+                       bs_revoke_and_ack
+               }
+       };
+       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, true /* return extra message */) => {
+               {
+                       let (extra_msg_option, bs_revoke_and_ack) = $crate::ln::functional_test_utils::do_main_commitment_signed_dance(&$node_a, &$node_b, $fail_backwards);
+                       $node_a.node.handle_revoke_and_ack(&$node_b.node.get_our_node_id(), &bs_revoke_and_ack);
+                       check_added_monitors!($node_a, 1);
+                       extra_msg_option
+               }
+       };
+       ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, false /* no extra message */) => {
+               assert!(commitment_signed_dance!($node_a, $node_b, (), $fail_backwards, true, true).is_none());
+       };
+       ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr) => {
+               $crate::ln::functional_test_utils::do_commitment_signed_dance(&$node_a, &$node_b, &$commitment_signed, $fail_backwards, false);
+       }
+}
+
+
+pub fn do_main_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, fail_backwards: bool) -> (Option<MessageSendEvent>, msgs::RevokeAndACK) {
+       let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!(node_a, node_b.node.get_our_node_id());
+       check_added_monitors!(node_b, 0);
+       assert!(node_b.node.get_and_clear_pending_msg_events().is_empty());
+       node_b.node.handle_revoke_and_ack(&node_a.node.get_our_node_id(), &as_revoke_and_ack);
+       assert!(node_b.node.get_and_clear_pending_msg_events().is_empty());
+       check_added_monitors!(node_b, 1);
+       node_b.node.handle_commitment_signed(&node_a.node.get_our_node_id(), &as_commitment_signed);
+       let (bs_revoke_and_ack, extra_msg_option) = {
+               let mut events = node_b.node.get_and_clear_pending_msg_events();
+               assert!(events.len() <= 2);
+               let node_a_event = remove_first_msg_event_to_node(&node_a.node.get_our_node_id(), &mut events);
+               (match node_a_event {
+                       MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
+                               assert_eq!(*node_id, node_a.node.get_our_node_id());
+                               (*msg).clone()
+                       },
+                       _ => panic!("Unexpected event"),
+               }, events.get(0).map(|e| e.clone()))
+       };
+       check_added_monitors!(node_b, 1);
+       if fail_backwards {
+               assert!(node_a.node.get_and_clear_pending_events().is_empty());
+               assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
+       }
+       (extra_msg_option, bs_revoke_and_ack)
+}
+
+pub fn do_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, commitment_signed: &msgs::CommitmentSigned, fail_backwards: bool, skip_last_step: bool) {
+       check_added_monitors!(node_a, 0);
+       assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
+       node_a.node.handle_commitment_signed(&node_b.node.get_our_node_id(), commitment_signed);
+       check_added_monitors!(node_a, 1);
+
+       commitment_signed_dance!(node_a, node_b, (), fail_backwards, true, false);
+
+       if skip_last_step { return; }
+
+       if fail_backwards {
+               expect_pending_htlcs_forwardable_and_htlc_handling_failed!(node_a,
+                       vec![crate::util::events::HTLCDestination::NextHopChannel{ node_id: Some(node_b.node.get_our_node_id()), channel_id: commitment_signed.channel_id }]);
+               check_added_monitors!(node_a, 1);
+
+               let node_a_per_peer_state = node_a.node.per_peer_state.read().unwrap();
+               let mut number_of_msg_events = 0;
+               for (cp_id, peer_state_mutex) in node_a_per_peer_state.iter() {
+                       let peer_state = peer_state_mutex.lock().unwrap();
+                       let cp_pending_msg_events = &peer_state.pending_msg_events;
+                       number_of_msg_events += cp_pending_msg_events.len();
+                       if cp_pending_msg_events.len() == 1 {
+                               if let MessageSendEvent::UpdateHTLCs { .. } = cp_pending_msg_events[0] {
+                                       assert_ne!(*cp_id, node_b.node.get_our_node_id());
+                               } else { panic!("Unexpected event"); }
+                       }
+               }
+               // Expecting the failure backwards event to the previous hop (not `node_b`)
+               assert_eq!(number_of_msg_events, 1);
+       } else {
+               assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
+       }
+}
+
+/// Get a payment preimage and hash.
+#[macro_export]
+macro_rules! get_payment_preimage_hash {
+       ($dest_node: expr) => {
+               {
+                       get_payment_preimage_hash!($dest_node, None)
+               }
+       };
+       ($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();
+                       let payment_preimage = $crate::ln::PaymentPreimage([*payment_count; 32]);
+                       *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, $min_final_cltv_expiry_delta).unwrap();
+                       (payment_preimage, payment_hash, payment_secret)
+               }
+       };
+}
+
+#[macro_export]
+macro_rules! get_route {
+       ($send_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
+               use $crate::chain::keysinterface::EntropySource;
+               let scorer = $crate::util::test_utils::TestScorer::new();
+               let keys_manager = $crate::util::test_utils::TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+               $crate::routing::router::get_route(
+                       &$send_node.node.get_our_node_id(), &$payment_params, &$send_node.network_graph.read_only(),
+                       Some(&$send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
+                       $recv_value, $cltv, $send_node.logger, &scorer, &random_seed_bytes
+               )
+       }}
+}
+
+#[cfg(test)]
+#[macro_export]
+macro_rules! get_route_and_payment_hash {
+       ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
+               let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id(), TEST_FINAL_CLTV)
+                       .with_features($recv_node.node.invoice_features());
+               $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, TEST_FINAL_CLTV)
+       }};
+       ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
+               let (payment_preimage, payment_hash, payment_secret) = $crate::get_payment_preimage_hash!($recv_node, Some($recv_value));
+               let route = $crate::get_route!($send_node, $payment_params, $recv_value, $cltv);
+               (route.unwrap(), payment_hash, payment_preimage, payment_secret)
+       }}
+}
+
 #[macro_export]
 #[cfg(any(test, feature = "_bench_unstable", feature = "_test_utils"))]
 macro_rules! expect_payment_claimable {
@@ -1789,17 +1813,18 @@ macro_rules! expect_payment_failed {
 }
 
 pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
-       node: &'a Node<'b, 'c, 'd>, payment_failed_event: Event, expected_payment_hash: PaymentHash,
+       payment_failed_events: Vec<Event>, expected_payment_hash: PaymentHash,
        expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e>
 ) {
-       let expected_payment_id = match payment_failed_event {
+       if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); }
+       let expected_payment_id = match &payment_failed_events[0] {
                Event::PaymentPathFailed { payment_hash, payment_failed_permanently, path, retry, payment_id, network_update, short_channel_id,
                        #[cfg(test)]
                        error_code,
                        #[cfg(test)]
                        error_data, .. } => {
-                       assert_eq!(payment_hash, expected_payment_hash, "unexpected payment_hash");
-                       assert_eq!(payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value");
+                       assert_eq!(*payment_hash, expected_payment_hash, "unexpected payment_hash");
+                       assert_eq!(*payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value");
                        assert!(retry.is_some(), "expected retry.is_some()");
                        assert_eq!(retry.as_ref().unwrap().final_value_msat, path.last().unwrap().fee_msat, "Retry amount should match last hop in path");
                        assert_eq!(retry.as_ref().unwrap().payment_params.payee_pubkey, path.last().unwrap().pubkey, "Retry payee node_id should match last hop in path");
@@ -1828,7 +1853,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
                                        },
                                        Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) if chan_closed => {
                                                if let Some(scid) = conditions.expected_blamed_scid {
-                                                       assert_eq!(short_channel_id, scid);
+                                                       assert_eq!(*short_channel_id, scid);
                                                }
                                                assert!(is_permanent);
                                        },
@@ -1842,10 +1867,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
                _ => panic!("Unexpected event"),
        };
        if !conditions.expected_mpp_parts_remain {
-               node.node.abandon_payment(expected_payment_id);
-               let events = node.node.get_and_clear_pending_events();
-               assert_eq!(events.len(), 1);
-               match events[0] {
+               match &payment_failed_events[1] {
                        Event::PaymentFailed { ref payment_hash, ref payment_id } => {
                                assert_eq!(*payment_hash, expected_payment_hash, "unexpected second payment_hash");
                                assert_eq!(*payment_id, expected_payment_id);
@@ -1859,9 +1881,8 @@ pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>(
        node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_payment_failed_permanently: bool,
        conditions: PaymentFailedConditions<'e>
 ) {
-       let mut events = node.node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 1);
-       expect_payment_failed_conditions_event(node, events.pop().unwrap(), expected_payment_hash, expected_payment_failed_permanently, conditions);
+       let events = node.node.get_and_clear_pending_events();
+       expect_payment_failed_conditions_event(events, expected_payment_hash, expected_payment_failed_permanently, conditions);
 }
 
 pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) -> PaymentId {
@@ -1932,8 +1953,7 @@ pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
        let mut events = origin_node.node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), expected_route.len());
        for (path_idx, expected_path) in expected_route.iter().enumerate() {
-               let (ev, updated_events) = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &events);
-               events = updated_events;
+               let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events);
                // Once we've gotten through all the HTLCs, the last one should result in a
                // PaymentClaimable (but each previous one should not!), .
                let expect_payment = path_idx == expected_route.len() - 1;
@@ -1992,9 +2012,8 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>,
        } else {
                for expected_path in expected_paths.iter() {
                        // For MPP payments, we always want the message to the first node in the path.
-                       let (ev, updated_events) = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &events);
+                       let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events);
                        per_path_msgs.push(msgs_from_ev!(&ev));
-                       events = updated_events;
                }
        }
 
@@ -2096,7 +2115,7 @@ pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route:
 pub const TEST_FINAL_CLTV: u32 = 70;
 
 pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
-       let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(expected_route.last().unwrap().node.invoice_features());
        let route = get_route!(origin_node, payment_params, recv_value, TEST_FINAL_CLTV).unwrap();
        assert_eq!(route.paths.len(), 1);
@@ -2110,10 +2129,10 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route:
 }
 
 pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64)  {
-       let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(expected_route.last().unwrap().node.invoice_features());
        let network_graph = origin_node.network_graph.read_only();
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let seed = [0u8; 32];
        let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
@@ -2148,22 +2167,6 @@ pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe
 }
 
 pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) {
-       let expected_payment_id = pass_failed_payment_back_no_abandon(origin_node, expected_paths_slice, skip_last, our_payment_hash);
-       if !skip_last {
-               origin_node.node.abandon_payment(expected_payment_id.unwrap());
-               let events = origin_node.node.get_and_clear_pending_events();
-               assert_eq!(events.len(), 1);
-               match events[0] {
-                       Event::PaymentFailed { ref payment_hash, ref payment_id } => {
-                               assert_eq!(*payment_hash, our_payment_hash, "unexpected second payment_hash");
-                               assert_eq!(*payment_id, expected_payment_id.unwrap());
-                       }
-                       _ => panic!("Unexpected second event"),
-               }
-       }
-}
-
-pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) -> Option<PaymentId> {
        let mut expected_paths: Vec<_> = expected_paths_slice.iter().collect();
        check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len());
 
@@ -2187,8 +2190,6 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b
        per_path_msgs.sort_unstable_by(|(_, node_id_a), (_, node_id_b)| node_id_a.cmp(node_id_b));
        expected_paths.sort_unstable_by(|path_a, path_b| path_a[path_a.len() - 2].node.get_our_node_id().cmp(&path_b[path_b.len() - 2].node.get_our_node_id()));
 
-       let mut expected_payment_id = None;
-
        for (i, (expected_route, (path_msgs, next_hop))) in expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() {
                let mut next_msgs = Some(path_msgs);
                let mut expected_next_node = next_hop;
@@ -2236,8 +2237,9 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b
                        assert!(origin_node.node.get_and_clear_pending_msg_events().is_empty());
                        commitment_signed_dance!(origin_node, prev_node, next_msgs.as_ref().unwrap().1, false);
                        let events = origin_node.node.get_and_clear_pending_events();
-                       assert_eq!(events.len(), 1);
-                       expected_payment_id = Some(match events[0] {
+                       if i == expected_paths.len() - 1 { assert_eq!(events.len(), 2); } else { assert_eq!(events.len(), 1); }
+
+                       let expected_payment_id = match events[0] {
                                Event::PaymentPathFailed { payment_hash, payment_failed_permanently, all_paths_failed, ref path, ref payment_id, .. } => {
                                        assert_eq!(payment_hash, our_payment_hash);
                                        assert!(payment_failed_permanently);
@@ -2248,7 +2250,16 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b
                                        payment_id.unwrap()
                                },
                                _ => panic!("Unexpected event"),
-                       });
+                       };
+                       if i == expected_paths.len() - 1 {
+                               match events[1] {
+                                       Event::PaymentFailed { ref payment_hash, ref payment_id } => {
+                                               assert_eq!(*payment_hash, our_payment_hash, "unexpected second payment_hash");
+                                               assert_eq!(*payment_id, expected_payment_id);
+                                       }
+                                       _ => panic!("Unexpected second event"),
+                               }
+                       }
                }
        }
 
@@ -2257,8 +2268,6 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b
        assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_events().is_empty());
        assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty());
        check_added_monitors!(expected_paths[0].last().unwrap(), 0);
-
-       expected_payment_id
 }
 
 pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash)  {
@@ -2278,8 +2287,9 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec<TestChanMonCfg> {
                let persister = test_utils::TestPersister::new();
                let seed = [i as u8; 32];
                let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
+               let scorer = Mutex::new(test_utils::TestScorer::new());
 
-               chan_mon_cfgs.push(TestChanMonCfg { tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager });
+               chan_mon_cfgs.push(TestChanMonCfg { tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager, scorer });
        }
 
        chan_mon_cfgs
@@ -2297,7 +2307,7 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec<TestChanMon
                        logger: &chanmon_cfgs[i].logger,
                        tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster,
                        fee_estimator: &chanmon_cfgs[i].fee_estimator,
-                       router: test_utils::TestRouter::new(network_graph.clone()),
+                       router: test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[i].scorer),
                        chain_monitor,
                        keys_manager: &chanmon_cfgs[i].keys_manager,
                        node_seed: seed,
@@ -2364,8 +2374,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
 
        for i in 0..node_count {
                for j in (i+1)..node_count {
-                       nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &msgs::Init { features: nodes[j].override_init_features.borrow().clone().unwrap_or_else(|| nodes[j].node.init_features()), remote_network_address: None }).unwrap();
-                       nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &msgs::Init { features: nodes[i].override_init_features.borrow().clone().unwrap_or_else(|| nodes[i].node.init_features()), remote_network_address: None }).unwrap();
+                       nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &msgs::Init { features: nodes[j].override_init_features.borrow().clone().unwrap_or_else(|| nodes[j].node.init_features()), remote_network_address: None }, true).unwrap();
+                       nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &msgs::Init { features: nodes[i].override_init_features.borrow().clone().unwrap_or_else(|| nodes[i].node.init_features()), remote_network_address: None }, false).unwrap();
                }
        }
 
@@ -2648,9 +2658,9 @@ macro_rules! handle_chan_reestablish_msgs {
 /// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas
 /// for claims/fails they are separated out.
 pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, send_channel_ready: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_htlc_fails: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool))  {
-       node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: node_b.node.init_features(), remote_network_address: None }).unwrap();
+       node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: node_b.node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b);
-       node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: node_a.node.init_features(), remote_network_address: None }).unwrap();
+       node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: node_a.node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a);
 
        if send_channel_ready.0 {
index 371fcfa77642f0b55637733a649ab3f739f4b800..d6d2972d0736e3ec642fccee7363e44329560584 100644 (file)
@@ -1802,7 +1802,7 @@ fn test_channel_reserve_holding_cell_htlcs() {
 
        // attempt to send amt_msat > their_max_htlc_value_in_flight_msat
        {
-               let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                        .with_features(nodes[2].node.invoice_features()).with_max_channel_saturation_power_of_half(0);
                let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, recv_value_0, TEST_FINAL_CLTV);
                route.paths[0].last_mut().unwrap().fee_msat += 1;
@@ -1827,7 +1827,7 @@ fn test_channel_reserve_holding_cell_htlcs() {
                        break;
                }
 
-               let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                        .with_features(nodes[2].node.invoice_features()).with_max_channel_saturation_power_of_half(0);
                let route = get_route!(nodes[0], payment_params, recv_value_0, TEST_FINAL_CLTV).unwrap();
                let (payment_preimage, ..) = send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], recv_value_0);
@@ -2747,7 +2747,7 @@ fn test_htlc_on_chain_success() {
                },
                _ => panic!()
        }
-       let events = nodes[1].node.get_and_clear_pending_msg_events();
+       let mut events = nodes[1].node.get_and_clear_pending_msg_events();
        {
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
                assert_eq!(added_monitors.len(), 2);
@@ -2757,8 +2757,8 @@ fn test_htlc_on_chain_success() {
        }
        assert_eq!(events.len(), 3);
 
-       let (nodes_2_event, events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events);
-       let (nodes_0_event, events) = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &events);
+       let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
+       let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events);
 
        match nodes_2_event {
                MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { .. }, node_id: _ } => {},
@@ -3170,7 +3170,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
        connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
 
        let events = nodes[1].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), if deliver_bs_raa { 2 + nodes.len() - 1 } else { 3 + nodes.len() });
+       assert_eq!(events.len(), if deliver_bs_raa { 3 + nodes.len() - 1 } else { 4 + nodes.len() });
        match events[0] {
                Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => { },
                _ => panic!("Unexepected event"),
@@ -3181,29 +3181,21 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                },
                _ => panic!("Unexpected event"),
        }
-       if !deliver_bs_raa {
-               match events[2] {
-                       Event::PendingHTLCsForwardable { .. } => { },
-                       _ => panic!("Unexpected event"),
-               };
-               nodes[1].node.abandon_payment(PaymentId(fourth_payment_hash.0));
-               let payment_failed_events = nodes[1].node.get_and_clear_pending_events();
-               assert_eq!(payment_failed_events.len(), 1);
-               match payment_failed_events[0] {
-                       Event::PaymentFailed { ref payment_hash, .. } => {
-                               assert_eq!(*payment_hash, fourth_payment_hash);
-                       },
-                       _ => panic!("Unexpected event"),
-               }
+       match events[2] {
+               Event::PaymentFailed { ref payment_hash, .. } => {
+                       assert_eq!(*payment_hash, fourth_payment_hash);
+               },
+               _ => panic!("Unexpected event"),
        }
+
        nodes[1].node.process_pending_htlc_forwards();
        check_added_monitors!(nodes[1], 1);
 
        let mut events = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), if deliver_bs_raa { 4 } else { 3 });
 
-       let events = if deliver_bs_raa {
-               let (nodes_2_event, events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events);
+       if deliver_bs_raa {
+               let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
                match nodes_2_event {
                        MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
                                assert_eq!(nodes[2].node.get_our_node_id(), *node_id);
@@ -3214,10 +3206,9 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                        },
                        _ => panic!("Unexpected event"),
                }
-               events
-       } else { events };
+       }
 
-       let (nodes_2_event, events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events);
+       let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        match nodes_2_event {
                MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage { channel_id, ref data } }, node_id: _ } => {
                        assert_eq!(channel_id, chan_2.2);
@@ -3226,7 +3217,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                _ => panic!("Unexpected event"),
        }
 
-       let (nodes_0_event, events) = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &events);
+       let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events);
        match nodes_0_event {
                MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed, .. } } => {
                        assert!(update_add_htlcs.is_empty());
@@ -3242,7 +3233,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                        commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false, true);
 
                        let events = nodes[0].node.get_and_clear_pending_events();
-                       assert_eq!(events.len(), 3);
+                       assert_eq!(events.len(), 6);
                        match events[0] {
                                Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
                                        assert!(failed_htlcs.insert(payment_hash.0));
@@ -3255,19 +3246,37 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                                _ => panic!("Unexpected event"),
                        }
                        match events[1] {
+                               Event::PaymentFailed { ref payment_hash, .. } => {
+                                       assert_eq!(*payment_hash, first_payment_hash);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+                       match events[2] {
                                Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
                                        assert!(failed_htlcs.insert(payment_hash.0));
                                        assert!(network_update.is_some());
                                },
                                _ => panic!("Unexpected event"),
                        }
-                       match events[2] {
+                       match events[3] {
+                               Event::PaymentFailed { ref payment_hash, .. } => {
+                                       assert_eq!(*payment_hash, second_payment_hash);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+                       match events[4] {
                                Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
                                        assert!(failed_htlcs.insert(payment_hash.0));
                                        assert!(network_update.is_some());
                                },
                                _ => panic!("Unexpected event"),
                        }
+                       match events[5] {
+                               Event::PaymentFailed { ref payment_hash, .. } => {
+                                       assert_eq!(*payment_hash, third_payment_hash);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
                },
                _ => panic!("Unexpected event"),
        }
@@ -3354,7 +3363,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
                nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &update_add_htlc);
        }
        let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 2);
+       assert_eq!(events.len(), 3);
        // Check that Alice fails backward the pending HTLC from the second payment.
        match events[0] {
                Event::PaymentPathFailed { payment_hash, .. } => {
@@ -3363,6 +3372,12 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
                _ => panic!("Unexpected event"),
        }
        match events[1] {
+               Event::PaymentFailed { payment_hash, .. } => {
+                       assert_eq!(payment_hash, failed_payment_hash);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       match events[2] {
                Event::ChannelClosed { reason: ClosureReason::ProcessingError { ref err }, .. } => {
                        assert_eq!(err, "Remote side tried to send a 0-msat HTLC");
                },
@@ -3509,8 +3524,8 @@ fn test_dup_events_on_peer_disconnect() {
        nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &claim_msgs.update_fulfill_htlcs[0]);
        expect_payment_sent_without_paths!(nodes[0], payment_preimage);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (false, false));
        expect_payment_path_successful!(nodes[0]);
@@ -3550,8 +3565,8 @@ fn test_peer_disconnected_before_funding_broadcasted() {
 
        // Ensure that the channel is closed with `ClosureReason::DisconnectedPeer` when the peers are
        // disconnected before the funding transaction was broadcasted.
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        check_closed_event!(nodes[0], 1, ClosureReason::DisconnectedPeer);
        check_closed_event!(nodes[1], 1, ClosureReason::DisconnectedPeer);
@@ -3567,8 +3582,8 @@ fn test_simple_peer_disconnect() {
        create_announced_chan_between_nodes(&nodes, 0, 1);
        create_announced_chan_between_nodes(&nodes, 1, 2);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
@@ -3576,8 +3591,8 @@ fn test_simple_peer_disconnect() {
        fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_2);
        claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        let (payment_preimage_3, payment_hash_3, _) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000);
@@ -3585,8 +3600,8 @@ fn test_simple_peer_disconnect() {
        let payment_hash_5 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
        let payment_hash_6 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_preimage_3);
        fail_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_hash_5);
@@ -3594,7 +3609,7 @@ fn test_simple_peer_disconnect() {
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (1, 0), (1, 0), (false, false));
        {
                let events = nodes[0].node.get_and_clear_pending_events();
-               assert_eq!(events.len(), 3);
+               assert_eq!(events.len(), 4);
                match events[0] {
                        Event::PaymentSent { payment_preimage, payment_hash, .. } => {
                                assert_eq!(payment_preimage, payment_preimage_3);
@@ -3603,14 +3618,20 @@ fn test_simple_peer_disconnect() {
                        _ => panic!("Unexpected event"),
                }
                match events[1] {
+                       Event::PaymentPathSuccessful { .. } => {},
+                       _ => panic!("Unexpected event"),
+               }
+               match events[2] {
                        Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } => {
                                assert_eq!(payment_hash, payment_hash_5);
                                assert!(payment_failed_permanently);
                        },
                        _ => panic!("Unexpected event"),
                }
-               match events[2] {
-                       Event::PaymentPathSuccessful { .. } => {},
+               match events[3] {
+                       Event::PaymentFailed { payment_hash, .. } => {
+                               assert_eq!(payment_hash, payment_hash_5);
+                       },
                        _ => panic!("Unexpected event"),
                }
        }
@@ -3680,8 +3701,8 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
                }
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        if messages_delivered < 3 {
                if simulate_broken_lnd {
                        // lnd has a long-standing bug where they send a channel_ready prior to a
@@ -3730,8 +3751,8 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
                };
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        nodes[1].node.process_pending_htlc_forwards();
@@ -3813,8 +3834,8 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
                }
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        if messages_delivered < 2 {
                reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (false, false));
                if messages_delivered < 1 {
@@ -3839,9 +3860,10 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
        if messages_delivered == 1 || messages_delivered == 2 {
                expect_payment_path_successful!(nodes[0]);
        }
-
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       if messages_delivered <= 5 {
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       }
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        if messages_delivered > 2 {
@@ -3954,13 +3976,13 @@ fn test_drop_messages_peer_disconnect_dual_htlc() {
                _ => panic!("Unexpected event"),
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
 
@@ -4641,10 +4663,10 @@ fn test_onchain_to_onchain_claim() {
                _ => panic!("Unexpected event"),
        }
        check_added_monitors!(nodes[1], 1);
-       let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
+       let mut msg_events = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(msg_events.len(), 3);
-       let (nodes_2_event, msg_events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &msg_events);
-       let (nodes_0_event, msg_events) = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &msg_events);
+       let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut msg_events);
+       let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut msg_events);
 
        match nodes_2_event {
                MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { .. }, node_id: _ } => {},
@@ -4716,7 +4738,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        // 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())
+       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV - 40)
                .with_features(nodes[3].node.invoice_features());
        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);
@@ -5122,7 +5144,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
        }
 
        let as_events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(as_events.len(), if announce_latest { 5 } else { 3 });
+       assert_eq!(as_events.len(), if announce_latest { 10 } else { 6 });
        let mut as_failds = HashSet::new();
        let mut as_updates = 0;
        for event in as_events.iter() {
@@ -5136,6 +5158,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
                        if network_update.is_some() {
                                as_updates += 1;
                        }
+               } else if let &Event::PaymentFailed { .. } = event {
                } else { panic!("Unexpected event"); }
        }
        assert!(as_failds.contains(&payment_hash_1));
@@ -5147,7 +5170,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
        assert!(as_failds.contains(&payment_hash_6));
 
        let bs_events = nodes[1].node.get_and_clear_pending_events();
-       assert_eq!(bs_events.len(), if announce_latest { 4 } else { 3 });
+       assert_eq!(bs_events.len(), if announce_latest { 8 } else { 6 });
        let mut bs_failds = HashSet::new();
        let mut bs_updates = 0;
        for event in bs_events.iter() {
@@ -5161,6 +5184,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
                        if network_update.is_some() {
                                bs_updates += 1;
                        }
+               } else if let &Event::PaymentFailed { .. } = event {
                } else { panic!("Unexpected event"); }
        }
        assert!(bs_failds.contains(&payment_hash_1));
@@ -5257,7 +5281,8 @@ fn test_key_derivation_params() {
        let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
        let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &chanmon_cfgs[0].persister, &keys_manager);
        let network_graph = Arc::new(NetworkGraph::new(chanmon_cfgs[0].chain_source.genesis_hash, &chanmon_cfgs[0].logger));
-       let router = test_utils::TestRouter::new(network_graph.clone());
+       let scorer = Mutex::new(test_utils::TestScorer::new());
+       let router = test_utils::TestRouter::new(network_graph.clone(), &scorer);
        let node = NodeCfg { chain_source: &chanmon_cfgs[0].chain_source, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, router, chain_monitor, keys_manager: &keys_manager, network_graph, node_seed: seed, override_init_features: alloc::rc::Rc::new(core::cell::RefCell::new(None)) };
        let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
        node_cfgs.remove(0);
@@ -5668,7 +5693,7 @@ fn test_fail_holding_cell_htlc_upon_free() {
 
        // Check that the payment failed to be sent out.
        let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 1);
+       assert_eq!(events.len(), 2);
        match &events[0] {
                &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, .. } => {
                        assert_eq!(PaymentId(our_payment_hash.0), *payment_id.as_ref().unwrap());
@@ -5680,6 +5705,12 @@ fn test_fail_holding_cell_htlc_upon_free() {
                },
                _ => panic!("Unexpected event"),
        }
+       match &events[1] {
+               &Event::PaymentFailed { ref payment_hash, .. } => {
+                       assert_eq!(our_payment_hash.clone(), *payment_hash);
+               },
+               _ => panic!("Unexpected event"),
+       }
 }
 
 // Test that if multiple HTLCs are released from the holding cell and one is
@@ -5753,7 +5784,7 @@ fn test_free_and_fail_holding_cell_htlcs() {
 
        // Check that the second payment failed to be sent out.
        let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 1);
+       assert_eq!(events.len(), 2);
        match &events[0] {
                &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, .. } => {
                        assert_eq!(payment_id_2, *payment_id.as_ref().unwrap());
@@ -5765,6 +5796,12 @@ fn test_free_and_fail_holding_cell_htlcs() {
                },
                _ => panic!("Unexpected event"),
        }
+       match &events[1] {
+               &Event::PaymentFailed { ref payment_hash, .. } => {
+                       assert_eq!(payment_hash_2.clone(), *payment_hash);
+               },
+               _ => panic!("Unexpected event"),
+       }
 
        // Complete the first payment and the RAA from the fee update.
        let (payment_event, send_raa_event) = {
@@ -6009,7 +6046,7 @@ fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
        let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0)
                .with_features(nodes[1].node.invoice_features());
        let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000, 0);
        route.paths[0].last_mut().unwrap().cltv_expiry_delta = 500000001;
@@ -6255,12 +6292,12 @@ fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
 
        //Disconnect and Reconnect
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]);
@@ -6647,7 +6684,7 @@ fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
        }
 
        let events_5 = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events_5.len(), 1);
+       assert_eq!(events_5.len(), 2);
 
        // Expect a PaymentPathFailed event with a ChannelFailure network update for the channel between
        // the node originating the error to its next hop.
@@ -6661,6 +6698,12 @@ fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
                },
                _ => panic!("Unexpected event"),
        }
+       match events_5[1] {
+               Event::PaymentFailed { payment_hash, .. } => {
+                       assert_eq!(payment_hash, our_payment_hash);
+               },
+               _ => panic!("Unexpected event"),
+       }
 
        // TODO: Test actual removal of channel from NetworkGraph when it's implemented.
 }
@@ -6732,7 +6775,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
        connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
        let events = nodes[0].node.get_and_clear_pending_events();
        // Only 2 PaymentPathFailed events should show up, over-dust HTLC has to be failed by timeout tx
-       assert_eq!(events.len(), 2);
+       assert_eq!(events.len(), 4);
        let mut first_failed = false;
        for event in events {
                match event {
@@ -6743,7 +6786,8 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
                                } else {
                                        assert_eq!(payment_hash, payment_hash_2);
                                }
-                       }
+                       },
+                       Event::PaymentFailed { .. } => {}
                        _ => panic!("Unexpected event"),
                }
        }
@@ -6925,9 +6969,9 @@ fn test_check_htlc_underpaying() {
        // Create some initial channels
        create_announced_chan_between_nodes(&nodes, 0, 1);
 
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
-       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(nodes[1].node.invoice_features());
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).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, None).unwrap();
@@ -6988,8 +7032,8 @@ fn test_announce_disable_channels() {
        create_announced_chan_between_nodes(&nodes, 0, 1);
 
        // Disconnect peers
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        nodes[0].node.timer_tick_occurred(); // Enabled -> DisabledStaged
        nodes[0].node.timer_tick_occurred(); // DisabledStaged -> Disabled
@@ -7009,10 +7053,10 @@ fn test_announce_disable_channels() {
                }
        }
        // Reconnect peers
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 3);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 3);
 
@@ -7068,7 +7112,7 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000);
 
        let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
-       let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 30)
                .with_features(nodes[0].node.invoice_features());
        let (route,_, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_params, 3000000, 30);
        send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000);
@@ -7174,13 +7218,13 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000);
        // Lock HTLC in both directions (using a slightly lower CLTV delay to provide timely RBF bumps)
-       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(nodes[1].node.invoice_features());
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 50).with_features(nodes[1].node.invoice_features());
+       let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None,
                3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0;
-       let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(nodes[0].node.invoice_features());
+       let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 50).with_features(nodes[0].node.invoice_features());
        let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None,
                3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
@@ -8142,7 +8186,7 @@ fn test_update_err_monitor_lockdown() {
                let mut node_0_per_peer_lock;
                let mut node_0_peer_state_lock;
                let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2);
-               if let Ok((_, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
+               if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
                        assert_eq!(watchtower.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::PermanentFailure);
                        assert_eq!(nodes[0].chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::Completed);
                } else { assert!(false); }
@@ -8236,7 +8280,7 @@ fn test_concurrent_monitor_claim() {
                let mut node_0_per_peer_lock;
                let mut node_0_peer_state_lock;
                let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2);
-               if let Ok((_, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
+               if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
                        // Watchtower Alice should already have seen the block and reject the update
                        assert_eq!(watchtower_alice.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::PermanentFailure);
                        assert_eq!(watchtower_bob.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::Completed);
@@ -8692,9 +8736,9 @@ fn test_duplicate_chan_id() {
        };
        check_added_monitors!(nodes[0], 0);
        nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
-       // At this point we'll try to add a duplicate channel monitor, which will be rejected, but
-       // still needs to be cleared here.
-       check_added_monitors!(nodes[1], 1);
+       // At this point we'll look up if the channel_id is present and immediately fail the channel
+       // without trying to persist the `ChannelMonitor`.
+       check_added_monitors!(nodes[1], 0);
 
        // ...still, nodes[1] will reject the duplicate channel.
        {
@@ -8788,13 +8832,11 @@ fn test_error_chans_closed() {
                _ => panic!("Unexpected event"),
        }
        // Note that at this point users of a standard PeerHandler will end up calling
-       // peer_disconnected with no_connection_possible set to false, duplicating the
-       // close-all-channels logic. That's OK, we don't want to end up not force-closing channels for
-       // users with their own peer handling logic. We duplicate the call here, however.
+       // peer_disconnected.
        assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
        assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), true);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
        assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2);
 }
@@ -8910,8 +8952,8 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t
        create_announced_chan_between_nodes(&nodes, 0, 1);
        let (chan_announce, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2);
        let (_, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
-       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()).unwrap();
        check_closed_broadcast!(nodes[1], true);
@@ -8976,7 +9018,7 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
 
        let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(nodes[1].node.invoice_features());
        let route = get_route!(nodes[0], payment_params, 10_000, TEST_FINAL_CLTV).unwrap();
 
@@ -9032,9 +9074,11 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
                commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false);
 
                let failure_events = nodes[0].node.get_and_clear_pending_events();
-               assert_eq!(failure_events.len(), 2);
+               assert_eq!(failure_events.len(), 4);
                if let Event::PaymentPathFailed { .. } = failure_events[0] {} else { panic!(); }
-               if let Event::PaymentPathFailed { .. } = failure_events[1] {} else { panic!(); }
+               if let Event::PaymentFailed { .. } = failure_events[1] {} else { panic!(); }
+               if let Event::PaymentPathFailed { .. } = failure_events[2] {} else { panic!(); }
+               if let Event::PaymentFailed { .. } = failure_events[3] {} else { panic!(); }
        } else {
                // Let the second HTLC fail and claim the first
                expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]);
@@ -9045,7 +9089,7 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
                nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
                commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false);
 
-               expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain());
+               expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new());
 
                claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
        }
@@ -9081,7 +9125,7 @@ fn test_inconsistent_mpp_params() {
        create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0);
        let chan_2_3 =create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(nodes[3].node.invoice_features());
        let mut route = get_route!(nodes[0], payment_params, 15_000_000, TEST_FINAL_CLTV).unwrap();
        assert_eq!(route.paths.len(), 2);
@@ -9167,7 +9211,27 @@ fn test_inconsistent_mpp_params() {
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), true, None);
 
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
+       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 3);
+       match events[0] {
+               Event::PaymentSent { payment_hash, .. } => { // The payment was abandoned earlier, so the fee paid will be None
+                       assert_eq!(payment_hash, our_payment_hash);
+               },
+               _ => panic!("Unexpected event")
+       }
+       match events[1] {
+               Event::PaymentPathSuccessful { payment_hash, .. } => {
+                       assert_eq!(payment_hash.unwrap(), our_payment_hash);
+               },
+               _ => panic!("Unexpected event")
+       }
+       match events[2] {
+               Event::PaymentPathSuccessful { payment_hash, .. } => {
+                       assert_eq!(payment_hash.unwrap(), our_payment_hash);
+               },
+               _ => panic!("Unexpected event")
+       }
 }
 
 #[test]
@@ -9182,11 +9246,11 @@ fn test_keysend_payments_to_public_node() {
        let payer_pubkey = nodes[0].node.get_our_node_id();
        let payee_pubkey = nodes[1].node.get_our_node_id();
        let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey),
+               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
                final_value_msat: 10000,
                final_cltv_expiry_delta: 40,
        };
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
 
@@ -9210,18 +9274,16 @@ fn test_keysend_payments_to_private_node() {
 
        let payer_pubkey = nodes[0].node.get_our_node_id();
        let payee_pubkey = nodes[1].node.get_our_node_id();
-       nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
 
        let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
        let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey),
+               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
                final_value_msat: 10000,
                final_cltv_expiry_delta: 40,
        };
        let network_graph = nodes[0].network_graph.clone();
        let first_hops = nodes[0].node.list_usable_channels();
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let route = find_route(
                &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
@@ -9285,7 +9347,7 @@ fn test_double_partial_claim() {
 
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 2);
-       let (node_1_msgs, _events) = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &events);
+       let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_1_msgs, false, None);
 
        // At this point nodes[3] has received one half of the payment, and the user goes to handle
@@ -9603,7 +9665,7 @@ fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash
 
        create_chan_between_nodes(&nodes[0], &nodes[1]);
 
-       let payment_parameters = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id());
+       let payment_parameters = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), final_cltv_expiry_delta as u32);
        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));
index 088cf8661f8487b577a2a71e2a4b68f77236f7ea..c4435b470ca8c6deb8618fada682e9cd063fcc17 100644 (file)
@@ -1241,11 +1241,10 @@ fn do_test_revoked_counterparty_commitment_balances(confirm_htlc_spend_first: bo
        test_spendable_output(&nodes[1], &as_revoked_txn[0]);
 
        let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events();
-       expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(),
-               dust_payment_hash, false, PaymentFailedConditions::new());
-       expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(),
+       expect_payment_failed_conditions_event(payment_failed_events[..2].to_vec(),
                missing_htlc_payment_hash, false, PaymentFailedConditions::new());
-       assert!(payment_failed_events.is_empty());
+       expect_payment_failed_conditions_event(payment_failed_events[2..].to_vec(),
+               dust_payment_hash, false, PaymentFailedConditions::new());
 
        connect_blocks(&nodes[1], 1);
        test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 2 } else { 3 }]);
index 40817aa3c7d5494e6d4340427d666a5a4fe363ed..6e49a46f08a02a25065652e28cf3895afc031fe8 100644 (file)
@@ -46,6 +46,8 @@ use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer
 
 use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 
+use crate::routing::gossip::NodeId;
+
 /// 21 million * 10^8 * 1000
 pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000;
 
@@ -663,7 +665,7 @@ pub struct UnsignedNodeAnnouncement {
        pub timestamp: u32,
        /// The `node_id` this announcement originated from (don't rebroadcast the `node_announcement` back
        /// to this node).
-       pub node_id: PublicKey,
+       pub node_id: NodeId,
        /// An RGB color for UI purposes
        pub rgb: [u8; 3],
        /// An alias, for UI purposes.
@@ -698,13 +700,13 @@ pub struct UnsignedChannelAnnouncement {
        /// The short channel ID
        pub short_channel_id: u64,
        /// One of the two `node_id`s which are endpoints of this channel
-       pub node_id_1: PublicKey,
+       pub node_id_1: NodeId,
        /// The other of the two `node_id`s which are endpoints of this channel
-       pub node_id_2: PublicKey,
+       pub node_id_2: NodeId,
        /// The funding key for the first node
-       pub bitcoin_key_1: PublicKey,
+       pub bitcoin_key_1: NodeId,
        /// The funding key for the second node
-       pub bitcoin_key_2: PublicKey,
+       pub bitcoin_key_2: NodeId,
        pub(crate) excess_data: Vec<u8>,
 }
 /// A [`channel_announcement`] message to be sent to or received from a peer.
@@ -991,21 +993,15 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider {
        fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures);
 
        // Connection loss/reestablish:
-       /// Indicates a connection to the peer failed/an existing connection was lost. If no connection
-       /// is believed to be possible in the future (eg they're sending us messages we don't
-       /// understand or indicate they require unknown feature bits), `no_connection_possible` is set
-       /// and any outstanding channels should be failed.
-       ///
-       /// Note that in some rare cases this may be called without a corresponding
-       /// [`Self::peer_connected`].
-       fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
+       /// Indicates a connection to the peer failed/an existing connection was lost.
+       fn peer_disconnected(&self, their_node_id: &PublicKey);
 
        /// Handle a peer reconnecting, possibly generating `channel_reestablish` message(s).
        ///
        /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
        /// with us. Implementors should be somewhat conservative about doing so, however, as other
        /// message handlers may still wish to communicate with this peer.
-       fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init) -> Result<(), ()>;
+       fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init, inbound: bool) -> Result<(), ()>;
        /// Handle an incoming `channel_reestablish` message from the given peer.
        fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish);
 
@@ -1055,7 +1051,7 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
        /// the node *after* the provided pubkey and including up to one announcement immediately
        /// higher (as defined by `<PublicKey as Ord>::cmp`) than `starting_point`.
        /// If `None` is provided for `starting_point`, we start at the first node.
-       fn get_next_node_announcement(&self, starting_point: Option<&PublicKey>) -> Option<NodeAnnouncement>;
+       fn get_next_node_announcement(&self, starting_point: Option<&NodeId>) -> Option<NodeAnnouncement>;
        /// Called when a connection is established with a peer. This can be used to
        /// perform routing table synchronization using a strategy defined by the
        /// implementor.
@@ -1063,7 +1059,7 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
        /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
        /// with us. Implementors should be somewhat conservative about doing so, however, as other
        /// message handlers may still wish to communicate with this peer.
-       fn peer_connected(&self, their_node_id: &PublicKey, init: &Init) -> Result<(), ()>;
+       fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>;
        /// Handles the reply of a query we initiated to learn about channels
        /// for a given range of blocks. We can expect to receive one or more
        /// replies to a single query.
@@ -1080,6 +1076,13 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
        /// list of `short_channel_id`s.
        fn handle_query_short_channel_ids(&self, their_node_id: &PublicKey, msg: QueryShortChannelIds) -> Result<(), LightningError>;
 
+       // Handler queueing status:
+       /// Indicates that there are a large number of [`ChannelAnnouncement`] (or other) messages
+       /// pending some async action. While there is no guarantee of the rate of future messages, the
+       /// caller should seek to reduce the rate of new gossip messages handled, especially
+       /// [`ChannelAnnouncement`]s.
+       fn processing_queue_high(&self) -> bool;
+
        // Handler information:
        /// Gets the node feature flags which this handler itself supports. All available handlers are
        /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`]
@@ -1103,13 +1106,10 @@ pub trait OnionMessageHandler : OnionMessageProvider {
        /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
        /// with us. Implementors should be somewhat conservative about doing so, however, as other
        /// message handlers may still wish to communicate with this peer.
-       fn peer_connected(&self, their_node_id: &PublicKey, init: &Init) -> Result<(), ()>;
+       fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>;
        /// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
        /// drop and refuse to forward onion messages to this peer.
-       ///
-       /// Note that in some rare cases this may be called without a corresponding
-       /// [`Self::peer_connected`].
-       fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
+       fn peer_disconnected(&self, their_node_id: &PublicKey);
 
        // Handler information:
        /// Gets the node feature flags which this handler itself supports. All available handlers are
@@ -1843,7 +1843,7 @@ impl Readable for UnsignedNodeAnnouncement {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
                let features: NodeFeatures = Readable::read(r)?;
                let timestamp: u32 = Readable::read(r)?;
-               let node_id: PublicKey = Readable::read(r)?;
+               let node_id: NodeId = Readable::read(r)?;
                let mut rgb = [0; 3];
                r.read_exact(&mut rgb)?;
                let alias: [u8; 32] = Readable::read(r)?;
@@ -2053,6 +2053,7 @@ mod tests {
        use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
        use crate::ln::msgs;
        use crate::ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
+       use crate::routing::gossip::NodeId;
        use crate::util::ser::{Writeable, Readable, Hostname};
 
        use bitcoin::hashes::hex::FromHex;
@@ -2160,10 +2161,10 @@ mod tests {
                        features,
                        chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
                        short_channel_id: 2316138423780173,
-                       node_id_1: pubkey_1,
-                       node_id_2: pubkey_2,
-                       bitcoin_key_1: pubkey_3,
-                       bitcoin_key_2: pubkey_4,
+                       node_id_1: NodeId::from_pubkey(&pubkey_1),
+                       node_id_2: NodeId::from_pubkey(&pubkey_2),
+                       bitcoin_key_1: NodeId::from_pubkey(&pubkey_3),
+                       bitcoin_key_2: NodeId::from_pubkey(&pubkey_4),
                        excess_data: if excess_data { vec![10, 0, 0, 20, 0, 0, 30, 0, 0, 40] } else { Vec::new() },
                };
                let channel_announcement = msgs::ChannelAnnouncement {
@@ -2245,7 +2246,7 @@ mod tests {
                let unsigned_node_announcement = msgs::UnsignedNodeAnnouncement {
                        features,
                        timestamp: 20190119,
-                       node_id: pubkey_1,
+                       node_id: NodeId::from_pubkey(&pubkey_1),
                        rgb: [32; 3],
                        alias: [16;32],
                        addresses,
index 1ecdb5a87fc4ce746718db5a2c916e32e56c744e..da5aadb83065af7d6de274c30a021e4b9b05fc23 100644 (file)
@@ -166,7 +166,7 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
        commitment_signed_dance!(nodes[0], nodes[1], update_1_0.commitment_signed, false, true);
 
        let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 1);
+       assert_eq!(events.len(), 2);
        if let &Event::PaymentPathFailed { ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, ref error_code, .. } = &events[0] {
                assert_eq!(*payment_failed_permanently, !expected_retryable);
                assert_eq!(*all_paths_failed, true);
@@ -212,10 +212,7 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
        } else {
                panic!("Unexpected event");
        }
-       nodes[0].node.abandon_payment(payment_id);
-       let events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 1);
-       match events[0] {
+       match events[1] {
                Event::PaymentFailed { payment_hash: ev_payment_hash, payment_id: ev_payment_id } => {
                        assert_eq!(*payment_hash, ev_payment_hash);
                        assert_eq!(payment_id, ev_payment_id);
@@ -579,8 +576,8 @@ fn test_onion_failure() {
        let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test("channel_disabled", 0, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
                // disconnect event to the channel between nodes[1] ~ nodes[2]
-               nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
-               nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+               nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
+               nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        }, true, Some(UPDATE|20), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id));
        reconnect_nodes(&nodes[1], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
@@ -655,7 +652,7 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) {
                        htlc_maximum_msat: None,
                        htlc_minimum_msat: None,
                }])];
-               let payment_params = PaymentParameters::from_node_id(*channel_to_update_counterparty)
+               let payment_params = PaymentParameters::from_node_id(*channel_to_update_counterparty, TEST_FINAL_CLTV)
                        .with_features(nodes[2].node.invoice_features())
                        .with_route_hints(hop_hints);
                get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, PAYMENT_AMT, TEST_FINAL_CLTV)
@@ -802,7 +799,7 @@ fn test_always_create_tlv_format_onion_payloads() {
        create_announced_chan_between_nodes(&nodes, 0, 1);
        create_announced_chan_between_nodes(&nodes, 1, 2);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(InvoiceFeatures::empty());
        let (route, _payment_hash, _payment_preimage, _payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 40000, TEST_FINAL_CLTV);
 
@@ -902,7 +899,7 @@ macro_rules! get_phantom_route {
        ($nodes: expr, $amt: expr, $channel: expr) => {{
                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)
+               let payment_params = PaymentParameters::from_node_id(phantom_pubkey, TEST_FINAL_CLTV)
                        .with_features($nodes[1].node.invoice_features())
                        .with_route_hints(vec![RouteHint(vec![
                                        RouteHintHop {
@@ -928,7 +925,7 @@ macro_rules! get_phantom_route {
                                                htlc_maximum_msat: None,
                                        }
                ])]);
-               let scorer = test_utils::TestScorer::with_penalty(0);
+               let scorer = test_utils::TestScorer::new();
                let network_graph = $nodes[0].network_graph.read_only();
                (get_route(
                        &$nodes[0].node.get_our_node_id(), &payment_params, &network_graph,
index 8867b2e96ae14c3e75bb960d5dd9fa97ed10d746..1d8d46a916a01cfdfa1cd783df48c7023a6c39e4 100644 (file)
@@ -15,7 +15,8 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
 
 use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
 use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, MIN_HTLC_RELAY_HOLDING_CELL_MILLIS, PaymentId};
+use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, PaymentId};
+use crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA;
 use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils::HTLCFailReason;
 use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, RoutePath, Router};
@@ -29,7 +30,6 @@ 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;
@@ -41,12 +41,13 @@ pub(crate) enum PendingOutboundPayment {
                session_privs: HashSet<[u8; 32]>,
        },
        Retryable {
-               retry_strategy: Retry,
+               retry_strategy: Option<Retry>,
                attempts: PaymentAttempts,
-               route_params: Option<RouteParameters>,
+               payment_params: Option<PaymentParameters>,
                session_privs: HashSet<[u8; 32]>,
                payment_hash: PaymentHash,
                payment_secret: Option<PaymentSecret>,
+               keysend_preimage: Option<PaymentPreimage>,
                pending_amt_msat: u64,
                /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+.
                pending_fee_msat: Option<u64>,
@@ -63,13 +64,8 @@ pub(crate) enum PendingOutboundPayment {
                payment_hash: Option<PaymentHash>,
                timer_ticks_without_htlcs: u8,
        },
-       /// When a payer gives up trying to retry a payment, they inform us, letting us generate a
-       /// `PaymentFailed` event when all HTLCs have irrevocably failed. This avoids a number of race
-       /// conditions in MPP-aware payment retriers (1), where the possibility of multiple
-       /// `PaymentPathFailed` events with `all_paths_failed` can be pending at once, confusing a
-       /// downstream event handler as to when a payment has actually failed.
-       ///
-       /// (1) <https://github.com/lightningdevkit/rust-lightning/issues/1164>
+       /// When we've decided to give up retrying a payment, we mark it as abandoned so we can eventually
+       /// generate a `PaymentFailed` event when all HTLCs have irrevocably failed.
        Abandoned {
                session_privs: HashSet<[u8; 32]>,
                payment_hash: PaymentHash,
@@ -82,15 +78,37 @@ impl PendingOutboundPayment {
                        attempts.count += 1;
                }
        }
+       fn is_auto_retryable_now(&self) -> bool {
+               match self {
+                       PendingOutboundPayment::Retryable { retry_strategy: Some(strategy), attempts, .. } => {
+                               strategy.is_retryable_now(&attempts)
+                       },
+                       _ => false,
+               }
+       }
        fn is_retryable_now(&self) -> bool {
-               if let PendingOutboundPayment::Retryable { retry_strategy, attempts, .. } = self {
-                       return retry_strategy.is_retryable_now(&attempts)
+               match self {
+                       PendingOutboundPayment::Retryable { retry_strategy: None, .. } => {
+                               // We're handling retries manually, we can always retry.
+                               true
+                       },
+                       PendingOutboundPayment::Retryable { retry_strategy: Some(strategy), attempts, .. } => {
+                               strategy.is_retryable_now(&attempts)
+                       },
+                       _ => false,
+               }
+       }
+       fn payment_parameters(&mut self) -> Option<&mut PaymentParameters> {
+               match self {
+                       PendingOutboundPayment::Retryable { payment_params: Some(ref mut params), .. } => {
+                               Some(params)
+                       },
+                       _ => None,
                }
-               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);
+               if let PendingOutboundPayment::Retryable { payment_params: Some(params), .. } = self {
+                       params.previously_failed_channels.push(scid);
                }
        }
        pub(super) fn is_fulfilled(&self) -> bool {
@@ -139,13 +157,13 @@ impl PendingOutboundPayment {
                let our_payment_hash;
                core::mem::swap(&mut session_privs, match self {
                        PendingOutboundPayment::Legacy { .. } |
-                               PendingOutboundPayment::Fulfilled { .. } =>
+                       PendingOutboundPayment::Fulfilled { .. } =>
                                return Err(()),
-                               PendingOutboundPayment::Retryable { session_privs, payment_hash, .. } |
-                                       PendingOutboundPayment::Abandoned { session_privs, payment_hash, .. } => {
-                                               our_payment_hash = *payment_hash;
-                                               session_privs
-                                       },
+                       PendingOutboundPayment::Retryable { session_privs, payment_hash, .. } |
+                       PendingOutboundPayment::Abandoned { session_privs, payment_hash, .. } => {
+                               our_payment_hash = *payment_hash;
+                               session_privs
+                       },
                });
                *self = PendingOutboundPayment::Abandoned { session_privs, payment_hash: our_payment_hash };
                Ok(())
@@ -212,12 +230,15 @@ impl PendingOutboundPayment {
 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.
+       /// Each attempt may be multiple HTLCs along multiple paths if the router decides to split up a
+       /// retry, and may retry multiple failed HTLCs at once if they failed around the same time and
+       /// were retried along a route from a single call to [`Router::find_route`].
        Attempts(usize),
        #[cfg(not(feature = "no-std"))]
-       /// Time elapsed before abandoning retries for a payment.
+       /// Time elapsed before abandoning retries for a payment. At least one attempt at payment is made;
+       /// see [`PaymentParameters::expiry_time`] to avoid any attempt at payment after a specific time.
+       ///
+       /// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
        Timeout(core::time::Duration),
 }
 
@@ -289,9 +310,35 @@ impl<T: Time> Display for PaymentAttemptsUsingTime<T> {
        }
 }
 
-/// 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.
+/// Indicates an immediate error on [`ChannelManager::send_payment_with_retry`]. Further errors
+/// may be surfaced later via [`Event::PaymentPathFailed`] and [`Event::PaymentFailed`].
+///
+/// [`ChannelManager::send_payment_with_retry`]: crate::ln::channelmanager::ChannelManager::send_payment_with_retry
+/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+/// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
+#[derive(Clone, Debug)]
+pub enum RetryableSendFailure {
+       /// The provided [`PaymentParameters::expiry_time`] indicated that the payment has expired. Note
+       /// that this error is *not* caused by [`Retry::Timeout`].
+       ///
+       /// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
+       PaymentExpired,
+       /// We were unable to find a route to the destination.
+       RouteNotFound,
+       /// Indicates that a payment for the provided [`PaymentId`] is already in-flight and has not
+       /// yet completed (i.e. generated an [`Event::PaymentSent`] or [`Event::PaymentFailed`]).
+       ///
+       /// [`PaymentId`]: crate::ln::channelmanager::PaymentId
+       /// [`Event::PaymentSent`]: crate::util::events::Event::PaymentSent
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
+       DuplicatePayment,
+}
+
+/// If a payment fails to send with [`ChannelManager::send_payment`], 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.
+///
+/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
 #[derive(Clone, Debug)]
 pub enum PaymentSendFailure {
        /// A parameter which was passed to send_payment was invalid, preventing us from attempting to
@@ -299,68 +346,58 @@ pub enum PaymentSendFailure {
        ///
        /// You can freely resend the payment in full (with the parameter error fixed).
        ///
-       /// Because the payment failed outright, no payment tracking is done, you do not need to call
-       /// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
-       /// for this payment.
+       /// Because the payment failed outright, no payment tracking is done and no
+       /// [`Event::PaymentPathFailed`] or [`Event::PaymentFailed`] events will be generated.
        ///
-       /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
-       /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
+       /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
        ParameterError(APIError),
        /// A parameter in a single path which was passed to send_payment was invalid, preventing us
        /// from attempting to send the payment at all.
        ///
        /// You can freely resend the payment in full (with the parameter error fixed).
        ///
+       /// Because the payment failed outright, no payment tracking is done and no
+       /// [`Event::PaymentPathFailed`] or [`Event::PaymentFailed`] events will be generated.
+       ///
        /// The results here are ordered the same as the paths in the route object which was passed to
        /// send_payment.
        ///
-       /// Because the payment failed outright, no payment tracking is done, you do not need to call
-       /// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
-       /// for this payment.
-       ///
-       /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
-       /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
+       /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
        PathParameterError(Vec<Result<(), APIError>>),
        /// All paths which were attempted failed to send, with no channel state change taking place.
        /// You can freely resend the payment in full (though you probably want to do so over different
        /// paths than the ones selected).
        ///
-       /// Because the payment failed outright, no payment tracking is done, you do not need to call
-       /// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
-       /// for this payment.
+       /// Because the payment failed outright, no payment tracking is done and no
+       /// [`Event::PaymentPathFailed`] or [`Event::PaymentFailed`] events will be generated.
        ///
-       /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
-       /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
+       /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
        AllFailedResendSafe(Vec<APIError>),
        /// Indicates that a payment for the provided [`PaymentId`] is already in-flight and has not
-       /// yet completed (i.e. generated an [`Event::PaymentSent`]) or been abandoned (via
-       /// [`ChannelManager::abandon_payment`]).
+       /// yet completed (i.e. generated an [`Event::PaymentSent`] or [`Event::PaymentFailed`]).
        ///
        /// [`PaymentId`]: crate::ln::channelmanager::PaymentId
        /// [`Event::PaymentSent`]: crate::util::events::Event::PaymentSent
-       /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
        DuplicatePayment,
-       /// Some paths which were attempted failed to send, though possibly not all. At least some
-       /// paths have irrevocably committed to the HTLC and retrying the payment in full would result
-       /// in over-/re-payment.
+       /// Some paths that were attempted failed to send, though some paths may have succeeded. At least
+       /// some paths have irrevocably committed to the HTLC.
        ///
-       /// The results here are ordered the same as the paths in the route object which was passed to
-       /// send_payment, and any `Err`s which are not [`APIError::MonitorUpdateInProgress`] can be
-       /// safely retried via [`ChannelManager::retry_payment`].
+       /// The results here are ordered the same as the paths in the route object that was passed to
+       /// send_payment.
        ///
-       /// Any entries which contain `Err(APIError::MonitorUpdateInprogress)` or `Ok(())` MUST NOT be
-       /// retried as they will result in over-/re-payment. These HTLCs all either successfully sent
-       /// (in the case of `Ok(())`) or will send once a [`MonitorEvent::Completed`] is provided for
-       /// the next-hop channel with the latest update_id.
+       /// Any entries that contain `Err(APIError::MonitorUpdateInprogress)` will send once a
+       /// [`MonitorEvent::Completed`] is provided for the next-hop channel with the latest update_id.
        ///
-       /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
        /// [`MonitorEvent::Completed`]: crate::chain::channelmonitor::MonitorEvent::Completed
        PartialFailure {
-               /// The errors themselves, in the same order as the route hops.
+               /// The errors themselves, in the same order as the paths from the route.
                results: Vec<Result<(), APIError>>,
                /// If some paths failed without irrevocably committing to the new HTLC(s), this will
-               /// contain a [`RouteParameters`] object which can be used to calculate a new route that
-               /// will pay all remaining unpaid balance.
+               /// contain a [`RouteParameters`] object for the failing paths.
                failed_paths_retry: Option<RouteParameters>,
                /// The payment id for the payment, which is now at least partially pending.
                payment_id: PaymentId,
@@ -369,32 +406,36 @@ pub enum PaymentSendFailure {
 
 pub(super) struct OutboundPayments {
        pub(super) pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
+       pub(super) retry_lock: Mutex<()>,
 }
 
 impl OutboundPayments {
        pub(super) fn new() -> Self {
                Self {
-                       pending_outbound_payments: Mutex::new(HashMap::new())
+                       pending_outbound_payments: Mutex::new(HashMap::new()),
+                       retry_lock: Mutex::new(()),
                }
        }
 
-       pub(super) fn send_payment<R: Deref, ES: Deref, NS: Deref, F>(
+       pub(super) fn send_payment<R: Deref, ES: Deref, NS: Deref, IH, SP, L: Deref>(
                &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>
+               first_hops: Vec<ChannelDetails>, compute_inflight_htlcs: IH, entropy_source: &ES,
+               node_signer: &NS, best_block_height: u32, logger: &L,
+               pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: SP,
+       ) -> Result<(), RetryableSendFailure>
        where
                R::Target: Router,
                ES::Target: EntropySource,
                NS::Target: NodeSigner,
-               F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+               L::Target: Logger,
+               IH: Fn() -> InFlightHtlcs,
+               SP: 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 })
+               self.send_payment_internal(payment_id, payment_hash, payment_secret, None, retry_strategy,
+                       route_params, router, first_hops, &compute_inflight_htlcs, entropy_source, node_signer,
+                       best_block_height, logger, pending_events, &send_payment_along_path)
        }
 
        pub(super) fn send_payment_with_route<ES: Deref, NS: Deref, F>(
@@ -408,13 +449,38 @@ 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, Retry::Attempts(0), None, entropy_source, best_block_height)?;
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, None, route, None, 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>(
+       pub(super) fn send_spontaneous_payment<R: Deref, ES: Deref, NS: Deref, IH, SP, L: Deref>(
+               &self, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId,
+               retry_strategy: Retry, route_params: RouteParameters, router: &R,
+               first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES,
+               node_signer: &NS, best_block_height: u32, logger: &L,
+               pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: SP
+       ) -> Result<PaymentHash, RetryableSendFailure>
+       where
+               R::Target: Router,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               L::Target: Logger,
+               IH: Fn() -> InFlightHtlcs,
+               SP: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                        u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>,
+       {
+               let preimage = payment_preimage
+                       .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes()));
+               let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner());
+               self.send_payment_internal(payment_id, payment_hash, &None, Some(preimage), retry_strategy,
+                       route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer,
+                       best_block_height, logger, pending_events, send_payment_along_path)
+                       .map(|()| payment_hash)
+       }
+
+       pub(super) fn send_spontaneous_payment_with_route<ES: Deref, NS: Deref, F>(
                &self, route: &Route, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId,
                entropy_source: &ES, node_signer: &NS, best_block_height: u32, send_payment_along_path: F
        ) -> Result<PaymentHash, PaymentSendFailure>
@@ -424,12 +490,10 @@ impl OutboundPayments {
                F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
                   u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
        {
-               let preimage = match payment_preimage {
-                       Some(p) => p,
-                       None => PaymentPreimage(entropy_source.get_secure_random_bytes()),
-               };
+               let preimage = payment_preimage
+                       .unwrap_or_else(|| 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, Retry::Attempts(0), None, entropy_source, best_block_height)?;
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?;
 
                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),
@@ -442,7 +506,8 @@ impl OutboundPayments {
 
        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,
+               best_block_height: u32, pending_events: &Mutex<Vec<events::Event>>, logger: &L,
+               send_payment_along_path: SP,
        )
        where
                R::Target: Router,
@@ -454,170 +519,293 @@ impl OutboundPayments {
                FH: Fn() -> Vec<ChannelDetails>,
                L::Target: Logger,
        {
+               let _single_thread = self.retry_lock.lock().unwrap();
                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 pmt.is_auto_retryable_now() {
+                                       if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, payment_params: Some(params), .. } = pmt {
                                                if pending_amt_msat < total_msat {
-                                                       retry_id_route_params = Some((*pmt_id, params.clone()));
-                                                       pmt.increment_attempts();
+                                                       retry_id_route_params = Some((*pmt_id, RouteParameters {
+                                                               final_value_msat: *total_msat - *pending_amt_msat,
+                                                               final_cltv_expiry_delta:
+                                                                       if let Some(delta) = params.final_cltv_expiry_delta { delta }
+                                                                       else {
+                                                                               debug_assert!(false, "We always set the final_cltv_expiry_delta when a path fails");
+                                                                               LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA.into()
+                                                                       },
+                                                               payment_params: params.clone(),
+                                                       }));
                                                        break
                                                }
                                        }
                                }
                        }
+                       core::mem::drop(outbounds);
                        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);
-                               }
+                               self.retry_payment_internal(payment_id, route_params, router, first_hops(), &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, &send_payment_along_path)
                        } else { break }
                }
+
+               let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+               outbounds.retain(|pmt_id, pmt| {
+                       let mut retain = true;
+                       if !pmt.is_auto_retryable_now() && pmt.remaining_parts() == 0 {
+                               if pmt.mark_abandoned().is_ok() {
+                                       pending_events.lock().unwrap().push(events::Event::PaymentFailed {
+                                               payment_id: *pmt_id,
+                                               payment_hash: pmt.payment_hash().expect("PendingOutboundPayments::Retryable always has a payment hash set"),
+                                       });
+                                       retain = false;
+                               }
+                       }
+                       retain
+               });
        }
 
-       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>
+       pub(super) fn needs_abandon(&self) -> bool {
+               let outbounds = self.pending_outbound_payments.lock().unwrap();
+               outbounds.iter().any(|(_, pmt)|
+                       !pmt.is_auto_retryable_now() && pmt.remaining_parts() == 0 && !pmt.is_fulfilled())
+       }
+
+       /// Errors immediately on [`RetryableSendFailure`] error conditions. Otherwise, further errors may
+       /// be surfaced asynchronously via [`Event::PaymentPathFailed`] and [`Event::PaymentFailed`].
+       ///
+       /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+       /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
+       fn send_payment_internal<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
+               &self, payment_id: PaymentId, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>,
+               keysend_preimage: Option<PaymentPreimage>, retry_strategy: Retry, route_params: RouteParameters,
+               router: &R, first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES,
+               node_signer: &NS, best_block_height: u32, logger: &L,
+               pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: SP,
+       ) -> Result<(), RetryableSendFailure>
        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>
+               L::Target: Logger,
+               IH: Fn() -> InFlightHtlcs,
+               SP: 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)),
-                               }))
+                               return Err(RetryableSendFailure::PaymentExpired)
                        }
                }
 
                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,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), &inflight_htlcs()
+               ).map_err(|_| RetryableSendFailure::RouteNotFound)?;
+
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret,
+                       payment_id, keysend_preimage, &route, Some(retry_strategy),
+                       Some(route_params.payment_params.clone()), entropy_source, best_block_height)
+                       .map_err(|_| RetryableSendFailure::DuplicatePayment)?;
+
+               let res = 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);
+               log_info!(logger, "Result sending payment with id {}: {:?}", log_bytes!(payment_id.0), res);
+               if let Err(e) = res {
+                       self.handle_pay_route_err(e, payment_id, payment_hash, route, route_params, router, first_hops, &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, &send_payment_along_path);
                }
+               Ok(())
        }
 
-       pub(super) fn retry_payment_with_route<ES: Deref, NS: Deref, F>(
-               &self, route: &Route, payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32,
-               send_payment_along_path: F
-       ) -> Result<(), PaymentSendFailure>
+       fn retry_payment_internal<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
+               &self, payment_id: PaymentId, route_params: RouteParameters, router: &R,
+               first_hops: Vec<ChannelDetails>, inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS,
+               best_block_height: u32, logger: &L, pending_events: &Mutex<Vec<events::Event>>,
+               send_payment_along_path: &SP,
+       )
        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>
+               L::Target: Logger,
+               IH: Fn() -> InFlightHtlcs,
+               SP: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                   u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
        {
-               const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
+               #[cfg(feature = "std")] {
+                       if has_expired(&route_params) {
+                               log_error!(logger, "Payment params expired on retry, abandoning payment {}", log_bytes!(payment_id.0));
+                               self.abandon_payment(payment_id, pending_events);
+                               return
+                       }
+               }
+
+               let route = match router.find_route(
+                       &node_signer.get_node_id(Recipient::Node).unwrap(), &route_params,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), &inflight_htlcs()
+               ) {
+                       Ok(route) => route,
+                       Err(e) => {
+                               log_error!(logger, "Failed to find a route on retry, abandoning payment {}: {:#?}", log_bytes!(payment_id.0), e);
+                               self.abandon_payment(payment_id, pending_events);
+                               return
+                       }
+               };
                for path in route.paths.iter() {
                        if path.len() == 0 {
-                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                       err: "length-0 path in route".to_string()
-                               }))
+                               log_error!(logger, "length-0 path in route");
+                               self.abandon_payment(payment_id, pending_events);
+                               return
                        }
                }
 
+               const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
                let mut onion_session_privs = Vec::with_capacity(route.paths.len());
                for _ in 0..route.paths.len() {
                        onion_session_privs.push(entropy_source.get_secure_random_bytes());
                }
 
-               let (total_msat, payment_hash, payment_secret) = {
+               macro_rules! abandon_with_entry {
+                       ($payment_id: expr, $payment_hash: expr, $payment: expr, $pending_events: expr) => {
+                               if $payment.get_mut().mark_abandoned().is_ok() && $payment.get().remaining_parts() == 0 {
+                                       $pending_events.lock().unwrap().push(events::Event::PaymentFailed {
+                                               payment_id: $payment_id,
+                                               payment_hash: $payment_hash,
+                                       });
+                                       $payment.remove();
+                               }
+                       }
+               }
+               let (total_msat, payment_hash, payment_secret, keysend_preimage) = {
                        let mut outbounds = self.pending_outbound_payments.lock().unwrap();
-                       match outbounds.get_mut(&payment_id) {
-                               Some(payment) => {
-                                       let res = match payment {
+                       match outbounds.entry(payment_id) {
+                               hash_map::Entry::Occupied(mut payment) => {
+                                       let res = match payment.get() {
                                                PendingOutboundPayment::Retryable {
-                                                       total_msat, payment_hash, payment_secret, pending_amt_msat, ..
+                                                       total_msat, payment_hash, keysend_preimage, payment_secret, pending_amt_msat, ..
                                                } => {
                                                        let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum();
                                                        if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 {
-                                                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                                                       err: format!("retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat).to_string()
-                                                               }))
+                                                               log_error!(logger, "retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat);
+                                                               let payment_hash = *payment_hash;
+                                                               abandon_with_entry!(payment_id, payment_hash, payment, pending_events);
+                                                               return
                                                        }
-                                                       (*total_msat, *payment_hash, *payment_secret)
+                                                       (*total_msat, *payment_hash, *payment_secret, *keysend_preimage)
                                                },
                                                PendingOutboundPayment::Legacy { .. } => {
-                                                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                                               err: "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102".to_string()
-                                                       }))
+                                                       log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
+                                                       return
                                                },
                                                PendingOutboundPayment::Fulfilled { .. } => {
-                                                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                                               err: "Payment already completed".to_owned()
-                                                       }));
+                                                       log_error!(logger, "Payment already completed");
+                                                       return
                                                },
                                                PendingOutboundPayment::Abandoned { .. } => {
-                                                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                                               err: "Payment already abandoned (with some HTLCs still pending)".to_owned()
-                                                       }));
+                                                       log_error!(logger, "Payment already abandoned (with some HTLCs still pending)");
+                                                       return
                                                },
                                        };
+                                       if !payment.get().is_retryable_now() {
+                                               log_error!(logger, "Retries exhausted for payment id {}", log_bytes!(payment_id.0));
+                                               abandon_with_entry!(payment_id, res.1, payment, pending_events);
+                                               return
+                                       }
+                                       payment.get_mut().increment_attempts();
                                        for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.iter()) {
-                                               assert!(payment.insert(*session_priv_bytes, path));
+                                               assert!(payment.get_mut().insert(*session_priv_bytes, path));
                                        }
                                        res
                                },
-                               None =>
-                                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
-                                               err: format!("Payment with ID {} not found", log_bytes!(payment_id.0)),
-                                       })),
+                               hash_map::Entry::Vacant(_) => {
+                                       log_error!(logger, "Payment with ID {} not found", log_bytes!(payment_id.0));
+                                       return
+                               }
                        }
                };
-               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)
+               let res = self.pay_route_internal(&route, payment_hash, &payment_secret, keysend_preimage,
+                       payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height,
+                       &send_payment_along_path);
+               log_info!(logger, "Result retrying payment id {}: {:?}", log_bytes!(payment_id.0), res);
+               if let Err(e) = res {
+                       self.handle_pay_route_err(e, payment_id, payment_hash, route, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
+               }
+       }
+
+       fn handle_pay_route_err<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
+               &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, route: Route,
+               mut route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>,
+               inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L,
+               pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: &SP,
+       )
+       where
+               R::Target: Router,
+               ES::Target: EntropySource,
+               NS::Target: NodeSigner,
+               L::Target: Logger,
+               IH: Fn() -> InFlightHtlcs,
+               SP: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+                   u32, PaymentId, &Option<PaymentPreimage>, [u8; 32]) -> Result<(), APIError>
+       {
+               match err {
+                       PaymentSendFailure::AllFailedResendSafe(errs) => {
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, errs.into_iter().map(|e| Err(e)), pending_events);
+                               self.retry_payment_internal(payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
+                       },
+                       PaymentSendFailure::PartialFailure { failed_paths_retry: Some(mut retry), results, .. } => {
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), pending_events);
+                               // 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.
+                               self.retry_payment_internal(payment_id, retry, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
+                       },
+                       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.
+                       },
+                       PaymentSendFailure::PathParameterError(results) => {
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, results.into_iter(), pending_events);
+                               self.abandon_payment(payment_id, pending_events);
+                       },
+                       PaymentSendFailure::ParameterError(e) => {
+                               log_error!(logger, "Failed to send to route due to parameter error: {:?}. Your router is buggy", e);
+                               self.abandon_payment(payment_id, pending_events);
+                       },
+                       PaymentSendFailure::DuplicatePayment => debug_assert!(false), // unreachable
+               }
+       }
+
+       fn push_path_failed_evs_and_scids<I: ExactSizeIterator + Iterator<Item = Result<(), APIError>>>(
+               payment_id: PaymentId, payment_hash: PaymentHash, route_params: &mut RouteParameters,
+               paths: Vec<Vec<RouteHop>>, path_results: I, pending_events: &Mutex<Vec<events::Event>>
+       ) {
+               let mut events = pending_events.lock().unwrap();
+               debug_assert_eq!(paths.len(), path_results.len());
+               for (path, path_res) in paths.into_iter().zip(path_results) {
+                       if let Err(e) = path_res {
+                               let failed_scid = if let APIError::InvalidRoute { .. } = e {
+                                       None
+                               } else {
+                                       let scid = path[0].short_channel_id;
+                                       route_params.payment_params.previously_failed_channels.push(scid);
+                                       Some(scid)
+                               };
+                               events.push(events::Event::PaymentPathFailed {
+                                       payment_id: Some(payment_id),
+                                       payment_hash,
+                                       payment_failed_permanently: false,
+                                       network_update: None,
+                                       all_paths_failed: false,
+                                       path,
+                                       short_channel_id: failed_scid,
+                                       retry: None,
+                                       #[cfg(test)]
+                                       error_code: None,
+                                       #[cfg(test)]
+                                       error_data: None,
+                               });
+                       }
+               }
        }
 
        pub(super) fn send_probe<ES: Deref, NS: Deref, F>(
@@ -641,7 +829,7 @@ 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, Retry::Attempts(0), None, entropy_source, best_block_height)?;
+               let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, None, &route, None, None, entropy_source, best_block_height)?;
 
                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)),
@@ -655,15 +843,15 @@ impl OutboundPayments {
        #[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, retry_strategy: Retry, entropy_source: &ES, best_block_height: u32
+               route: &Route, retry_strategy: Option<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, retry_strategy, None, entropy_source, best_block_height)
+               self.add_new_pending_payment(payment_hash, payment_secret, payment_id, None, 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, retry_strategy: Retry, route_params: Option<RouteParameters>,
-               entropy_source: &ES, best_block_height: u32
+               keysend_preimage: Option<PaymentPreimage>, route: &Route, retry_strategy: Option<Retry>,
+               payment_params: Option<PaymentParameters>, 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() {
@@ -677,12 +865,13 @@ impl OutboundPayments {
                                let payment = entry.insert(PendingOutboundPayment::Retryable {
                                        retry_strategy,
                                        attempts: PaymentAttempts::new(),
-                                       route_params,
+                                       payment_params,
                                        session_privs: HashSet::new(),
                                        pending_amt_msat: 0,
                                        pending_fee_msat: Some(0),
                                        payment_hash,
                                        payment_secret,
+                                       keysend_preimage,
                                        starting_block_height: best_block_height,
                                        total_msat: route.get_total_amount(),
                                });
@@ -789,7 +978,9 @@ impl OutboundPayments {
                                                Some(RouteParameters {
                                                        payment_params: payment_params.clone(),
                                                        final_value_msat: pending_amt_unsent,
-                                                       final_cltv_expiry_delta: max_unsent_cltv_delta,
+                                                       final_cltv_expiry_delta:
+                                                               if let Some(delta) = payment_params.final_cltv_expiry_delta { delta }
+                                                               else { max_unsent_cltv_delta },
                                                })
                                        } else { None }
                                } else { None },
@@ -819,8 +1010,8 @@ impl OutboundPayments {
                        .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`.
+       // If we failed to send any paths, remove the new PaymentId from the `pending_outbound_payments`
+       // map as the payment is free to be resent.
        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();
@@ -936,64 +1127,107 @@ impl OutboundPayments {
                });
        }
 
+       // Returns a bool indicating whether a PendingHTLCsForwardable event should be generated.
        pub(super) fn fail_htlc<L: Deref>(
                &self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason,
                path: &Vec<RouteHop>, session_priv: &SecretKey, payment_id: &PaymentId,
                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 {
+       ) -> bool 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 payment_is_probe = payment_is_probe(payment_hash, &payment_id, probing_cookie_secret);
                let mut session_priv_bytes = [0; 32];
                session_priv_bytes.copy_from_slice(&session_priv[..]);
                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+
+               // If any payments already need retry, there's no need to generate a redundant
+               // `PendingHTLCsForwardable`.
+               let already_awaiting_retry = outbounds.iter().any(|(_, pmt)| {
+                       let mut awaiting_retry = false;
+                       if pmt.is_auto_retryable_now() {
+                               if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, .. } = pmt {
+                                       if pending_amt_msat < total_msat {
+                                               awaiting_retry = true;
+                                       }
+                               }
+                       }
+                       awaiting_retry
+               });
+
                let mut all_paths_failed = false;
                let mut full_failure_ev = None;
-               let mut pending_retry_ev = None;
+               let mut pending_retry_ev = false;
+               let mut retry = 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
+                               return false
                        }
                        if payment.get().is_fulfilled() {
                                log_trace!(logger, "Received failure of HTLC with payment_hash {} after payment completion", log_bytes!(payment_hash.0));
-                               return
+                               return false
                        }
-                       let is_retryable_now = payment.get().is_retryable_now();
+                       let mut is_retryable_now = payment.get().is_auto_retryable_now();
                        if let Some(scid) = short_channel_id {
                                payment.get_mut().insert_previously_failed_scid(scid);
                        }
+
+                       // We want to move towards only using the `PaymentParameters` in the outbound payments
+                       // map. However, for backwards-compatibility, we still need to support passing the
+                       // `PaymentParameters` data that was shoved in the HTLC (and given to us via
+                       // `payment_params`) back to the user.
+                       let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
+                       if let Some(params) = payment.get_mut().payment_parameters() {
+                               if params.final_cltv_expiry_delta.is_none() {
+                                       // This should be rare, but a user could provide None for the payment data, and
+                                       // we need it when we go to retry the payment, so fill it in.
+                                       params.final_cltv_expiry_delta = Some(path_last_hop.cltv_expiry_delta);
+                               }
+                               retry = Some(RouteParameters {
+                                       payment_params: params.clone(),
+                                       final_value_msat: path_last_hop.fee_msat,
+                                       final_cltv_expiry_delta: params.final_cltv_expiry_delta.unwrap(),
+                               });
+                       } else if let Some(params) = payment_params {
+                               retry = Some(RouteParameters {
+                                       payment_params: params.clone(),
+                                       final_value_msat: path_last_hop.fee_msat,
+                                       final_cltv_expiry_delta:
+                                               if let Some(delta) = params.final_cltv_expiry_delta { delta }
+                                               else { path_last_hop.cltv_expiry_delta },
+                               });
+                       }
+
+                       if payment_is_probe || !is_retryable_now || !payment_retryable || retry.is_none() {
+                               let _ = payment.get_mut().mark_abandoned(); // we'll only Err if it's a legacy payment
+                               is_retryable_now = false;
+                       }
                        if payment.get().remaining_parts() == 0 {
                                all_paths_failed = true;
                                if payment.get().abandoned() {
-                                       full_failure_ev = Some(events::Event::PaymentFailed {
-                                               payment_id: *payment_id,
-                                               payment_hash: payment.get().payment_hash().expect("PendingOutboundPayments::RetriesExceeded always has a payment hash set"),
-                                       });
+                                       if !payment_is_probe {
+                                               full_failure_ev = Some(events::Event::PaymentFailed {
+                                                       payment_id: *payment_id,
+                                                       payment_hash: payment.get().payment_hash().expect("PendingOutboundPayments::RetriesExceeded always has a payment hash set"),
+                                               });
+                                       }
                                        payment.remove();
                                }
                        }
                        is_retryable_now
                } else {
                        log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
-                       return
+                       return false
                };
                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 {
-                               payment_params: payment_params_data.clone(),
-                               final_value_msat: path_last_hop.fee_msat,
-                               final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
-                       })
-               } else { None };
                log_trace!(logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0));
 
                let path_failure = {
-                       if payment_is_probe(payment_hash, &payment_id, probing_cookie_secret) {
+                       if payment_is_probe {
                                if !payment_retryable {
                                        events::Event::ProbeSuccessful {
                                                payment_id: *payment_id,
@@ -1015,11 +1249,11 @@ 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() {
+                               // If we miss abandoning the payment above, we *must* generate an event here or else the
+                               // payment will sit in our outbounds forever.
+                               if attempts_remaining && !already_awaiting_retry {
                                        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),
-                                       });
+                                       pending_retry_ev = true;
                                }
                                events::Event::PaymentPathFailed {
                                        payment_id: Some(*payment_id),
@@ -1040,16 +1274,17 @@ 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); }
+               pending_retry_ev
        }
 
-       pub(super) fn abandon_payment(&self, payment_id: PaymentId) -> Option<events::Event> {
-               let mut failed_ev = None;
+       pub(super) fn abandon_payment(
+               &self, payment_id: PaymentId, pending_events: &Mutex<Vec<events::Event>>
+       ) {
                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
                if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
                        if let Ok(()) = payment.get_mut().mark_abandoned() {
                                if payment.get().remaining_parts() == 0 {
-                                       failed_ev = Some(events::Event::PaymentFailed {
+                                       pending_events.lock().unwrap().push(events::Event::PaymentFailed {
                                                payment_id,
                                                payment_hash: payment.get().payment_hash().expect("PendingOutboundPayments::RetriesExceeded always has a payment hash set"),
                                        });
@@ -1057,7 +1292,6 @@ impl OutboundPayments {
                                }
                        }
                }
-               failed_ev
        }
 
        #[cfg(test)]
@@ -1101,13 +1335,14 @@ 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))),
+               (3, payment_params, option),
                (4, payment_secret, option),
-               (not_written, attempts, (static_value, PaymentAttempts::new())),
+               (5, keysend_preimage, option),
                (6, total_msat, required),
-               (not_written, route_params, (static_value, None)),
                (8, pending_amt_msat, required),
                (10, starting_block_height, required),
+               (not_written, retry_strategy, (static_value, None)),
+               (not_written, attempts, (static_value, PaymentAttempts::new())),
        },
        (3, Abandoned) => {
                (0, session_privs, required),
@@ -1122,13 +1357,13 @@ mod tests {
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
 
        use crate::ln::PaymentHash;
-       use crate::ln::channelmanager::{PaymentId, PaymentSendFailure};
+       use crate::ln::channelmanager::PaymentId;
        use crate::ln::msgs::{ErrorAction, LightningError};
-       use crate::ln::outbound_payment::{OutboundPayments, Retry};
+       use crate::ln::outbound_payment::{OutboundPayments, Retry, RetryableSendFailure};
        use crate::routing::gossip::NetworkGraph;
        use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters};
-       use crate::sync::Arc;
-       use crate::util::errors::APIError;
+       use crate::sync::{Arc, Mutex};
+       use crate::util::events::Event;
        use crate::util::test_utils;
 
        #[test]
@@ -1143,31 +1378,40 @@ mod tests {
                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 scorer = Mutex::new(test_utils::TestScorer::new());
+               let router = test_utils::TestRouter::new(network_graph, &scorer);
                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);
+                               PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()),
+                               0
+                       ).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()
+               let pending_events = Mutex::new(Vec::new());
+               if on_retry {
+                       outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), None,
+                       &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)),
+                       Some(expired_route_params.payment_params.clone()), &&keys_manager, 0).unwrap();
+                       outbound_payments.retry_payment_internal(
+                               PaymentId([0; 32]), expired_route_params, &&router, vec![], &|| InFlightHtlcs::new(),
+                               &&keys_manager, &&keys_manager, 0, &&logger, &pending_events,
+                               &|_, _, _, _, _, _, _, _, _| Ok(()));
+                       let events = pending_events.lock().unwrap();
+                       assert_eq!(events.len(), 1);
+                       if let Event::PaymentFailed { .. } = events[0] { } else { panic!("Unexpected event"); }
                } else {
-                       outbound_payments.send_payment(
+                       let err = 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"); }
+                               &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger,
+                               &pending_events, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err();
+                       if let RetryableSendFailure::PaymentExpired = err { } else { panic!("Unexpected error"); }
+               }
        }
 
        #[test]
@@ -1180,33 +1424,40 @@ mod tests {
                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 scorer = Mutex::new(test_utils::TestScorer::new());
+               let router = test_utils::TestRouter::new(network_graph, &scorer);
                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()));
+                       PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0);
                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()
+               router.expect_find_route(route_params.clone(),
+                       Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }));
+
+               let pending_events = Mutex::new(Vec::new());
+               if on_retry {
+                       outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), None,
+                               &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)),
+                               Some(route_params.payment_params.clone()), &&keys_manager, 0).unwrap();
+                       outbound_payments.retry_payment_internal(
+                               PaymentId([0; 32]), route_params, &&router, vec![], &|| InFlightHtlcs::new(),
+                               &&keys_manager, &&keys_manager, 0, &&logger, &pending_events,
+                               &|_, _, _, _, _, _, _, _, _| Ok(()));
+                       let events = pending_events.lock().unwrap();
+                       assert_eq!(events.len(), 1);
+                       if let Event::PaymentFailed { .. } = events[0] { } else { panic!("Unexpected event"); }
                } else {
-                       outbound_payments.send_payment(
+                       let err = 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"); }
+                               &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger,
+                               &pending_events, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err();
+                       if let RetryableSendFailure::RouteNotFound = err {
+                       } else { panic!("Unexpected error"); }
+               }
        }
 }
index 726c5b89e5466ea544da5bbe160431170901d9bf..86648e5fb724d39b4e027f2152ea002b32166f79 100644 (file)
@@ -16,13 +16,14 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS
 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::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS, RecentPaymentDetails};
 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::gossip::{EffectiveCapacity, RoutingFees};
 use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RouteParameters};
+use crate::routing::scoring::ChannelUsage;
 use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
 use crate::util::test_utils;
 use crate::util::errors::APIError;
@@ -39,63 +40,9 @@ use crate::routing::gossip::NodeId;
 #[cfg(feature = "std")]
 use {
        crate::util::time::tests::SinceEpoch,
-       std::time::{SystemTime, Duration}
+       std::time::{SystemTime, Instant, Duration}
 };
 
-#[test]
-fn retry_single_path_payment() {
-       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 mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
-
-       let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1);
-       let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1);
-       // Rebalance to find a route
-       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
-
-       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100_000);
-
-       // Rebalance so that the first hop fails.
-       send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000);
-
-       // Make sure the payment fails on the first hop.
-       let payment_id = PaymentId(payment_hash.0);
-       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), payment_id).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_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1.2 }]);
-       let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
-       assert!(htlc_updates.update_add_htlcs.is_empty());
-       assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
-       assert!(htlc_updates.update_fulfill_htlcs.is_empty());
-       assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
-       check_added_monitors!(nodes[1], 1);
-       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
-       commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false);
-       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
-
-       // Rebalance the channel so the retry succeeds.
-       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
-
-       // Mine two blocks (we expire retries after 3, so this will check that we don't expire early)
-       connect_blocks(&nodes[0], 2);
-
-       // Retry the payment and make sure it succeeds.
-       nodes[0].node.retry_payment(&route, payment_id).unwrap();
-       check_added_monitors!(nodes[0], 1);
-       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
-       assert_eq!(events.len(), 1);
-       pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 100_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
-}
-
 #[test]
 fn mpp_failure() {
        let chanmon_cfgs = create_chanmon_cfgs(4);
@@ -135,7 +82,8 @@ fn mpp_retry() {
        // Rebalance
        send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000);
 
-       let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 1_000_000);
+       let amt_msat = 1_000_000;
+       let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], amt_msat);
        let path = route.paths[0].clone();
        route.paths.push(path);
        route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
@@ -147,17 +95,24 @@ fn mpp_retry() {
 
        // Initiate the MPP payment.
        let payment_id = PaymentId(payment_hash.0);
-       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), payment_id).unwrap();
+       let mut route_params = RouteParameters {
+               payment_params: route.payment_params.clone().unwrap(),
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), payment_id, route_params.clone(), Retry::Attempts(1)).unwrap();
        check_added_monitors!(nodes[0], 2); // one monitor per path
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 2);
 
        // Pass half of the payment along the success path.
-       let (success_path_msgs, mut events) = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &events);
+       let success_path_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), success_path_msgs, false, None);
 
        // Add the HTLC along the first hop.
-       let (fail_path_msgs_1, _events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events);
+       let fail_path_msgs_1 = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        let (update_add, commitment_signed) = match fail_path_msgs_1 {
                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_eq!(update_add_htlcs.len(), 1);
@@ -183,25 +138,23 @@ fn mpp_retry() {
        check_added_monitors!(nodes[2], 1);
        nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
        commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false);
-       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       match events[1] {
+               Event::PendingHTLCsForwardable { .. } => {},
+               _ => panic!("Unexpected event")
+       }
+       events.remove(1);
+       expect_payment_failed_conditions_event(events, payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
 
        // Rebalance the channel so the second half of the payment can succeed.
        send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000);
 
-       // Make sure it errors as expected given a too-large amount.
-       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, payment_id) {
-               assert!(err.contains("over total_payment_amt_msat"));
-       } else { panic!("Unexpected error"); }
-
-       // Make sure it errors as expected given the wrong payment_id.
-       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, PaymentId([0; 32])) {
-               assert!(err.contains("not found"));
-       } else { panic!("Unexpected error"); }
-
        // Retry the second half of the payment and make sure it succeeds.
-       let mut path = route.clone();
-       path.paths.remove(0);
-       nodes[0].node.retry_payment(&path, payment_id).unwrap();
+       route.paths.remove(0);
+       route_params.final_value_msat = 1_000_000;
+       route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id);
+       nodes[0].router.expect_find_route(route_params, Ok(route));
+       nodes[0].node.process_pending_htlc_forwards();
        check_added_monitors!(nodes[0], 1);
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
@@ -237,7 +190,7 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) {
        assert_eq!(events.len(), 2);
 
        // Pass half of the payment along the first path.
-       let (node_1_msgs, mut events) = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &events);
+       let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 200_000, payment_hash, Some(payment_secret), node_1_msgs, false, None);
 
        if send_partial_mpp {
@@ -265,7 +218,7 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) {
                expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain().expected_htlc_error_data(23, &[][..]));
        } else {
                // Pass half of the payment along the second path.
-               let (node_2_msgs, _events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &events);
+               let node_2_msgs = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
                pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash, Some(payment_secret), node_2_msgs, true, None);
 
                // Even after MPP_TIMEOUT_TICKS we should not timeout the MPP if we have all the parts
@@ -283,55 +236,6 @@ fn mpp_receive_timeout() {
        do_mpp_receive_timeout(false);
 }
 
-#[test]
-fn retry_expired_payment() {
-       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 mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
-
-       let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1);
-       let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1);
-       // Rebalance to find a route
-       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
-
-       let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100_000);
-
-       // Rebalance so that the first hop fails.
-       send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000);
-
-       // Make sure the payment fails on the first hop.
-       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]);
-       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_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1.2 }]);
-       let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
-       assert!(htlc_updates.update_add_htlcs.is_empty());
-       assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
-       assert!(htlc_updates.update_fulfill_htlcs.is_empty());
-       assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
-       check_added_monitors!(nodes[1], 1);
-       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
-       commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false);
-       expect_payment_failed!(nodes[0], payment_hash, false);
-
-       // Mine blocks so the payment will have expired.
-       connect_blocks(&nodes[0], 3);
-
-       // Retry the payment and make sure it errors as expected.
-       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, PaymentId(payment_hash.0)) {
-               assert!(err.contains("not found"));
-       } else {
-               panic!("Unexpected error");
-       }
-}
-
 #[test]
 fn no_pending_leak_on_initial_send_failure() {
        // In an earlier version of our payment tracking, we'd have a retry entry even when the initial
@@ -349,12 +253,12 @@ fn no_pending_leak_on_initial_send_failure() {
 
        let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)),
                true, APIError::ChannelUnavailable { ref err },
-               assert_eq!(err, "Peer for first hop currently disconnected/pending monitor update!"));
+               assert_eq!(err, "Peer for first hop currently disconnected"));
 
        assert!(!nodes[0].node.has_pending_payments());
 }
@@ -387,9 +291,15 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
 
        // Send two payments - one which will get to nodes[2] and will be claimed, one which we'll time
        // out and retry.
-       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
+       let amt_msat = 1_000_000;
+       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
        let (payment_preimage_1, payment_hash_1, _, payment_id_1) = send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000);
-       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
+       let route_params = RouteParameters {
+               payment_params: route.payment_params.clone().unwrap(),
+               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();
@@ -400,8 +310,8 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        // We relay the payment to nodes[1] while its disconnected from nodes[2], causing the payment
        // to be returned immediately to nodes[0], without having nodes[2] fail the inbound payment
        // which would prevent retry.
-       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        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, true);
@@ -430,13 +340,13 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        assert_eq!(as_broadcasted_txn.len(), 1);
        assert_eq!(as_broadcasted_txn[0], as_commitment_tx);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
        // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an
        // error, as the channel has hit the chain.
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
        let as_err = nodes[0].node.get_and_clear_pending_msg_events();
@@ -498,7 +408,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
                confirm_transaction(&nodes[0], &first_htlc_timeout_tx);
        }
        nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
-       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
+       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new());
 
        // Finally, retry the payment (which was reloaded from the ChannelMonitor when nodes[0] was
        // reloaded) via a route over the new channel, which work without issue and eventually be
@@ -524,8 +434,8 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
                nodes[1].node.timer_tick_occurred();
        }
 
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id_1).is_err()); // Shouldn't be allowed to retry a fulfilled payment
-       nodes[0].node.retry_payment(&new_route, PaymentId(payment_hash.0)).unwrap();
+       assert!(nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id_1).is_err()); // Shouldn't be allowed to retry a fulfilled payment
+       nodes[0].node.send_payment(&new_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);
@@ -586,7 +496,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
 
        reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized], first_persister, first_new_chain_monitor, first_nodes_0_deserialized);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and
        // force-close the channel.
@@ -595,12 +505,12 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
        assert!(nodes[0].node.has_pending_payments());
        assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
        // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an
        // error, as the channel has hit the chain.
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
        let as_err = nodes[0].node.get_and_clear_pending_msg_events();
@@ -659,7 +569,10 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
        // If we attempt to retry prior to the HTLC-Timeout (or commitment transaction, for dust HTLCs)
        // confirming, we will fail as it's considered still-pending...
        let (new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 });
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+       match nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id) {
+               Err(PaymentSendFailure::DuplicatePayment) => {},
+               _ => panic!("Unexpected error")
+       }
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
        // After ANTI_REORG_DELAY confirmations, the HTLC should be failed and we can try the payment
@@ -667,42 +580,49 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
        // (which should also still work).
        connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
        connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
-       // We set mpp_parts_remain to avoid having abandon_payment called
-       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
+       expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new());
 
        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
        let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_3).encode();
        nodes_0_serialized = nodes[0].node.encode();
 
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_ok());
+       // After the payment failed, we're free to send it again.
+       assert!(nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id).is_ok());
        assert!(!nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
        reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], second_persister, second_new_chain_monitor, second_nodes_0_deserialized);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        // Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures
        // the payment is not (spuriously) listed as still pending.
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_ok());
+       assert!(nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id).is_ok());
        check_added_monitors!(nodes[0], 1);
        pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], if use_dust { 1_000 } else { 1_000_000 }, payment_hash, payment_secret);
        claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
 
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+       match nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id) {
+               Err(PaymentSendFailure::DuplicatePayment) => {},
+               _ => panic!("Unexpected error")
+       }
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
        let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_3).encode();
        nodes_0_serialized = nodes[0].node.encode();
 
-       // Ensure that after reload we cannot retry the payment.
+       // Check that after reload we can send the payment again (though we shouldn't, since it was
+       // claimed previously).
        reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], third_persister, third_new_chain_monitor, third_nodes_0_deserialized);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
-       assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+       match nodes[0].node.send_payment(&new_route, payment_hash, &Some(payment_secret), payment_id) {
+               Err(PaymentSendFailure::DuplicatePayment) => {},
+               _ => panic!("Unexpected error")
+       }
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 }
 
@@ -740,8 +660,8 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co
        check_added_monitors!(nodes[0], 1);
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        // Connect blocks until the CLTV timeout is up so that we get an HTLC-Timeout transaction
        connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
@@ -892,7 +812,7 @@ fn test_fulfill_restart_failure() {
        // Now reload nodes[1]...
        reload_node!(nodes[1], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        nodes[1].node.fail_htlc_backwards(&payment_hash);
@@ -919,9 +839,9 @@ fn get_ldk_payment_preimage() {
        let expiry_secs = 60 * 60;
        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())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(nodes[1].node.invoice_features());
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
        let route = get_route(
@@ -1021,6 +941,7 @@ fn successful_probe_yields_event() {
                },
                _ => panic!(),
        };
+       assert!(!nodes[0].node.has_pending_payments());
 }
 
 #[test]
@@ -1033,7 +954,7 @@ fn failed_probe_yields_event() {
        create_announced_chan_between_nodes(&nodes, 0, 1);
        create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 90000000);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id());
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42);
 
        let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 9_998_000, 42);
 
@@ -1066,6 +987,7 @@ fn failed_probe_yields_event() {
                },
                _ => panic!(),
        };
+       assert!(!nodes[0].node.has_pending_payments());
 }
 
 #[test]
@@ -1080,7 +1002,7 @@ fn onchain_failed_probe_yields_event() {
        let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1).2;
        create_announced_chan_between_nodes(&nodes, 1, 2);
 
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id());
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42);
 
        // Send a dust HTLC, which will be treated as if it timed out once the channel hits the chain.
        let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 1_000, 42);
@@ -1120,6 +1042,7 @@ fn onchain_failed_probe_yields_event() {
                }
        }
        assert!(found_probe_failed);
+       assert!(!nodes[0].node.has_pending_payments());
 }
 
 #[test]
@@ -1232,20 +1155,17 @@ fn abandoned_send_payment_idempotent() {
        nodes[1].node.fail_htlc_backwards(&first_payment_hash);
        expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::FailedPayment { payment_hash: first_payment_hash }]);
 
-       pass_failed_payment_back_no_abandon(&nodes[0], &[&[&nodes[1]]], false, first_payment_hash);
-       check_send_rejected!();
-
-       // Until we abandon the payment, no matter how many timer ticks pass, we still cannot reuse the
+       // Until we abandon the payment upon path failure, no matter how many timer ticks pass, we still cannot reuse the
        // PaymentId.
        for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
                nodes[0].node.timer_tick_occurred();
        }
        check_send_rejected!();
 
-       nodes[0].node.abandon_payment(payment_id);
-       get_event!(nodes[0], Event::PaymentFailed);
+       pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, first_payment_hash);
 
-       // However, we can reuse the PaymentId immediately after we `abandon_payment`.
+       // However, we can reuse the PaymentId immediately after we `abandon_payment` upon passing the
+       // failed payment back.
        nodes[0].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret), payment_id).unwrap();
        check_added_monitors!(nodes[0], 1);
        pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, second_payment_hash, second_payment_secret);
@@ -1274,7 +1194,11 @@ fn test_trivial_inflight_htlc_tracking(){
        let (_, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2);
 
        // Send and claim the payment. Inflight HTLCs should be empty.
-       send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 500000);
+       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 500000);
+       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
+       check_added_monitors!(nodes[0], 1);
+       pass_along_route(&nodes[0], &[&vec!(&nodes[1], &nodes[2])[..]], 500000, payment_hash, payment_secret);
+       claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], payment_preimage);
        {
                let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs();
 
@@ -1299,9 +1223,17 @@ fn test_trivial_inflight_htlc_tracking(){
                assert_eq!(chan_1_used_liquidity, None);
                assert_eq!(chan_2_used_liquidity, None);
        }
+       let pending_payments = nodes[0].node.list_recent_payments();
+       assert_eq!(pending_payments.len(), 1);
+       assert_eq!(pending_payments[0], RecentPaymentDetails::Fulfilled { payment_hash: Some(payment_hash) });
+
+       // Remove fulfilled payment
+       for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
+               nodes[0].node.timer_tick_occurred();
+       }
 
        // Send the payment, but do not claim it. Our inflight HTLCs should contain the pending payment.
-       let (payment_preimage, _,  _) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 500000);
+       let (payment_preimage, payment_hash,  _) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 500000);
        {
                let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs();
 
@@ -1327,9 +1259,18 @@ fn test_trivial_inflight_htlc_tracking(){
                assert_eq!(chan_1_used_liquidity, Some(501000));
                assert_eq!(chan_2_used_liquidity, Some(500000));
        }
+       let pending_payments = nodes[0].node.list_recent_payments();
+       assert_eq!(pending_payments.len(), 1);
+       assert_eq!(pending_payments[0], RecentPaymentDetails::Pending { payment_hash, total_msat: 500000 });
 
        // Now, let's claim the payment. This should result in the used liquidity to return `None`.
        claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
+
+       // Remove fulfilled payment
+       for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
+               nodes[0].node.timer_tick_occurred();
+       }
+
        {
                let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs();
 
@@ -1354,6 +1295,9 @@ fn test_trivial_inflight_htlc_tracking(){
                assert_eq!(chan_1_used_liquidity, None);
                assert_eq!(chan_2_used_liquidity, None);
        }
+
+       let pending_payments = nodes[0].node.list_recent_payments();
+       assert_eq!(pending_payments.len(), 0);
 }
 
 #[test]
@@ -1418,14 +1362,14 @@ fn do_test_intercepted_payment(test: InterceptTest) {
        let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), Some(zero_conf_chan_config)]);
 
        let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[0].keys_manager.get_secure_random_bytes();
 
        let _ = create_announced_chan_between_nodes(&nodes, 0, 1).2;
 
        let amt_msat = 100_000;
        let intercept_scid = nodes[1].node.get_intercept_scid();
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_route_hints(vec![
                        RouteHint(vec![RouteHintHop {
                                src_node_id: nodes[1].node.get_our_node_id(),
@@ -1586,17 +1530,21 @@ fn do_test_intercepted_payment(test: InterceptTest) {
 #[derive(PartialEq)]
 enum AutoRetry {
        Success,
+       Spontaneous,
        FailAttempts,
        FailTimeout,
        FailOnRestart,
+       FailOnRetry,
 }
 
 #[test]
 fn automatic_retries() {
        do_automatic_retries(AutoRetry::Success);
+       do_automatic_retries(AutoRetry::Spontaneous);
        do_automatic_retries(AutoRetry::FailAttempts);
        do_automatic_retries(AutoRetry::FailTimeout);
        do_automatic_retries(AutoRetry::FailOnRestart);
+       do_automatic_retries(AutoRetry::FailOnRetry);
 }
 fn do_automatic_retries(test: AutoRetry) {
        // Test basic automatic payment retries in ChannelManager. See individual `test` variant comments
@@ -1623,7 +1571,7 @@ fn do_automatic_retries(test: AutoRetry) {
        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())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_features(invoice_features);
        let route_params = RouteParameters {
@@ -1653,12 +1601,12 @@ fn do_automatic_retries(test: AutoRetry) {
                        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();
+                       assert_eq!(events.len(), 2);
                        match events[0] {
                                Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
                                        assert_eq!(payment_hash, ev_payment_hash);
@@ -1667,12 +1615,18 @@ fn do_automatic_retries(test: AutoRetry) {
                                _ => 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) }
+                       } else {
+                               match events[1] {
+                                       Event::PaymentFailed { payment_hash: ev_payment_hash, .. } => {
+                                               assert_eq!(payment_hash, ev_payment_hash);
+                                       },
+                                       _ => panic!("Unexpected event"),
+                               }
+                       }
                }
        }
 
@@ -1692,6 +1646,21 @@ fn do_automatic_retries(test: AutoRetry) {
                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::Spontaneous {
+               nodes[0].node.send_spontaneous_payment_with_retry(Some(payment_preimage), 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, None, msg_events.pop().unwrap(), true, Some(payment_preimage));
+               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();
@@ -1709,17 +1678,6 @@ fn do_automatic_retries(test: AutoRetry) {
                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.
@@ -1734,7 +1692,6 @@ fn do_automatic_retries(test: AutoRetry) {
                        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] {
@@ -1764,12 +1721,31 @@ fn do_automatic_retries(test: AutoRetry) {
                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);
 
+               let mut events = nodes[0].node.get_and_clear_pending_events();
+               expect_pending_htlcs_forwardable_from_events!(nodes[0], events, true);
                // Make sure we don't retry again.
+               let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(msg_events.len(), 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::FailOnRetry {
+               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);
+
+               // We retry payments in `process_pending_htlc_forwards`. Since our channel closed, we should
+               // fail to find a route.
                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] {
@@ -1805,7 +1781,7 @@ fn auto_retry_partial_failure() {
        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())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_features(invoice_features);
        let route_params = RouteParameters {
@@ -1844,7 +1820,7 @@ fn auto_retry_partial_failure() {
                                cltv_expiry_delta: 100,
                        }],
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+               payment_params: Some(route_params.payment_params.clone()),
        };
        let retry_1_route = Route {
                paths: vec![
@@ -1865,7 +1841,7 @@ fn auto_retry_partial_failure() {
                                cltv_expiry_delta: 100,
                        }],
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+               payment_params: Some(route_params.payment_params.clone()),
        };
        let retry_2_route = Route {
                paths: vec![
@@ -1878,24 +1854,40 @@ fn auto_retry_partial_failure() {
                                cltv_expiry_delta: 100,
                        }],
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+               payment_params: Some(route_params.payment_params.clone()),
        };
-       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));
+       nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route));
+       let mut payment_params = route_params.payment_params.clone();
+       payment_params.previously_failed_channels.push(chan_2_id);
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params, final_value_msat: amt_msat / 2, final_cltv_expiry_delta: TEST_FINAL_CLTV
+               }, Ok(retry_1_route));
+       let mut payment_params = route_params.payment_params.clone();
+       payment_params.previously_failed_channels.push(chan_3_id);
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params, final_value_msat: amt_msat / 4, final_cltv_expiry_delta: TEST_FINAL_CLTV
+               }, 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);
+       assert_eq!(closed_chan_events.len(), 4);
        match closed_chan_events[0] {
                Event::ChannelClosed { .. } => {},
                _ => panic!("Unexpected event"),
        }
        match closed_chan_events[1] {
+               Event::PaymentPathFailed { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+       match closed_chan_events[2] {
                Event::ChannelClosed { .. } => {},
                _ => panic!("Unexpected event"),
        }
+       match closed_chan_events[3] {
+               Event::PaymentPathFailed { .. } => {},
+               _ => 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
@@ -2001,7 +1993,7 @@ fn auto_retry_zero_attempts_send_error() {
        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())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_features(invoice_features);
        let route_params = RouteParameters {
@@ -2011,11 +2003,13 @@ fn auto_retry_zero_attempts_send_error() {
        };
 
        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"); }
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
        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
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 3);
+       if let Event::ChannelClosed { .. } = events[0] { } else { panic!(); }
+       if let Event::PaymentPathFailed { .. } = events[1] { } else { panic!(); }
+       if let Event::PaymentFailed { .. } = events[2] { } else { panic!(); }
        check_added_monitors!(nodes[0], 2);
 }
 
@@ -2039,7 +2033,7 @@ fn fails_paying_after_rejected_by_payee() {
        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())
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_features(invoice_features);
        let route_params = RouteParameters {
@@ -2074,6 +2068,27 @@ fn retry_multi_path_single_failed_payment() {
 
        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 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(), TEST_FINAL_CLTV)
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let route_params = RouteParameters {
+               payment_params: payment_params.clone(),
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
        let chans = nodes[0].node.list_usable_channels();
        let mut route = Route {
                paths: vec![
@@ -2094,34 +2109,42 @@ fn retry_multi_path_single_failed_payment() {
                                cltv_expiry_delta: 100,
                        }],
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+               payment_params: Some(payment_params),
        };
-       nodes[0].router.expect_find_route(Ok(route.clone()));
+       nodes[0].router.expect_find_route(route_params.clone(), 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 mut pay_params = route.payment_params.clone().unwrap();
+       pay_params.previously_failed_channels.push(chans[1].short_channel_id.unwrap());
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params: pay_params,
+                       // Note that the second request here requests the amount we originally failed to send,
+                       // not the amount remaining on the full payment, which should be changed.
+                       final_value_msat: 100_000_001, final_cltv_expiry_delta: TEST_FINAL_CLTV
+               }, 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,
-       };
+       {
+               let scorer = chanmon_cfgs[0].scorer.lock().unwrap();
+               // The initial send attempt, 2 paths
+               scorer.expect_usage(chans[0].short_channel_id.unwrap(), ChannelUsage { amount_msat: 10_000, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown });
+               scorer.expect_usage(chans[1].short_channel_id.unwrap(), ChannelUsage { amount_msat: 100_000_001, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown });
+               // The retry, 2 paths. Ensure that the in-flight HTLC amount is factored in.
+               scorer.expect_usage(chans[0].short_channel_id.unwrap(), ChannelUsage { amount_msat: 50_000_001, inflight_htlc_msat: 10_000, effective_capacity: EffectiveCapacity::Unknown });
+               scorer.expect_usage(chans[1].short_channel_id.unwrap(), ChannelUsage { amount_msat: 50_000_000, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown });
+       }
 
        nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       let 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: false,
+                       network_update: None, all_paths_failed: false, short_channel_id: Some(expected_scid), .. } => {
+                       assert_eq!(payment_hash, ev_payment_hash);
+                       assert_eq!(expected_scid, route.paths[1][0].short_channel_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
        let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(htlc_msgs.len(), 2);
        check_added_monitors!(nodes[0], 2);
@@ -2137,6 +2160,26 @@ fn immediate_retry_on_failure() {
 
        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 amt_msat = 100_000_001;
+       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(), TEST_FINAL_CLTV)
+               .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 chans = nodes[0].node.list_usable_channels();
        let mut route = Route {
                paths: vec![
@@ -2149,36 +2192,32 @@ fn immediate_retry_on_failure() {
                                cltv_expiry_delta: 100,
                        }],
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
+               payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)),
        };
-       nodes[0].router.expect_find_route(Ok(route.clone()));
+       nodes[0].router.expect_find_route(route_params.clone(), 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,
-       };
+       let mut pay_params = route_params.payment_params.clone();
+       pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap());
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params: pay_params, final_value_msat: amt_msat,
+                       final_cltv_expiry_delta: TEST_FINAL_CLTV
+               }, Ok(route.clone()));
 
        nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
+       let 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: false,
+               network_update: None, all_paths_failed: false, short_channel_id: Some(expected_scid), .. } => {
+                       assert_eq!(payment_hash, ev_payment_hash);
+                       assert_eq!(expected_scid, route.paths[1][0].short_channel_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
        let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(htlc_msgs.len(), 2);
        check_added_monitors!(nodes[0], 2);
@@ -2208,6 +2247,25 @@ fn no_extra_retries_on_back_to_back_fail() {
        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 amt_msat = 200_000_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(), TEST_FINAL_CLTV)
+               .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 mut route = Route {
                paths: vec![
                        vec![RouteHop {
@@ -2215,7 +2273,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                node_features: nodes[1].node.node_features(),
                                short_channel_id: chan_1_scid,
                                channel_features: nodes[1].node.channel_features(),
-                               fee_msat: 0,
+                               fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee
                                cltv_expiry_delta: 100,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
@@ -2230,7 +2288,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                node_features: nodes[1].node.node_features(),
                                short_channel_id: chan_1_scid,
                                channel_features: nodes[1].node.channel_features(),
-                               fee_msat: 0,
+                               fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee
                                cltv_expiry_delta: 100,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
@@ -2241,31 +2299,18 @@ fn no_extra_retries_on_back_to_back_fail() {
                                cltv_expiry_delta: 100,
                        }]
                ],
-               payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())),
+               payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)),
        };
-       nodes[0].router.expect_find_route(Ok(route.clone()));
-       // On retry, we'll only be asked for one path
+       nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
+       let mut second_payment_params = route_params.payment_params.clone();
+       second_payment_params.previously_failed_channels = vec![chan_2_scid, chan_2_scid];
+       // On retry, we'll only return 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,
-       };
+       route.paths[0][1].fee_msat = amt_msat;
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params: second_payment_params,
+                       final_value_msat: amt_msat, final_cltv_expiry_delta: TEST_FINAL_CLTV,
+               }, Ok(route.clone()));
 
        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]);
@@ -2329,12 +2374,18 @@ fn no_extra_retries_on_back_to_back_fail() {
 
        // 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.
+       // with it set.
+       //
+       // Previously, we retried payments in an event consumer, which would retry each
+       // `PaymentPathFailed` individually. In that setup, we had retried the payment in response to
+       // the first `PaymentPathFailed`, then seen the second `PaymentPathFailed` with
+       // `all_paths_failed` set and assumed the payment was completely failed. We ultimately fixed it
+       // by adding the `PaymentFailed` event.
+       //
+       // Because we now retry payments as a batch, we simply return a single-path route in the
+       // second, batched, request, have that fail, ensure the payment was abandoned.
        let mut events = nodes[0].node.get_and_clear_pending_events();
-       assert_eq!(events.len(), 4);
+       assert_eq!(events.len(), 3);
        match events[0] {
                Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
                        assert_eq!(payment_hash, ev_payment_hash);
@@ -2353,10 +2404,6 @@ fn no_extra_retries_on_back_to_back_fail() {
                },
                _ => 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]);
@@ -2369,7 +2416,7 @@ fn no_extra_retries_on_back_to_back_fail() {
        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);
+       assert_eq!(events.len(), 2);
        match events[0] {
                Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => {
                        assert_eq!(payment_hash, ev_payment_hash);
@@ -2377,10 +2424,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                },
                _ => 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] {
+       match events[1] {
                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);
@@ -2388,3 +2432,323 @@ fn no_extra_retries_on_back_to_back_fail() {
                _ => panic!("Unexpected event"),
        }
 }
+
+#[test]
+fn test_simple_partial_retry() {
+       // In the first version of the in-`ChannelManager` payment retries, retries were sent for the
+       // full amount of the payment, rather than only the missing amount. Here we simply test for
+       // this by sending a payment with two parts, failing one, and retrying the second. Note that
+       // `TestRouter` will check that the `RouteParameters` (which contain the amount) matches the
+       // request.
+       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 amt_msat = 200_000_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[2], 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(), TEST_FINAL_CLTV)
+               .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 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, // nodes[1] will fail the payment as we don't pay its fee
+                               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: 100_000,
+                               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(), TEST_FINAL_CLTV)),
+       };
+       nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
+       let mut second_payment_params = route_params.payment_params.clone();
+       second_payment_params.previously_failed_channels = vec![chan_2_scid];
+       // On retry, we'll only be asked for one path (or 100k sats)
+       route.paths.remove(0);
+       nodes[0].router.expect_find_route(RouteParameters {
+                       payment_params: second_payment_params,
+                       final_value_msat: amt_msat / 2, final_cltv_expiry_delta: TEST_FINAL_CLTV,
+               }, Ok(route.clone()));
+
+       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);
+
+       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);
+
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 2);
+       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"),
+       }
+
+       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);
+
+       expect_pending_htlcs_forwardable!(nodes[1]);
+       check_added_monitors!(nodes[1], 1);
+
+       let bs_forward_update = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id());
+       nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[0]);
+       nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[1]);
+       commitment_signed_dance!(nodes[2], nodes[1], &bs_forward_update.commitment_signed, false);
+
+       expect_pending_htlcs_forwardable!(nodes[2]);
+       expect_payment_claimable!(nodes[2], payment_hash, payment_secret, amt_msat);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn test_threaded_payment_retries() {
+       // In the first version of the in-`ChannelManager` payment retries, retries weren't limited to
+       // a single thread and would happily let multiple threads run retries at the same time. Because
+       // retries are done by first calculating the amount we need to retry, then dropping the
+       // relevant lock, then actually sending, we would happily let multiple threads retry the same
+       // amount at the same time, overpaying our original HTLC!
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+       // There is one mitigating guardrail when retrying payments - we can never over-pay by more
+       // than 10% of the original value. Thus, we want all our retries to be below that. In order to
+       // keep things simple, we route one HTLC for 0.1% of the payment over channel 1 and the rest
+       // out over channel 3+4. This will let us ignore 99% of the payment value and deal with only
+       // our channel.
+       let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0).0.contents.short_channel_id;
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 10_000_000, 0);
+       let chan_3_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 10_000_000, 0).0.contents.short_channel_id;
+       let chan_4_scid = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 0).0.contents.short_channel_id;
+
+       let amt_msat = 100_000_000;
+       let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[2], 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(), TEST_FINAL_CLTV)
+               .with_expiry_time(payment_expiry_secs as u64)
+               .with_features(invoice_features);
+       let mut route_params = RouteParameters {
+               payment_params,
+               final_value_msat: amt_msat,
+               final_cltv_expiry_delta: TEST_FINAL_CLTV,
+       };
+
+       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[3].node.get_our_node_id(),
+                               node_features: nodes[2].node.node_features(),
+                               short_channel_id: 42, // Set a random SCID which nodes[1] will fail as unknown
+                               channel_features: nodes[2].node.channel_features(),
+                               fee_msat: amt_msat / 1000,
+                               cltv_expiry_delta: 100,
+                       }],
+                       vec![RouteHop {
+                               pubkey: nodes[2].node.get_our_node_id(),
+                               node_features: nodes[2].node.node_features(),
+                               short_channel_id: chan_3_scid,
+                               channel_features: nodes[2].node.channel_features(),
+                               fee_msat: 100_000,
+                               cltv_expiry_delta: 100,
+                       }, RouteHop {
+                               pubkey: nodes[3].node.get_our_node_id(),
+                               node_features: nodes[3].node.node_features(),
+                               short_channel_id: chan_4_scid,
+                               channel_features: nodes[3].node.channel_features(),
+                               fee_msat: amt_msat - amt_msat / 1000,
+                               cltv_expiry_delta: 100,
+                       }]
+               ],
+               payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)),
+       };
+       nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
+
+       nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0xdeadbeef)).unwrap();
+       check_added_monitors!(nodes[0], 2);
+       let mut send_msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(send_msg_events.len(), 2);
+       send_msg_events.retain(|msg|
+               if let MessageSendEvent::UpdateHTLCs { node_id, .. } = msg {
+                       // Drop the commitment update for nodes[2], we can just let that one sit pending
+                       // forever.
+                       *node_id == nodes[1].node.get_our_node_id()
+               } else { panic!(); }
+       );
+
+       // from here on out, the retry `RouteParameters` amount will be amt/1000
+       route_params.final_value_msat /= 1000;
+       route.paths.pop();
+
+       let end_time = Instant::now() + Duration::from_secs(1);
+       macro_rules! thread_body { () => { {
+               // We really want std::thread::scope, but its not stable until 1.63. Until then, we get unsafe.
+               let node_ref = NodePtr::from_node(&nodes[0]);
+               move || {
+                       let node_a = unsafe { &*node_ref.0 };
+                       while Instant::now() < end_time {
+                               node_a.node.get_and_clear_pending_events(); // wipe the PendingHTLCsForwardable
+                               // Ignore if we have any pending events, just always pretend we just got a
+                               // PendingHTLCsForwardable
+                               node_a.node.process_pending_htlc_forwards();
+                       }
+               }
+       } } }
+       let mut threads = Vec::new();
+       for _ in 0..16 { threads.push(std::thread::spawn(thread_body!())); }
+
+       // Back in the main thread, poll pending messages and make sure that we never have more than
+       // one HTLC pending at a time. Note that the commitment_signed_dance will fail horribly if
+       // there are HTLC messages shoved in while its running. This allows us to test that we never
+       // generate an additional update_add_htlc until we've fully failed the first.
+       let mut previously_failed_channels = Vec::new();
+       loop {
+               assert_eq!(send_msg_events.len(), 1);
+               let send_event = SendEvent::from_event(send_msg_events.pop().unwrap());
+               assert_eq!(send_event.msgs.len(), 1);
+
+               nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
+               commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false, true);
+
+               // Note that we only push one route into `expect_find_route` at a time, because that's all
+               // the retries (should) need. If the bug is reintroduced "real" routes may be selected, but
+               // we should still ultimately fail for the same reason - because we're trying to send too
+               // many HTLCs at once.
+               let mut new_route_params = route_params.clone();
+               previously_failed_channels.push(route.paths[0][1].short_channel_id);
+               new_route_params.payment_params.previously_failed_channels = previously_failed_channels.clone();
+               route.paths[0][1].short_channel_id += 1;
+               nodes[0].router.expect_find_route(new_route_params, Ok(route.clone()));
+
+               let bs_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(), &bs_fail_updates.update_fail_htlcs[0]);
+               // The "normal" commitment_signed_dance delivers the final RAA and then calls
+               // `check_added_monitors` to ensure only the one RAA-generated monitor update was created.
+               // This races with our other threads which may generate an add-HTLCs commitment update via
+               // `process_pending_htlc_forwards`. Instead, we defer the monitor update check until after
+               // *we've* called `process_pending_htlc_forwards` when its guaranteed to have two updates.
+               let last_raa = commitment_signed_dance!(nodes[0], nodes[1], bs_fail_updates.commitment_signed, false, true, false, true);
+               nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &last_raa);
+
+               let cur_time = Instant::now();
+               if cur_time > end_time {
+                       for thread in threads.drain(..) { thread.join().unwrap(); }
+               }
+
+               // Make sure we have some events to handle when we go around...
+               nodes[0].node.get_and_clear_pending_events(); // wipe the PendingHTLCsForwardable
+               nodes[0].node.process_pending_htlc_forwards();
+               send_msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+               check_added_monitors!(nodes[0], 2);
+
+               if cur_time > end_time {
+                       break;
+               }
+       }
+}
index a63f764cd8f839c3afeae5febae6bc05231a5455..e9eaf33e8840b021afe7fbcfc60afec3e0fa5b3d 100644 (file)
@@ -27,7 +27,7 @@ use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
 use crate::ln::wire;
 use crate::ln::wire::Encode;
 use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
-use crate::routing::gossip::{NetworkGraph, P2PGossipSync};
+use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId};
 use crate::util::atomic_counter::AtomicCounter;
 use crate::util::events::{MessageSendEvent, MessageSendEventsProvider, OnionMessageProvider};
 use crate::util::logger::Logger;
@@ -46,16 +46,23 @@ use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256::HashEngine as Sha256Engine;
 use bitcoin::hashes::{HashEngine, Hash};
 
-/// Handler for BOLT1-compliant messages.
+/// A handler provided to [`PeerManager`] for reading and handling custom messages.
+///
+/// [BOLT 1] specifies a custom message type range for use with experimental or application-specific
+/// messages. `CustomMessageHandler` allows for user-defined handling of such types. See the
+/// [`lightning_custom_message`] crate for tools useful in composing more than one custom handler.
+///
+/// [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md
+/// [`lightning_custom_message`]: https://docs.rs/lightning_custom_message/latest/lightning_custom_message
 pub trait CustomMessageHandler: wire::CustomMessageReader {
-       /// Called with the message type that was received and the buffer to be read.
-       /// Can return a `MessageHandlingError` if the message could not be handled.
+       /// Handles the given message sent from `sender_node_id`, possibly producing messages for
+       /// [`CustomMessageHandler::get_and_clear_pending_msg`] to return and thus for [`PeerManager`]
+       /// to send.
        fn handle_custom_message(&self, msg: Self::CustomMessage, sender_node_id: &PublicKey) -> Result<(), LightningError>;
 
-       /// Gets the list of pending messages which were generated by the custom message
-       /// handler, clearing the list in the process. The first tuple element must
-       /// correspond to the intended recipients node ids. If no connection to one of the
-       /// specified node does not exist, the message is simply not sent to it.
+       /// Returns the list of pending messages that were generated by the handler, clearing the list
+       /// in the process. Each message is paired with the node id of the intended recipient. If no
+       /// connection to the node exists, then the message is simply not sent.
        fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)>;
 }
 
@@ -71,8 +78,8 @@ impl RoutingMessageHandler for IgnoringMessageHandler {
        fn handle_channel_update(&self, _msg: &msgs::ChannelUpdate) -> Result<bool, LightningError> { Ok(false) }
        fn get_next_channel_announcement(&self, _starting_point: u64) ->
                Option<(msgs::ChannelAnnouncement, Option<msgs::ChannelUpdate>, Option<msgs::ChannelUpdate>)> { None }
-       fn get_next_node_announcement(&self, _starting_point: Option<&PublicKey>) -> Option<msgs::NodeAnnouncement> { None }
-       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
+       fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option<msgs::NodeAnnouncement> { None }
+       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
        fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), LightningError> { Ok(()) }
        fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) }
        fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::QueryChannelRange) -> Result<(), LightningError> { Ok(()) }
@@ -81,14 +88,15 @@ impl RoutingMessageHandler for IgnoringMessageHandler {
        fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
                InitFeatures::empty()
        }
+       fn processing_queue_high(&self) -> bool { false }
 }
 impl OnionMessageProvider for IgnoringMessageHandler {
        fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option<msgs::OnionMessage> { None }
 }
 impl OnionMessageHandler for IgnoringMessageHandler {
        fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {}
-       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
-       fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
+       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
+       fn peer_disconnected(&self, _their_node_id: &PublicKey) {}
        fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
        fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
                InitFeatures::empty()
@@ -222,8 +230,8 @@ impl ChannelMessageHandler for ErroringMessageHandler {
        }
        // msgs::ChannelUpdate does not contain the channel_id field, so we just drop them.
        fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelUpdate) {}
-       fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
-       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
+       fn peer_disconnected(&self, _their_node_id: &PublicKey) {}
+       fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
        fn handle_error(&self, _their_node_id: &PublicKey, _msg: &msgs::ErrorMessage) {}
        fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
        fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
@@ -314,16 +322,7 @@ pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone {
 /// generate no further read_event/write_buffer_space_avail/socket_disconnected calls for the
 /// descriptor.
 #[derive(Clone)]
-pub struct PeerHandleError {
-       /// Used to indicate that we probably can't make any future connections to this peer (e.g.
-       /// because we required features that our peer was missing, or vice versa).
-       ///
-       /// While LDK's [`ChannelManager`] will not do it automatically, you likely wish to force-close
-       /// any channels with this peer or check for new versions of LDK.
-       ///
-       /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
-       pub no_connection_possible: bool,
-}
+pub struct PeerHandleError { }
 impl fmt::Debug for PeerHandleError {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                formatter.write_str("Peer Sent Invalid Data")
@@ -345,7 +344,7 @@ impl error::Error for PeerHandleError {
 enum InitSyncTracker{
        NoSyncRequested,
        ChannelsSyncing(u64),
-       NodesSyncing(PublicKey),
+       NodesSyncing(NodeId),
 }
 
 /// The ratio between buffer sizes at which we stop sending initial sync messages vs when we stop
@@ -389,7 +388,15 @@ const BUFFER_DRAIN_MSGS_PER_TICK: usize = 32;
 
 struct Peer {
        channel_encryptor: PeerChannelEncryptor,
-       their_node_id: Option<PublicKey>,
+       /// We cache a `NodeId` here to avoid serializing peers' keys every time we forward gossip
+       /// messages in `PeerManager`. Use `Peer::set_their_node_id` to modify this field.
+       their_node_id: Option<(PublicKey, NodeId)>,
+       /// The features provided in the peer's [`msgs::Init`] message.
+       ///
+       /// This is set only after we've processed the [`msgs::Init`] message and called relevant
+       /// `peer_connected` handler methods. Thus, this field is set *iff* we've finished our
+       /// handshake and can talk to this peer normally (though use [`Peer::handshake_complete`] to
+       /// check this.
        their_features: Option<InitFeatures>,
        their_net_address: Option<NetAddress>,
 
@@ -412,9 +419,24 @@ struct Peer {
        awaiting_pong_timer_tick_intervals: i8,
        received_message_since_timer_tick: bool,
        sent_gossip_timestamp_filter: bool,
+
+       /// Indicates we've received a `channel_announcement` since the last time we had
+       /// [`PeerManager::gossip_processing_backlogged`] set (or, really, that we've received a
+       /// `channel_announcement` at all - we set this unconditionally but unset it every time we
+       /// check if we're gossip-processing-backlogged).
+       received_channel_announce_since_backlogged: bool,
+
+       inbound_connection: bool,
 }
 
 impl Peer {
+       /// True after we've processed the [`msgs::Init`] message and called relevant `peer_connected`
+       /// handler methods. Thus, this implies we've finished our handshake and can talk to this peer
+       /// normally.
+       fn handshake_complete(&self) -> bool {
+               self.their_features.is_some()
+       }
+
        /// Returns true if the channel announcements/updates for the given channel should be
        /// forwarded to this peer.
        /// If we are sending our routing table to this peer and we have not yet sent channel
@@ -422,6 +444,7 @@ impl Peer {
        /// point and we shouldn't send it yet to avoid sending duplicate updates. If we've already
        /// sent the old versions, we should send the update, and so return true here.
        fn should_forward_channel_announcement(&self, channel_id: u64) -> bool {
+               if !self.handshake_complete() { return false; }
                if self.their_features.as_ref().unwrap().supports_gossip_queries() &&
                        !self.sent_gossip_timestamp_filter {
                                return false;
@@ -434,7 +457,8 @@ impl Peer {
        }
 
        /// Similar to the above, but for node announcements indexed by node_id.
-       fn should_forward_node_announcement(&self, node_id: PublicKey) -> bool {
+       fn should_forward_node_announcement(&self, node_id: NodeId) -> bool {
+               if !self.handshake_complete() { return false; }
                if self.their_features.as_ref().unwrap().supports_gossip_queries() &&
                        !self.sent_gossip_timestamp_filter {
                                return false;
@@ -442,14 +466,18 @@ impl Peer {
                match self.sync_status {
                        InitSyncTracker::NoSyncRequested => true,
                        InitSyncTracker::ChannelsSyncing(_) => false,
-                       InitSyncTracker::NodesSyncing(pk) => pk < node_id,
+                       InitSyncTracker::NodesSyncing(sync_node_id) => sync_node_id.as_slice() < node_id.as_slice(),
                }
        }
 
        /// Returns whether we should be reading bytes from this peer, based on whether its outbound
        /// buffer still has space and we don't need to pause reads to get some writes out.
-       fn should_read(&self) -> bool {
-               self.pending_outbound_buffer.len() < OUTBOUND_BUFFER_LIMIT_READ_PAUSE
+       fn should_read(&mut self, gossip_processing_backlogged: bool) -> bool {
+               if !gossip_processing_backlogged {
+                       self.received_channel_announce_since_backlogged = false;
+               }
+               self.pending_outbound_buffer.len() < OUTBOUND_BUFFER_LIMIT_READ_PAUSE &&
+                       (!gossip_processing_backlogged || !self.received_channel_announce_since_backlogged)
        }
 
        /// Determines if we should push additional gossip background sync (aka "backfill") onto a peer's
@@ -457,19 +485,20 @@ impl Peer {
        fn should_buffer_gossip_backfill(&self) -> bool {
                self.pending_outbound_buffer.is_empty() && self.gossip_broadcast_buffer.is_empty()
                        && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK
+                       && self.handshake_complete()
        }
 
        /// Determines if we should push an onion message onto a peer's outbound buffer. This is checked
        /// every time the peer's buffer may have been drained.
        fn should_buffer_onion_message(&self) -> bool {
-               self.pending_outbound_buffer.is_empty()
+               self.pending_outbound_buffer.is_empty() && self.handshake_complete()
                        && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK
        }
 
        /// Determines if we should push additional gossip broadcast messages onto a peer's outbound
        /// buffer. This is checked every time the peer's buffer may have been drained.
        fn should_buffer_gossip_broadcast(&self) -> bool {
-               self.pending_outbound_buffer.is_empty()
+               self.pending_outbound_buffer.is_empty() && self.handshake_complete()
                        && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK
        }
 
@@ -481,6 +510,10 @@ impl Peer {
                total_outbound_buffered > OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP ||
                        self.msgs_sent_since_pong > BUFFER_DRAIN_MSGS_PER_TICK * FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO
        }
+
+       fn set_their_node_id(&mut self, node_id: PublicKey) {
+               self.their_node_id = Some((node_id, NodeId::from_pubkey(&node_id)));
+       }
 }
 
 /// SimpleArcPeerManager is useful when you need a PeerManager with a static lifetime, e.g.
@@ -562,6 +595,9 @@ pub struct PeerManager<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: D
 
        peer_counter: AtomicCounter,
 
+       gossip_processing_backlogged: AtomicBool,
+       gossip_processing_backlog_lifted: AtomicBool,
+
        node_signer: NS,
 
        logger: L,
@@ -651,10 +687,10 @@ impl<Descriptor: SocketDescriptor, RM: Deref, L: Deref, NS: Deref> PeerManager<D
 /// This works around `format!()` taking a reference to each argument, preventing
 /// `if let Some(node_id) = peer.their_node_id { format!(.., node_id) } else { .. }` from compiling
 /// due to lifetime errors.
-struct OptionalFromDebugger<'a>(&'a Option<PublicKey>);
+struct OptionalFromDebugger<'a>(&'a Option<(PublicKey, NodeId)>);
 impl core::fmt::Display for OptionalFromDebugger<'_> {
        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
-               if let Some(node_id) = self.0 { write!(f, " from {}", log_pubkey!(node_id)) } else { Ok(()) }
+               if let Some((node_id, _)) = self.0 { write!(f, " from {}", log_pubkey!(node_id)) } else { Ok(()) }
        }
 }
 
@@ -720,6 +756,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        blocked_event_processors: AtomicBool::new(false),
                        ephemeral_key_midstate,
                        peer_counter: AtomicCounter::new(),
+                       gossip_processing_backlogged: AtomicBool::new(false),
+                       gossip_processing_backlog_lifted: AtomicBool::new(false),
                        last_node_announcement_serial: AtomicU32::new(current_time),
                        logger,
                        custom_message_handler,
@@ -728,19 +766,24 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                }
        }
 
-       /// Get the list of node ids for peers which have completed the initial handshake.
+       /// Get a list of tuples mapping from node id to network addresses for peers which have
+       /// completed the initial handshake.
        ///
-       /// For outbound connections, this will be the same as the their_node_id parameter passed in to
-       /// new_outbound_connection, however entries will only appear once the initial handshake has
-       /// completed and we are sure the remote peer has the private key for the given node_id.
-       pub fn get_peer_node_ids(&self) -> Vec<PublicKey> {
+       /// For outbound connections, the [`PublicKey`] will be the same as the `their_node_id` parameter
+       /// passed in to [`Self::new_outbound_connection`], however entries will only appear once the initial
+       /// handshake has completed and we are sure the remote peer has the private key for the given
+       /// [`PublicKey`].
+       ///
+       /// The returned `Option`s will only be `Some` if an address had been previously given via
+       /// [`Self::new_outbound_connection`] or [`Self::new_inbound_connection`].
+       pub fn get_peer_node_ids(&self) -> Vec<(PublicKey, Option<NetAddress>)> {
                let peers = self.peers.read().unwrap();
                peers.values().filter_map(|peer_mutex| {
                        let p = peer_mutex.lock().unwrap();
-                       if !p.channel_encryptor.is_ready_for_encryption() || p.their_features.is_none() {
+                       if !p.handshake_complete() {
                                return None;
                        }
-                       p.their_node_id
+                       Some((p.their_node_id.unwrap().0, p.their_net_address.clone()))
                }).collect()
        }
 
@@ -751,7 +794,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).into_inner()).expect("You broke SHA-256!")
        }
 
-       /// Indicates a new outbound connection has been established to a node with the given node_id
+       /// Indicates a new outbound connection has been established to a node with the given `node_id`
        /// and an optional remote network address.
        ///
        /// The remote network address adds the option to report a remote IP address back to a connecting
@@ -793,6 +836,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        awaiting_pong_timer_tick_intervals: 0,
                        received_message_since_timer_tick: false,
                        sent_gossip_timestamp_filter: false,
+
+                       received_channel_announce_since_backlogged: false,
+                       inbound_connection: false,
                })).is_some() {
                        panic!("PeerManager driver duplicated descriptors!");
                };
@@ -840,16 +886,32 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        awaiting_pong_timer_tick_intervals: 0,
                        received_message_since_timer_tick: false,
                        sent_gossip_timestamp_filter: false,
+
+                       received_channel_announce_since_backlogged: false,
+                       inbound_connection: true,
                })).is_some() {
                        panic!("PeerManager driver duplicated descriptors!");
                };
                Ok(())
        }
 
-       fn do_attempt_write_data(&self, descriptor: &mut Descriptor, peer: &mut Peer) {
+       fn peer_should_read(&self, peer: &mut Peer) -> bool {
+               peer.should_read(self.gossip_processing_backlogged.load(Ordering::Relaxed))
+       }
+
+       fn update_gossip_backlogged(&self) {
+               let new_state = self.message_handler.route_handler.processing_queue_high();
+               let prev_state = self.gossip_processing_backlogged.swap(new_state, Ordering::Relaxed);
+               if prev_state && !new_state {
+                       self.gossip_processing_backlog_lifted.store(true, Ordering::Relaxed);
+               }
+       }
+
+       fn do_attempt_write_data(&self, descriptor: &mut Descriptor, peer: &mut Peer, force_one_write: bool) {
+               let mut have_written = false;
                while !peer.awaiting_write_event {
                        if peer.should_buffer_onion_message() {
-                               if let Some(peer_node_id) = peer.their_node_id {
+                               if let Some((peer_node_id, _)) = peer.their_node_id {
                                        if let Some(next_onion_message) =
                                                self.message_handler.onion_message_handler.next_onion_message_for_peer(peer_node_id) {
                                                        self.enqueue_message(peer, &next_onion_message);
@@ -889,8 +951,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                }
                                        },
                                        InitSyncTracker::ChannelsSyncing(_) => unreachable!(),
-                                       InitSyncTracker::NodesSyncing(key) => {
-                                               if let Some(msg) = self.message_handler.route_handler.get_next_node_announcement(Some(&key)) {
+                                       InitSyncTracker::NodesSyncing(sync_node_id) => {
+                                               if let Some(msg) = self.message_handler.route_handler.get_next_node_announcement(Some(&sync_node_id)) {
                                                        self.enqueue_message(peer, &msg);
                                                        peer.sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id);
                                                } else {
@@ -903,13 +965,23 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                self.maybe_send_extra_ping(peer);
                        }
 
+                       let should_read = self.peer_should_read(peer);
                        let next_buff = match peer.pending_outbound_buffer.front() {
-                               None => return,
+                               None => {
+                                       if force_one_write && !have_written {
+                                               if should_read {
+                                                       let data_sent = descriptor.send_data(&[], should_read);
+                                                       debug_assert_eq!(data_sent, 0, "Can't write more than no data");
+                                               }
+                                       }
+                                       return
+                               },
                                Some(buff) => buff,
                        };
 
                        let pending = &next_buff[peer.pending_outbound_buffer_first_msg_offset..];
-                       let data_sent = descriptor.send_data(pending, peer.should_read());
+                       let data_sent = descriptor.send_data(pending, should_read);
+                       have_written = true;
                        peer.pending_outbound_buffer_first_msg_offset += data_sent;
                        if peer.pending_outbound_buffer_first_msg_offset == next_buff.len() {
                                peer.pending_outbound_buffer_first_msg_offset = 0;
@@ -939,12 +1011,12 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                // This is most likely a simple race condition where the user found that the socket
                                // was writeable, then we told the user to `disconnect_socket()`, then they called
                                // this method. Return an error to make sure we get disconnected.
-                               return Err(PeerHandleError { no_connection_possible: false });
+                               return Err(PeerHandleError { });
                        },
                        Some(peer_mutex) => {
                                let mut peer = peer_mutex.lock().unwrap();
                                peer.awaiting_write_event = false;
-                               self.do_attempt_write_data(descriptor, &mut peer);
+                               self.do_attempt_write_data(descriptor, &mut peer, false);
                        }
                };
                Ok(())
@@ -962,6 +1034,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
        /// [`send_data`] call on this descriptor has `resume_read` set (preventing DoS issues in the
        /// send buffer).
        ///
+       /// In order to avoid processing too many messages at once per peer, `data` should be on the
+       /// order of 4KiB.
+       ///
        /// [`send_data`]: SocketDescriptor::send_data
        /// [`process_events`]: PeerManager::process_events
        pub fn read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result<bool, PeerHandleError> {
@@ -969,7 +1044,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        Ok(res) => Ok(res),
                        Err(e) => {
                                log_trace!(self.logger, "Peer sent invalid data or we decided to disconnect due to a protocol error");
-                               self.disconnect_event_internal(peer_descriptor, e.no_connection_possible);
+                               self.disconnect_event_internal(peer_descriptor);
                                Err(e)
                        }
                }
@@ -978,9 +1053,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
        /// Append a message to a peer's pending outbound/write buffer
        fn enqueue_message<M: wire::Type>(&self, peer: &mut Peer, message: &M) {
                if is_gossip_msg(message.type_id()) {
-                       log_gossip!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()));
+                       log_gossip!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap().0));
                } else {
-                       log_trace!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()))
+                       log_trace!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap().0))
                }
                peer.msgs_sent_since_pong += 1;
                peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(message));
@@ -1002,7 +1077,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                // This is most likely a simple race condition where the user read some bytes
                                // from the socket, then we told the user to `disconnect_socket()`, then they
                                // called this method. Return an error to make sure we get disconnected.
-                               return Err(PeerHandleError { no_connection_possible: false });
+                               return Err(PeerHandleError { });
                        },
                        Some(peer_mutex) => {
                                let mut read_pos = 0;
@@ -1016,7 +1091,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                                msgs::ErrorAction::DisconnectPeer { msg: _ } => {
                                                                                        //TODO: Try to push msg
                                                                                        log_debug!(self.logger, "Error handling message{}; disconnecting peer with: {}", OptionalFromDebugger(&peer_node_id), e.err);
-                                                                                       return Err(PeerHandleError{ no_connection_possible: false });
+                                                                                       return Err(PeerHandleError { });
                                                                                },
                                                                                msgs::ErrorAction::IgnoreAndLog(level) => {
                                                                                        log_given_level!(self.logger, level, "Error handling message{}; ignoring: {}", OptionalFromDebugger(&peer_node_id), e.err);
@@ -1065,14 +1140,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                                                macro_rules! insert_node_id {
                                                        () => {
-                                                               match self.node_id_to_descriptor.lock().unwrap().entry(peer.their_node_id.unwrap()) {
+                                                               match self.node_id_to_descriptor.lock().unwrap().entry(peer.their_node_id.unwrap().0) {
                                                                        hash_map::Entry::Occupied(_) => {
-                                                                               log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(peer.their_node_id.unwrap()));
+                                                                               log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(peer.their_node_id.unwrap().0));
                                                                                peer.their_node_id = None; // Unset so that we don't generate a peer_disconnected event
-                                                                               return Err(PeerHandleError{ no_connection_possible: false })
+                                                                               return Err(PeerHandleError { })
                                                                        },
                                                                        hash_map::Entry::Vacant(entry) => {
-                                                                               log_debug!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(peer.their_node_id.unwrap()));
+                                                                               log_debug!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(peer.their_node_id.unwrap().0));
                                                                                entry.insert(peer_descriptor.clone())
                                                                        },
                                                                };
@@ -1096,7 +1171,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
                                                                peer.pending_read_is_header = true;
 
-                                                               peer.their_node_id = Some(their_node_id);
+                                                               peer.set_their_node_id(their_node_id);
                                                                insert_node_id!();
                                                                let features = self.message_handler.chan_handler.provided_init_features(&their_node_id)
                                                                        .or(self.message_handler.route_handler.provided_init_features(&their_node_id))
@@ -1110,7 +1185,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                        peer.channel_encryptor.process_act_three(&peer.pending_read_buffer[..]));
                                                                peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
                                                                peer.pending_read_is_header = true;
-                                                               peer.their_node_id = Some(their_node_id);
+                                                               peer.set_their_node_id(their_node_id);
                                                                insert_node_id!();
                                                                let features = self.message_handler.chan_handler.provided_init_features(&their_node_id)
                                                                        .or(self.message_handler.route_handler.provided_init_features(&their_node_id))
@@ -1126,7 +1201,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                        if peer.pending_read_buffer.capacity() > 8192 { peer.pending_read_buffer = Vec::new(); }
                                                                        peer.pending_read_buffer.resize(msg_len as usize + 16, 0);
                                                                        if msg_len < 2 { // Need at least the message type tag
-                                                                               return Err(PeerHandleError{ no_connection_possible: false });
+                                                                               return Err(PeerHandleError { });
                                                                        }
                                                                        peer.pending_read_is_header = false;
                                                                } else {
@@ -1169,19 +1244,19 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                                                (msgs::DecodeError::UnknownRequiredFeature, ty) => {
                                                                                                        log_gossip!(self.logger, "Received a message with an unknown required feature flag or TLV, you may want to update!");
                                                                                                        self.enqueue_message(peer, &msgs::WarningMessage { channel_id: [0; 32], data: format!("Received an unknown required feature/TLV in message type {:?}", ty) });
-                                                                                                       return Err(PeerHandleError { no_connection_possible: false });
+                                                                                                       return Err(PeerHandleError { });
                                                                                                }
-                                                                                               (msgs::DecodeError::UnknownVersion, _) => return Err(PeerHandleError { no_connection_possible: false }),
+                                                                                               (msgs::DecodeError::UnknownVersion, _) => return Err(PeerHandleError { }),
                                                                                                (msgs::DecodeError::InvalidValue, _) => {
                                                                                                        log_debug!(self.logger, "Got an invalid value while deserializing message");
-                                                                                                       return Err(PeerHandleError { no_connection_possible: false });
+                                                                                                       return Err(PeerHandleError { });
                                                                                                }
                                                                                                (msgs::DecodeError::ShortRead, _) => {
                                                                                                        log_debug!(self.logger, "Deserialization failed due to shortness of message");
-                                                                                                       return Err(PeerHandleError { no_connection_possible: false });
+                                                                                                       return Err(PeerHandleError { });
                                                                                                }
-                                                                                               (msgs::DecodeError::BadLengthDescriptor, _) => return Err(PeerHandleError { no_connection_possible: false }),
-                                                                                               (msgs::DecodeError::Io(_), _) => return Err(PeerHandleError { no_connection_possible: false }),
+                                                                                               (msgs::DecodeError::BadLengthDescriptor, _) => return Err(PeerHandleError { }),
+                                                                                               (msgs::DecodeError::Io(_), _) => return Err(PeerHandleError { }),
                                                                                        }
                                                                                }
                                                                        };
@@ -1191,7 +1266,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                        }
                                                }
                                        }
-                                       pause_read = !peer.should_read();
+                                       pause_read = !self.peer_should_read(peer);
 
                                        if let Some(message) = msg_to_handle {
                                                match self.handle_message(&peer_mutex, peer_lock, message) {
@@ -1212,7 +1287,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                }
 
                for msg in msgs_to_forward.drain(..) {
-                       self.forward_broadcast_msg(&*peers, &msg, peer_node_id.as_ref());
+                       self.forward_broadcast_msg(&*peers, &msg, peer_node_id.as_ref().map(|(pk, _)| pk));
                }
 
                Ok(pause_read)
@@ -1226,17 +1301,17 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                mut peer_lock: MutexGuard<Peer>,
                message: wire::Message<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>
        ) -> Result<Option<wire::Message<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> {
-               let their_node_id = peer_lock.their_node_id.clone().expect("We know the peer's public key by the time we receive messages");
+               let their_node_id = peer_lock.their_node_id.clone().expect("We know the peer's public key by the time we receive messages").0;
                peer_lock.received_message_since_timer_tick = true;
 
                // Need an Init as first message
                if let wire::Message::Init(msg) = message {
                        if msg.features.requires_unknown_bits() {
                                log_debug!(self.logger, "Peer features required unknown version bits");
-                               return Err(PeerHandleError{ no_connection_possible: true }.into());
+                               return Err(PeerHandleError { }.into());
                        }
                        if peer_lock.their_features.is_some() {
-                               return Err(PeerHandleError{ no_connection_possible: false }.into());
+                               return Err(PeerHandleError { }.into());
                        }
 
                        log_info!(self.logger, "Received peer Init message from {}: {}", log_pubkey!(their_node_id), msg.features);
@@ -1246,24 +1321,24 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                peer_lock.sync_status = InitSyncTracker::ChannelsSyncing(0);
                        }
 
-                       if let Err(()) = self.message_handler.route_handler.peer_connected(&their_node_id, &msg) {
+                       if let Err(()) = self.message_handler.route_handler.peer_connected(&their_node_id, &msg, peer_lock.inbound_connection) {
                                log_debug!(self.logger, "Route Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
-                               return Err(PeerHandleError{ no_connection_possible: true }.into());
+                               return Err(PeerHandleError { }.into());
                        }
-                       if let Err(()) = self.message_handler.chan_handler.peer_connected(&their_node_id, &msg) {
+                       if let Err(()) = self.message_handler.chan_handler.peer_connected(&their_node_id, &msg, peer_lock.inbound_connection) {
                                log_debug!(self.logger, "Channel Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
-                               return Err(PeerHandleError{ no_connection_possible: true }.into());
+                               return Err(PeerHandleError { }.into());
                        }
-                       if let Err(()) = self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg) {
+                       if let Err(()) = self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg, peer_lock.inbound_connection) {
                                log_debug!(self.logger, "Onion Message Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
-                               return Err(PeerHandleError{ no_connection_possible: true }.into());
+                               return Err(PeerHandleError { }.into());
                        }
 
                        peer_lock.their_features = Some(msg.features);
                        return Ok(None);
                } else if peer_lock.their_features.is_none() {
                        log_debug!(self.logger, "Peer {} sent non-Init first message", log_pubkey!(their_node_id));
-                       return Err(PeerHandleError{ no_connection_possible: false }.into());
+                       return Err(PeerHandleError { }.into());
                }
 
                if let wire::Message::GossipTimestampFilter(_msg) = message {
@@ -1277,6 +1352,10 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        return Ok(None);
                }
 
+               if let wire::Message::ChannelAnnouncement(ref _msg) = message {
+                       peer_lock.received_channel_announce_since_backlogged = true;
+               }
+
                mem::drop(peer_lock);
 
                if is_gossip_msg(message.type_id()) {
@@ -1311,7 +1390,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                }
                                self.message_handler.chan_handler.handle_error(&their_node_id, &msg);
                                if msg.channel_id == [0; 32] {
-                                       return Err(PeerHandleError{ no_connection_possible: true }.into());
+                                       return Err(PeerHandleError { }.into());
                                }
                        },
                        wire::Message::Warning(msg) => {
@@ -1403,12 +1482,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                .map_err(|e| -> MessageHandlingError { e.into() })? {
                                        should_forward = Some(wire::Message::ChannelAnnouncement(msg));
                                }
+                               self.update_gossip_backlogged();
                        },
                        wire::Message::NodeAnnouncement(msg) => {
                                if self.message_handler.route_handler.handle_node_announcement(&msg)
                                                .map_err(|e| -> MessageHandlingError { e.into() })? {
                                        should_forward = Some(wire::Message::NodeAnnouncement(msg));
                                }
+                               self.update_gossip_backlogged();
                        },
                        wire::Message::ChannelUpdate(msg) => {
                                self.message_handler.chan_handler.handle_channel_update(&their_node_id, &msg);
@@ -1416,6 +1497,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                .map_err(|e| -> MessageHandlingError { e.into() })? {
                                        should_forward = Some(wire::Message::ChannelUpdate(msg));
                                }
+                               self.update_gossip_backlogged();
                        },
                        wire::Message::QueryShortChannelIds(msg) => {
                                self.message_handler.route_handler.handle_query_short_channel_ids(&their_node_id, msg)?;
@@ -1438,8 +1520,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        // Unknown messages:
                        wire::Message::Unknown(type_id) if message.is_even() => {
                                log_debug!(self.logger, "Received unknown even message of type {}, disconnecting peer!", type_id);
-                               // Fail the channel if message is an even, unknown type as per BOLT #1.
-                               return Err(PeerHandleError{ no_connection_possible: true }.into());
+                               return Err(PeerHandleError { }.into());
                        },
                        wire::Message::Unknown(type_id) => {
                                log_trace!(self.logger, "Received unknown odd message of type {}, ignoring", type_id);
@@ -1459,19 +1540,22 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                                for (_, peer_mutex) in peers.iter() {
                                        let mut peer = peer_mutex.lock().unwrap();
-                                       if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||
+                                       if !peer.handshake_complete() ||
                                                        !peer.should_forward_channel_announcement(msg.contents.short_channel_id) {
                                                continue
                                        }
+                                       debug_assert!(peer.their_node_id.is_some());
+                                       debug_assert!(peer.channel_encryptor.is_ready_for_encryption());
                                        if peer.buffer_full_drop_gossip_broadcast() {
                                                log_gossip!(self.logger, "Skipping broadcast message to {:?} as its outbound buffer is full", peer.their_node_id);
                                                continue;
                                        }
-                                       if peer.their_node_id.as_ref() == Some(&msg.contents.node_id_1) ||
-                                          peer.their_node_id.as_ref() == Some(&msg.contents.node_id_2) {
-                                               continue;
+                                       if let Some((_, their_node_id)) = peer.their_node_id {
+                                               if their_node_id == msg.contents.node_id_1 || their_node_id == msg.contents.node_id_2 {
+                                                       continue;
+                                               }
                                        }
-                                       if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
+                                       if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
                                                continue;
                                        }
                                        self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
@@ -1483,18 +1567,22 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                                for (_, peer_mutex) in peers.iter() {
                                        let mut peer = peer_mutex.lock().unwrap();
-                                       if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||
+                                       if !peer.handshake_complete() ||
                                                        !peer.should_forward_node_announcement(msg.contents.node_id) {
                                                continue
                                        }
+                                       debug_assert!(peer.their_node_id.is_some());
+                                       debug_assert!(peer.channel_encryptor.is_ready_for_encryption());
                                        if peer.buffer_full_drop_gossip_broadcast() {
                                                log_gossip!(self.logger, "Skipping broadcast message to {:?} as its outbound buffer is full", peer.their_node_id);
                                                continue;
                                        }
-                                       if peer.their_node_id.as_ref() == Some(&msg.contents.node_id) {
-                                               continue;
+                                       if let Some((_, their_node_id)) = peer.their_node_id {
+                                               if their_node_id == msg.contents.node_id {
+                                                       continue;
+                                               }
                                        }
-                                       if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
+                                       if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
                                                continue;
                                        }
                                        self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
@@ -1506,15 +1594,17 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                                for (_, peer_mutex) in peers.iter() {
                                        let mut peer = peer_mutex.lock().unwrap();
-                                       if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||
+                                       if !peer.handshake_complete() ||
                                                        !peer.should_forward_channel_announcement(msg.contents.short_channel_id)  {
                                                continue
                                        }
+                                       debug_assert!(peer.their_node_id.is_some());
+                                       debug_assert!(peer.channel_encryptor.is_ready_for_encryption());
                                        if peer.buffer_full_drop_gossip_broadcast() {
                                                log_gossip!(self.logger, "Skipping broadcast message to {:?} as its outbound buffer is full", peer.their_node_id);
                                                continue;
                                        }
-                                       if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
+                                       if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
                                                continue;
                                        }
                                        self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
@@ -1563,6 +1653,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        }
                }
 
+               self.update_gossip_backlogged();
+               let flush_read_disabled = self.gossip_processing_backlog_lifted.swap(false, Ordering::Relaxed);
+
                let mut peers_to_disconnect = HashMap::new();
                let mut events_generated = self.message_handler.chan_handler.get_and_clear_pending_msg_events();
                events_generated.append(&mut self.message_handler.route_handler.get_and_clear_pending_msg_events());
@@ -1586,7 +1679,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                        Some(descriptor) => match peers.get(&descriptor) {
                                                                Some(peer_mutex) => {
                                                                        let peer_lock = peer_mutex.lock().unwrap();
-                                                                       if peer_lock.their_features.is_none() {
+                                                                       if !peer_lock.handshake_complete() {
                                                                                continue;
                                                                        }
                                                                        peer_lock
@@ -1707,10 +1800,12 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                self.forward_broadcast_msg(peers, &wire::Message::ChannelAnnouncement(msg), None),
                                                        _ => {},
                                                }
-                                               match self.message_handler.route_handler.handle_channel_update(&update_msg) {
-                                                       Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) =>
-                                                               self.forward_broadcast_msg(peers, &wire::Message::ChannelUpdate(update_msg), None),
-                                                       _ => {},
+                                               if let Some(msg) = update_msg {
+                                                       match self.message_handler.route_handler.handle_channel_update(&msg) {
+                                                               Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) =>
+                                                                       self.forward_broadcast_msg(peers, &wire::Message::ChannelUpdate(msg), None),
+                                                               _ => {},
+                                                       }
                                                }
                                        },
                                        MessageSendEvent::BroadcastChannelUpdate { msg } => {
@@ -1721,6 +1816,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                        _ => {},
                                                }
                                        },
+                                       MessageSendEvent::BroadcastNodeAnnouncement { msg } => {
+                                               log_debug!(self.logger, "Handling BroadcastNodeAnnouncement event in peer_handler for node {}", msg.contents.node_id);
+                                               match self.message_handler.route_handler.handle_node_announcement(&msg) {
+                                                       Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) =>
+                                                               self.forward_broadcast_msg(peers, &wire::Message::NodeAnnouncement(msg), None),
+                                                       _ => {},
+                                               }
+                                       },
                                        MessageSendEvent::SendChannelUpdate { ref node_id, ref msg } => {
                                                log_trace!(self.logger, "Handling SendChannelUpdate event in peer_handler for node {} for channel {}",
                                                                log_pubkey!(node_id), msg.contents.short_channel_id);
@@ -1782,7 +1885,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        }
 
                        for (descriptor, peer_mutex) in peers.iter() {
-                               self.do_attempt_write_data(&mut (*descriptor).clone(), &mut *peer_mutex.lock().unwrap());
+                               let mut peer = peer_mutex.lock().unwrap();
+                               if flush_read_disabled { peer.received_channel_announce_since_backlogged = false; }
+                               self.do_attempt_write_data(&mut (*descriptor).clone(), &mut *peer, flush_read_disabled);
                        }
                }
                if !peers_to_disconnect.is_empty() {
@@ -1794,24 +1899,21 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                // thread can be holding the peer lock if we have the global write
                                // lock).
 
-                               if let Some(mut descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
+                               let descriptor_opt = self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
+                               if let Some(mut descriptor) = descriptor_opt {
                                        if let Some(peer_mutex) = peers.remove(&descriptor) {
+                                               let mut peer = peer_mutex.lock().unwrap();
                                                if let Some(msg) = msg {
                                                        log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with message {}",
                                                                        log_pubkey!(node_id),
                                                                        msg.data);
-                                                       let mut peer = peer_mutex.lock().unwrap();
                                                        self.enqueue_message(&mut *peer, &msg);
                                                        // This isn't guaranteed to work, but if there is enough free
                                                        // room in the send buffer, put the error message there...
-                                                       self.do_attempt_write_data(&mut descriptor, &mut *peer);
-                                               } else {
-                                                       log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with no message", log_pubkey!(node_id));
+                                                       self.do_attempt_write_data(&mut descriptor, &mut *peer, false);
                                                }
+                                               self.do_disconnect(descriptor, &*peer, "DisconnectPeer HandleError");
                                        }
-                                       descriptor.disconnect_socket();
-                                       self.message_handler.chan_handler.peer_disconnected(&node_id, false);
-                                       self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
                                }
                        }
                }
@@ -1819,10 +1921,26 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
        /// Indicates that the given socket descriptor's connection is now closed.
        pub fn socket_disconnected(&self, descriptor: &Descriptor) {
-               self.disconnect_event_internal(descriptor, false);
+               self.disconnect_event_internal(descriptor);
        }
 
-       fn disconnect_event_internal(&self, descriptor: &Descriptor, no_connection_possible: bool) {
+       fn do_disconnect(&self, mut descriptor: Descriptor, peer: &Peer, reason: &'static str) {
+               if !peer.handshake_complete() {
+                       log_trace!(self.logger, "Disconnecting peer which hasn't completed handshake due to {}", reason);
+                       descriptor.disconnect_socket();
+                       return;
+               }
+
+               debug_assert!(peer.their_node_id.is_some());
+               if let Some((node_id, _)) = peer.their_node_id {
+                       log_trace!(self.logger, "Disconnecting peer with id {} due to {}", node_id, reason);
+                       self.message_handler.chan_handler.peer_disconnected(&node_id);
+                       self.message_handler.onion_message_handler.peer_disconnected(&node_id);
+               }
+               descriptor.disconnect_socket();
+       }
+
+       fn disconnect_event_internal(&self, descriptor: &Descriptor) {
                let mut peers = self.peers.write().unwrap();
                let peer_option = peers.remove(descriptor);
                match peer_option {
@@ -1833,13 +1951,13 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        },
                        Some(peer_lock) => {
                                let peer = peer_lock.lock().unwrap();
-                               if let Some(node_id) = peer.their_node_id {
-                                       log_trace!(self.logger,
-                                               "Handling disconnection of peer {}, with {}future connection to the peer possible.",
-                                               log_pubkey!(node_id), if no_connection_possible { "no " } else { "" });
+                               if !peer.handshake_complete() { return; }
+                               debug_assert!(peer.their_node_id.is_some());
+                               if let Some((node_id, _)) = peer.their_node_id {
+                                       log_trace!(self.logger, "Handling disconnection of peer {}", log_pubkey!(node_id));
                                        self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
-                                       self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
-                                       self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
+                                       self.message_handler.chan_handler.peer_disconnected(&node_id);
+                                       self.message_handler.onion_message_handler.peer_disconnected(&node_id);
                                }
                        }
                };
@@ -1847,21 +1965,17 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
        /// Disconnect a peer given its node id.
        ///
-       /// Set `no_connection_possible` to true to prevent any further connection with this peer,
-       /// force-closing any channels we have with it.
-       ///
        /// If a peer is connected, this will call [`disconnect_socket`] on the descriptor for the
        /// peer. Thus, be very careful about reentrancy issues.
        ///
        /// [`disconnect_socket`]: SocketDescriptor::disconnect_socket
-       pub fn disconnect_by_node_id(&self, node_id: PublicKey, no_connection_possible: bool) {
+       pub fn disconnect_by_node_id(&self, node_id: PublicKey) {
                let mut peers_lock = self.peers.write().unwrap();
-               if let Some(mut descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
-                       log_trace!(self.logger, "Disconnecting peer with id {} due to client request", node_id);
-                       peers_lock.remove(&descriptor);
-                       self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
-                       self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
-                       descriptor.disconnect_socket();
+               if let Some(descriptor) = self.node_id_to_descriptor.lock().unwrap().remove(&node_id) {
+                       let peer_opt = peers_lock.remove(&descriptor);
+                       if let Some(peer_mutex) = peer_opt {
+                               self.do_disconnect(descriptor, &*peer_mutex.lock().unwrap(), "client request");
+                       } else { debug_assert!(false, "node_id_to_descriptor thought we had a peer"); }
                }
        }
 
@@ -1872,13 +1986,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                let mut peers_lock = self.peers.write().unwrap();
                self.node_id_to_descriptor.lock().unwrap().clear();
                let peers = &mut *peers_lock;
-               for (mut descriptor, peer) in peers.drain() {
-                       if let Some(node_id) = peer.lock().unwrap().their_node_id {
-                               log_trace!(self.logger, "Disconnecting peer with id {} due to client request to disconnect all peers", node_id);
-                               self.message_handler.chan_handler.peer_disconnected(&node_id, false);
-                               self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
-                       }
-                       descriptor.disconnect_socket();
+               for (descriptor, peer_mutex) in peers.drain() {
+                       self.do_disconnect(descriptor, &*peer_mutex.lock().unwrap(), "client request to disconnect all peers");
                }
        }
 
@@ -1912,9 +2021,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                {
                        let peers_lock = self.peers.read().unwrap();
 
+                       self.update_gossip_backlogged();
+                       let flush_read_disabled = self.gossip_processing_backlog_lifted.swap(false, Ordering::Relaxed);
+
                        for (descriptor, peer_mutex) in peers_lock.iter() {
                                let mut peer = peer_mutex.lock().unwrap();
-                               if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_node_id.is_none() {
+                               if flush_read_disabled { peer.received_channel_announce_since_backlogged = false; }
+
+                               if !peer.handshake_complete() {
                                        // The peer needs to complete its handshake before we can exchange messages. We
                                        // give peers one timer tick to complete handshake, reusing
                                        // `awaiting_pong_timer_tick_intervals` to track number of timer ticks taken
@@ -1926,56 +2040,56 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        }
                                        continue;
                                }
+                               debug_assert!(peer.channel_encryptor.is_ready_for_encryption());
+                               debug_assert!(peer.their_node_id.is_some());
 
-                               if peer.awaiting_pong_timer_tick_intervals == -1 {
-                                       // Magic value set in `maybe_send_extra_ping`.
-                                       peer.awaiting_pong_timer_tick_intervals = 1;
+                               loop { // Used as a `goto` to skip writing a Ping message.
+                                       if peer.awaiting_pong_timer_tick_intervals == -1 {
+                                               // Magic value set in `maybe_send_extra_ping`.
+                                               peer.awaiting_pong_timer_tick_intervals = 1;
+                                               peer.received_message_since_timer_tick = false;
+                                               break;
+                                       }
+
+                                       if (peer.awaiting_pong_timer_tick_intervals > 0 && !peer.received_message_since_timer_tick)
+                                               || peer.awaiting_pong_timer_tick_intervals as u64 >
+                                                       MAX_BUFFER_DRAIN_TICK_INTERVALS_PER_PEER as u64 * peers_lock.len() as u64
+                                       {
+                                               descriptors_needing_disconnect.push(descriptor.clone());
+                                               break;
+                                       }
                                        peer.received_message_since_timer_tick = false;
-                                       continue;
-                               }
 
-                               if (peer.awaiting_pong_timer_tick_intervals > 0 && !peer.received_message_since_timer_tick)
-                                       || peer.awaiting_pong_timer_tick_intervals as u64 >
-                                               MAX_BUFFER_DRAIN_TICK_INTERVALS_PER_PEER as u64 * peers_lock.len() as u64
-                               {
-                                       descriptors_needing_disconnect.push(descriptor.clone());
-                                       continue;
-                               }
-                               peer.received_message_since_timer_tick = false;
+                                       if peer.awaiting_pong_timer_tick_intervals > 0 {
+                                               peer.awaiting_pong_timer_tick_intervals += 1;
+                                               break;
+                                       }
 
-                               if peer.awaiting_pong_timer_tick_intervals > 0 {
-                                       peer.awaiting_pong_timer_tick_intervals += 1;
-                                       continue;
+                                       peer.awaiting_pong_timer_tick_intervals = 1;
+                                       let ping = msgs::Ping {
+                                               ponglen: 0,
+                                               byteslen: 64,
+                                       };
+                                       self.enqueue_message(&mut *peer, &ping);
+                                       break;
                                }
-
-                               peer.awaiting_pong_timer_tick_intervals = 1;
-                               let ping = msgs::Ping {
-                                       ponglen: 0,
-                                       byteslen: 64,
-                               };
-                               self.enqueue_message(&mut *peer, &ping);
-                               self.do_attempt_write_data(&mut (descriptor.clone()), &mut *peer);
+                               self.do_attempt_write_data(&mut (descriptor.clone()), &mut *peer, flush_read_disabled);
                        }
                }
 
                if !descriptors_needing_disconnect.is_empty() {
                        {
                                let mut peers_lock = self.peers.write().unwrap();
-                               for descriptor in descriptors_needing_disconnect.iter() {
-                                       if let Some(peer) = peers_lock.remove(descriptor) {
-                                               if let Some(node_id) = peer.lock().unwrap().their_node_id {
-                                                       log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", node_id);
+                               for descriptor in descriptors_needing_disconnect {
+                                       if let Some(peer_mutex) = peers_lock.remove(&descriptor) {
+                                               let peer = peer_mutex.lock().unwrap();
+                                               if let Some((node_id, _)) = peer.their_node_id {
                                                        self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
-                                                       self.message_handler.chan_handler.peer_disconnected(&node_id, false);
-                                                       self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
                                                }
+                                               self.do_disconnect(descriptor, &*peer, "ping timeout");
                                        }
                                }
                        }
-
-                       for mut descriptor in descriptors_needing_disconnect.drain(..) {
-                               descriptor.disconnect_socket();
-                       }
                }
        }
 
@@ -2021,7 +2135,7 @@ 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: self.node_signer.get_node_id(Recipient::Node).unwrap(),
+                       node_id: NodeId::from_pubkey(&self.node_signer.get_node_id(Recipient::Node).unwrap()),
                        rgb, alias, addresses,
                        excess_address_data: Vec::new(),
                        excess_data: Vec::new(),
@@ -2063,6 +2177,7 @@ fn is_gossip_msg(type_id: u16) -> bool {
 #[cfg(test)]
 mod tests {
        use crate::chain::keysinterface::{NodeSigner, Recipient};
+       use crate::ln::peer_channel_encryptor::PeerChannelEncryptor;
        use crate::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler, filter_addresses};
        use crate::ln::{msgs, wire};
        use crate::ln::msgs::NetAddress;
@@ -2138,11 +2253,14 @@ mod tests {
        }
 
        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 id_a = 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 addr_a = NetAddress::IPv4{addr: [127, 0, 0, 1], port: 1000};
+               let id_b = peer_b.node_signer.get_node_id(Recipient::Node).unwrap();
                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();
-               peer_a.new_inbound_connection(fd_a.clone(), None).unwrap();
+               let addr_b = NetAddress::IPv4{addr: [127, 0, 0, 1], port: 1001};
+               let initial_data = peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap();
+               peer_a.new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap();
                assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false);
                peer_a.process_events();
 
@@ -2157,6 +2275,9 @@ mod tests {
                let a_data = fd_a.outbound_data.lock().unwrap().split_off(0);
                assert_eq!(peer_b.read_event(&mut fd_b, &a_data).unwrap(), false);
 
+               assert!(peer_a.get_peer_node_ids().contains(&(id_b, Some(addr_b))));
+               assert!(peer_b.get_peer_node_ids().contains(&(id_a, Some(addr_a))));
+
                (fd_a.clone(), fd_b.clone())
        }
 
@@ -2165,19 +2286,15 @@ mod tests {
                // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
                // push a DisconnectPeer event to remove the node flagged by id
                let cfgs = create_peermgr_cfgs(2);
-               let chan_handler = test_utils::TestChannelMessageHandler::new();
-               let mut peers = create_network(2, &cfgs);
+               let peers = create_network(2, &cfgs);
                establish_connection(&peers[0], &peers[1]);
                assert_eq!(peers[0].peers.read().unwrap().len(), 1);
 
                let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap();
-
-               chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError {
+               cfgs[0].chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError {
                        node_id: their_id,
                        action: msgs::ErrorAction::DisconnectPeer { msg: None },
                });
-               assert_eq!(chan_handler.pending_events.lock().unwrap().len(), 1);
-               peers[0].message_handler.chan_handler = &chan_handler;
 
                peers[0].process_events();
                assert_eq!(peers[0].peers.read().unwrap().len(), 0);
@@ -2211,6 +2328,35 @@ mod tests {
                assert_eq!(peers[1].read_event(&mut fd_b, &a_data).unwrap(), false);
        }
 
+       #[test]
+       fn test_non_init_first_msg() {
+               // Simple test of the first message received over a connection being something other than
+               // Init. This results in an immediate disconnection, which previously included a spurious
+               // peer_disconnected event handed to event handlers (which would panic in
+               // `TestChannelMessageHandler` here).
+               let cfgs = create_peermgr_cfgs(2);
+               let peers = create_network(2, &cfgs);
+
+               let mut fd_dup = FileDescriptor { fd: 3, outbound_data: Arc::new(Mutex::new(Vec::new())) };
+               let addr_dup = NetAddress::IPv4{addr: [127, 0, 0, 1], port: 1003};
+               let id_a = cfgs[0].node_signer.get_node_id(Recipient::Node).unwrap();
+               peers[0].new_inbound_connection(fd_dup.clone(), Some(addr_dup.clone())).unwrap();
+
+               let mut dup_encryptor = PeerChannelEncryptor::new_outbound(id_a, SecretKey::from_slice(&[42; 32]).unwrap());
+               let initial_data = dup_encryptor.get_act_one(&peers[1].secp_ctx);
+               assert_eq!(peers[0].read_event(&mut fd_dup, &initial_data).unwrap(), false);
+               peers[0].process_events();
+
+               let a_data = fd_dup.outbound_data.lock().unwrap().split_off(0);
+               let (act_three, _) =
+                       dup_encryptor.process_act_two(&a_data[..], &&cfgs[1].node_signer).unwrap();
+               assert_eq!(peers[0].read_event(&mut fd_dup, &act_three).unwrap(), false);
+
+               let not_init_msg = msgs::Ping { ponglen: 4, byteslen: 0 };
+               let msg_bytes = dup_encryptor.encrypt_message(&not_init_msg);
+               assert!(peers[0].read_event(&mut fd_dup, &msg_bytes).is_err());
+       }
+
        #[test]
        fn test_disconnect_all_peer() {
                // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
index aca781b9fd6f50ef2908d4fa518678c932ec522f..7636f5c63641edc5e18cb5d7f69d3375a9fa235b 100644 (file)
@@ -66,7 +66,7 @@ fn test_priv_forwarding_rejection() {
                htlc_maximum_msat: None,
        }]);
        let last_hops = vec![route_hint];
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_features(nodes[2].node.invoice_features())
                .with_route_hints(last_hops);
        let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000, TEST_FINAL_CLTV);
@@ -90,8 +90,8 @@ fn test_priv_forwarding_rejection() {
        // Now disconnect nodes[1] from its peers and restart with accept_forwards_to_priv_channels set
        // to true. Sadly there is currently no way to change it at runtime.
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        let nodes_1_serialized = nodes[1].node.encode();
        let monitor_a_serialized = get_monitor!(nodes[1], chan_id_1).encode();
@@ -100,8 +100,8 @@ fn test_priv_forwarding_rejection() {
        no_announce_cfg.accept_forwards_to_priv_channels = true;
        reload_node!(nodes[1], no_announce_cfg, &nodes_1_serialized, &[&monitor_a_serialized, &monitor_b_serialized], persister, new_chain_monitor, nodes_1_deserialized);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish);
@@ -109,8 +109,8 @@ fn test_priv_forwarding_rejection() {
        get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
        get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
 
-       nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: nodes[2].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: nodes[2].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[2]).pop().unwrap();
        let cs_reestablish = get_chan_reestablish_msgs!(nodes[2], nodes[1]).pop().unwrap();
        nodes[2].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
@@ -184,14 +184,14 @@ fn do_test_1_conf_open(connect_style: ConnectStyle) {
                msg.clone()
        } else { panic!("Unexpected event"); };
        let (bs_announcement, bs_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = bs_announce_events[1] {
-               (msg.clone(), update_msg.clone())
+               (msg.clone(), update_msg.clone().unwrap())
        } else { panic!("Unexpected event"); };
 
        nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs);
        let as_announce_events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(as_announce_events.len(), 1);
        let (announcement, as_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = as_announce_events[0] {
-               (msg.clone(), update_msg.clone())
+               (msg.clone(), update_msg.clone().unwrap())
        } else { panic!("Unexpected event"); };
        assert_eq!(announcement, bs_announcement);
 
@@ -233,7 +233,7 @@ fn test_routed_scid_alias() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42)
                .with_features(nodes[2].node.invoice_features())
                .with_route_hints(hop_hints);
        let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
@@ -388,7 +388,7 @@ fn test_inbound_scid_privacy() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42)
                .with_features(nodes[2].node.invoice_features())
                .with_route_hints(hop_hints.clone());
        let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
@@ -403,7 +403,7 @@ fn test_inbound_scid_privacy() {
        // what channel we're talking about.
        hop_hints[0].0[0].short_channel_id = last_hop[0].short_channel_id.unwrap();
 
-       let payment_params_2 = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params_2 = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42)
                .with_features(nodes[2].node.invoice_features())
                .with_route_hints(hop_hints);
        let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000, 42);
@@ -454,7 +454,7 @@ fn test_scid_alias_returned() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42)
                .with_features(nodes[2].node.invoice_features())
                .with_route_hints(hop_hints);
        let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000, 42);
@@ -757,7 +757,7 @@ fn test_public_0conf_channel() {
        match bs_announcement[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
                        announcement = msg.clone();
-                       bs_update = update_msg.clone();
+                       bs_update = update_msg.clone().unwrap();
                },
                _ => panic!("Unexpected event"),
        };
@@ -767,6 +767,7 @@ fn test_public_0conf_channel() {
        match as_announcement[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
                        assert!(announcement == *msg);
+                       let update_msg = update_msg.as_ref().unwrap();
                        assert_eq!(update_msg.contents.short_channel_id, scid);
                        assert_eq!(update_msg.contents.short_channel_id, announcement.contents.short_channel_id);
                        assert_eq!(update_msg.contents.short_channel_id, bs_update.contents.short_channel_id);
index 2ca3f21fe940270dc16438cd79a157c529e2f7a8..14deefd3f93828181f6cfad952d48913c8e25586 100644 (file)
@@ -44,8 +44,8 @@ fn test_funding_peer_disconnect() {
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
        let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        confirm_transaction(&nodes[0], &tx);
        let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
@@ -53,16 +53,16 @@ fn test_funding_peer_disconnect() {
 
        reconnect_nodes(&nodes[0], &nodes[1], (false, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        confirm_transaction(&nodes[1], &tx);
        let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
        assert!(events_2.is_empty());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
 
        // nodes[0] hasn't yet received a channel_ready, so it only sends that on reconnect.
@@ -140,7 +140,7 @@ fn test_funding_peer_disconnect() {
        assert_eq!(events_7.len(), 1);
        let (chan_announcement, as_update) = match events_7[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
-                       (msg.clone(), update_msg.clone())
+                       (msg.clone(), update_msg.clone().unwrap())
                },
                _ => panic!("Unexpected event {:?}", events_7[0]),
        };
@@ -153,7 +153,7 @@ fn test_funding_peer_disconnect() {
        let bs_update = match events_8[0] {
                MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
                        assert_eq!(*msg, chan_announcement);
-                       update_msg.clone()
+                       update_msg.clone().unwrap()
                },
                _ => panic!("Unexpected event {:?}", events_8[0]),
        };
@@ -169,7 +169,7 @@ fn test_funding_peer_disconnect() {
 
        // Check that after deserialization and reconnection we can still generate an identical
        // channel_announcement from the cached signatures.
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
 
@@ -190,15 +190,15 @@ fn test_no_txn_manager_serialize_deserialize() {
 
        let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        let chan_0_monitor_serialized =
                get_monitor!(nodes[0], OutPoint { txid: tx.txid(), index: 0 }.to_channel_id()).encode();
        reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]);
@@ -267,7 +267,7 @@ fn test_manager_serialize_deserialize_events() {
        let chan_0_monitor_serialized = get_monitor!(nodes[0], bs_funding_signed.channel_id).encode();
        reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        // After deserializing, make sure the funding_transaction is still held by the channel manager
        let events_4 = nodes[0].node.get_and_clear_pending_events();
@@ -278,9 +278,9 @@ fn test_manager_serialize_deserialize_events() {
        // Make sure the channel is functioning as though the de/serialization never happened
        assert_eq!(nodes[0].node.list_channels().len(), 1);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]);
@@ -313,7 +313,7 @@ fn test_simple_manager_serialize_deserialize() {
        let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
        let (_, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
 
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
        reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized);
@@ -353,9 +353,9 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
        let nodes_0_serialized = nodes[0].node.encode();
 
        route_payment(&nodes[0], &[&nodes[3]], 1000000);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[3].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       nodes[3].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        // Now the ChannelMonitor (which is now out-of-sync with ChannelManager for channel w/
        // nodes[3])
@@ -443,9 +443,9 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
        //... and we can even still claim the payment!
        claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage);
 
-       nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
        let reestablish = get_chan_reestablish_msgs!(nodes[3], nodes[0]).pop().unwrap();
-       nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: nodes[3].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: nodes[3].node.init_features(), remote_network_address: None }, false).unwrap();
        nodes[0].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish);
        let mut found_err = false;
        for msg_event in nodes[0].node.get_and_clear_pending_msg_events() {
@@ -488,14 +488,14 @@ fn do_test_data_loss_protect(reconnect_panicing: bool) {
        send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
        send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
        reload_node!(nodes[0], previous_node_state, &[&previous_chain_monitor_state], persister, new_chain_monitor, nodes_0_deserialized);
 
        if reconnect_panicing {
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
 
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
 
@@ -543,8 +543,8 @@ fn do_test_data_loss_protect(reconnect_panicing: bool) {
        // after the warning message sent by B, we should not able to
        // use the channel, or reconnect with success to the channel.
        assert!(nodes[0].node.list_usable_channels().is_empty());
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let retry_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
 
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &retry_reestablish[0]);
@@ -627,8 +627,8 @@ fn test_forwardable_regen() {
        assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
 
        // Now restart nodes[1] and make sure it regenerates a single PendingHTLCsForwardable
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
 
        let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id_1).encode();
        let chan_1_monitor_serialized = get_monitor!(nodes[1], chan_id_2).encode();
@@ -701,8 +701,8 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
        // Send the payment through to nodes[3] *without* clearing the PaymentClaimable event
        let mut send_events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(send_events.len(), 2);
-       let (node_1_msgs, mut send_events) = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &send_events);
-       let (node_2_msgs, _send_events) = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &send_events);
+       let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut send_events);
+       let node_2_msgs = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut send_events);
        do_pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_1_msgs, true, false, None);
        do_pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_2_msgs, true, false, None);
 
@@ -753,8 +753,8 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
        assert!(get_monitor!(nodes[3], chan_id_persisted).get_stored_preimages().contains_key(&payment_hash));
        assert!(get_monitor!(nodes[3], chan_id_not_persisted).get_stored_preimages().contains_key(&payment_hash));
 
-       nodes[1].node.peer_disconnected(&nodes[3].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[3].node.get_our_node_id());
+       nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id());
 
        // During deserialization, we should have closed one channel and broadcast its latest
        // commitment transaction. We should also still have the original PaymentClaimable event we
@@ -779,9 +779,9 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
        if !persist_both_monitors {
                // If one of the two channels is still live, reveal the payment preimage over it.
 
-               nodes[3].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: nodes[2].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[3].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: nodes[2].node.init_features(), remote_network_address: None }, true).unwrap();
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[3], nodes[2]);
-               nodes[2].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: nodes[3].node.init_features(), remote_network_address: None }).unwrap();
+               nodes[2].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: nodes[3].node.init_features(), remote_network_address: None }, false).unwrap();
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[2], nodes[3]);
 
                nodes[2].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish_1[0]);
@@ -923,7 +923,7 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht
        let bs_commitment_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
        assert_eq!(bs_commitment_tx.len(), 1);
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), true);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        if use_cs_commitment {
@@ -1038,7 +1038,7 @@ fn removed_payment_no_manager_persistence() {
        // Now that the ChannelManager has force-closed the channel which had the HTLC removed, it is
        // now forgotten everywhere. The ChannelManager should have, as a side-effect of reload,
        // learned that the HTLC is gone from the ChannelMonitor and added it to the to-fail-back set.
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), true);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
        expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]);
index 55c1341c3d0b9824e9e9abb2aa3667550ee9eecd..69e0c9afa9e49c056c7d081ef8e42913d7492d55 100644 (file)
@@ -13,8 +13,8 @@ use crate::chain::channelmonitor::ANTI_REORG_DELAY;
 use crate::chain::transaction::OutPoint;
 use crate::chain::Confirm;
 use crate::ln::channelmanager::ChannelManager;
-use crate::ln::msgs::ChannelMessageHandler;
-use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
+use crate::ln::msgs::{ChannelMessageHandler, Init};
+use crate::util::events::{Event, MessageSendEventsProvider, ClosureReason, HTLCDestination};
 use crate::util::test_utils;
 use crate::util::ser::Writeable;
 
@@ -374,6 +374,12 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
        nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
 
        // Now check that we can create a new channel
+       if reload_node && nodes[0].node.per_peer_state.read().unwrap().len() == 0 {
+               // If we dropped the channel before reloading the node, nodes[1] was also dropped from
+               // nodes[0] storage, and hence not connected again on startup. We therefore need to
+               // reconnect to the node before attempting to create a new channel.
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       }
        create_announced_chan_between_nodes(&nodes, 0, 1);
        send_payment(&nodes[0], &[&nodes[1]], 8000000);
 }
index 2e703600f554082ff9aa20d11bdc619de98fd5ae..75eacb74bc2fe7352a99288e28fcef82eac4c81d 100644 (file)
@@ -76,7 +76,7 @@ fn updates_shutdown_wait() {
        let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
        let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
        let logger = test_utils::TestLogger::new();
-       let scorer = test_utils::TestScorer::with_penalty(0);
+       let scorer = test_utils::TestScorer::new();
        let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -93,9 +93,9 @@ fn updates_shutdown_wait() {
 
        let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
 
-       let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(nodes[1].node.invoice_features());
+       let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_features(nodes[1].node.invoice_features());
        let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payment_params_1, &nodes[0].network_graph.read_only(), None, 100000, TEST_FINAL_CLTV, &logger, &scorer, &random_seed_bytes).unwrap();
-       let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(nodes[0].node.invoice_features());
+       let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV).with_features(nodes[0].node.invoice_features());
        let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payment_params_2, &nodes[1].network_graph.read_only(), None, 100000, TEST_FINAL_CLTV, &logger, &scorer, &random_seed_bytes).unwrap();
        unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)), true, APIError::ChannelUnavailable {..}, {});
        unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)), true, APIError::ChannelUnavailable {..}, {});
@@ -243,12 +243,12 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
                }
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
        let node_0_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
        let node_1_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &node_0_reestablish);
@@ -305,12 +305,12 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
                assert!(node_0_2nd_closing_signed.is_some());
        }
 
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
        let node_1_2nd_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, false).unwrap();
        if recv_count == 0 {
                // If all closing_signeds weren't delivered we can just resume where we left off...
                let node_0_2nd_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
index 1309baf60eac7ed85a5493ec8ca102653cad6eb6..aee7f562defc5915517d696cf032353deee4e3d6 100644 (file)
@@ -85,8 +85,8 @@ fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
                let mut features = InitFeatures::empty();
                features.set_onion_messages_optional();
                let init_msg = msgs::Init { features, remote_network_address: None };
-               nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone()).unwrap();
-               nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone()).unwrap();
+               nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone(), true).unwrap();
+               nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone(), false).unwrap();
        }
        nodes
 }
index 497628607ce0ff5ec4154f9546a8dc28179747e3..7814ccb6508c77a10abfa32ee189914493a62278 100644 (file)
@@ -43,15 +43,14 @@ use crate::prelude::*;
 /// # extern crate bitcoin;
 /// # use bitcoin::hashes::_export::_core::time::Duration;
 /// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
-/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager};
-/// # use lightning::ln::msgs::DecodeError;
+/// # use lightning::chain::keysinterface::KeysManager;
 /// # use lightning::ln::peer_handler::IgnoringMessageHandler;
 /// # use lightning::onion_message::{BlindedPath, CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
 /// # use lightning::util::logger::{Logger, Record};
 /// # use lightning::util::ser::{Writeable, Writer};
 /// # use lightning::io;
 /// # use std::sync::Arc;
-/// # struct FakeLogger {};
+/// # struct FakeLogger;
 /// # impl Logger for FakeLogger {
 /// #     fn log(&self, record: &Record) { unimplemented!() }
 /// # }
@@ -67,7 +66,7 @@ use crate::prelude::*;
 /// # let your_custom_message_handler = IgnoringMessageHandler {};
 /// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
 /// // ChannelManager.
-/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, your_custom_message_handler);
+/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, &your_custom_message_handler);
 ///
 /// # struct YourCustomMessage {}
 /// impl Writeable for YourCustomMessage {
@@ -418,7 +417,7 @@ impl<ES: Deref, NS: Deref, L: Deref, CMH: Deref> OnionMessageHandler for OnionMe
                };
        }
 
-       fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) -> Result<(), ()> {
+       fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init, _inbound: bool) -> Result<(), ()> {
                if init.features.supports_onion_messages() {
                        let mut peers = self.pending_messages.lock().unwrap();
                        peers.insert(their_node_id.clone(), VecDeque::new());
@@ -426,7 +425,7 @@ impl<ES: Deref, NS: Deref, L: Deref, CMH: Deref> OnionMessageHandler for OnionMe
                Ok(())
        }
 
-       fn peer_disconnected(&self, their_node_id: &PublicKey, _no_connection_possible: bool) {
+       fn peer_disconnected(&self, their_node_id: &PublicKey) {
                let mut pending_msgs = self.pending_messages.lock().unwrap();
                pending_msgs.remove(their_node_id);
        }
index d3e476fd5fc0391c3fd6ff06e5bbf7933d4a4da7..957aecb09486568efe1486342ce0695994e4aa41 100644 (file)
@@ -7,7 +7,7 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-//! The top-level network map tracking logic lives here.
+//! The [`NetworkGraph`] stores the network gossip and [`P2PGossipSync`] fetches it from peers
 
 use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
 use bitcoin::secp256k1::PublicKey;
@@ -16,17 +16,14 @@ use bitcoin::secp256k1;
 
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash;
-use bitcoin::blockdata::transaction::TxOut;
 use bitcoin::hash_types::BlockHash;
 
-use crate::chain;
-use crate::chain::Access;
-use crate::ln::chan_utils::make_funding_redeemscript;
 use crate::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
 use crate::ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
 use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter};
 use crate::ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
 use crate::ln::msgs;
+use crate::routing::utxo::{self, UtxoLookup};
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable};
 use crate::util::logger::{Logger, Level};
 use crate::util::events::{MessageSendEvent, MessageSendEventsProvider};
@@ -43,7 +40,6 @@ use crate::sync::{RwLock, RwLockReadGuard};
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::Mutex;
 use core::ops::{Bound, Deref};
-use bitcoin::hashes::hex::ToHex;
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -159,6 +155,8 @@ pub struct NetworkGraph<L: Deref> where L::Target: Logger {
        /// resync them from gossip. Each `NodeId` is mapped to the time (in seconds) it was removed so
        /// that once some time passes, we can potentially resync it from gossip again.
        removed_nodes: Mutex<HashMap<NodeId, Option<u64>>>,
+       /// Announcement messages which are awaiting an on-chain lookup to be processed.
+       pub(super) pending_checks: utxo::PendingChecks,
 }
 
 /// A read-only view of [`NetworkGraph`].
@@ -218,31 +216,30 @@ impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
 /// This network graph is then used for routing payments.
 /// Provides interface to help with initial routing sync by
 /// serving historical announcements.
-pub struct P2PGossipSync<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref>
-where C::Target: chain::Access, L::Target: Logger
+pub struct P2PGossipSync<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref>
+where U::Target: UtxoLookup, L::Target: Logger
 {
        network_graph: G,
-       chain_access: Option<C>,
+       utxo_lookup: Option<U>,
        #[cfg(feature = "std")]
        full_syncs_requested: AtomicUsize,
        pending_events: Mutex<Vec<MessageSendEvent>>,
        logger: L,
 }
 
-impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> P2PGossipSync<G, C, L>
-where C::Target: chain::Access, L::Target: Logger
+impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> P2PGossipSync<G, U, L>
+where U::Target: UtxoLookup, L::Target: Logger
 {
        /// Creates a new tracker of the actual state of the network of channels and nodes,
        /// assuming an existing Network Graph.
-       /// Chain monitor is used to make sure announced channels exist on-chain,
-       /// channel data is correct, and that the announcement is signed with
-       /// channel owners' keys.
-       pub fn new(network_graph: G, chain_access: Option<C>, logger: L) -> Self {
+       /// UTXO lookup is used to make sure announced channels exist on-chain, channel data is
+       /// correct, and the announcement is signed with channel owners' keys.
+       pub fn new(network_graph: G, utxo_lookup: Option<U>, logger: L) -> Self {
                P2PGossipSync {
                        network_graph,
                        #[cfg(feature = "std")]
                        full_syncs_requested: AtomicUsize::new(0),
-                       chain_access,
+                       utxo_lookup,
                        pending_events: Mutex::new(vec![]),
                        logger,
                }
@@ -251,8 +248,8 @@ where C::Target: chain::Access, L::Target: Logger
        /// Adds a provider used to check new announcements. Does not affect
        /// existing announcements unless they are updated.
        /// Add, update or remove the provider would replace the current one.
-       pub fn add_chain_access(&mut self, chain_access: Option<C>) {
-               self.chain_access = chain_access;
+       pub fn add_utxo_lookup(&mut self, utxo_lookup: Option<U>) {
+               self.utxo_lookup = utxo_lookup;
        }
 
        /// Gets a reference to the underlying [`NetworkGraph`] which was provided in
@@ -275,6 +272,36 @@ where C::Target: chain::Access, L::Target: Logger
                        false
                }
        }
+
+       /// Used to broadcast forward gossip messages which were validated async.
+       ///
+       /// Note that this will ignore events other than `Broadcast*` or messages with too much excess
+       /// data.
+       pub(super) fn forward_gossip_msg(&self, mut ev: MessageSendEvent) {
+               match &mut ev {
+                       MessageSendEvent::BroadcastChannelAnnouncement { msg, ref mut update_msg } => {
+                               if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
+                               if update_msg.as_ref()
+                                       .map(|msg| msg.contents.excess_data.len()).unwrap_or(0) > MAX_EXCESS_BYTES_FOR_RELAY
+                               {
+                                       *update_msg = None;
+                               }
+                       },
+                       MessageSendEvent::BroadcastChannelUpdate { msg } => {
+                               if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
+                       },
+                       MessageSendEvent::BroadcastNodeAnnouncement { msg } => {
+                               if msg.contents.excess_data.len() >  MAX_EXCESS_BYTES_FOR_RELAY ||
+                                  msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY ||
+                                  msg.contents.excess_data.len() + msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY
+                               {
+                                       return;
+                               }
+                       },
+                       _ => return,
+               }
+               self.pending_events.lock().unwrap().push(ev);
+       }
 }
 
 impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
@@ -326,8 +353,24 @@ macro_rules! secp_verify_sig {
        };
 }
 
-impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync<G, C, L>
-where C::Target: chain::Access, L::Target: Logger
+macro_rules! get_pubkey_from_node_id {
+       ( $node_id: expr, $msg_type: expr ) => {
+               PublicKey::from_slice($node_id.as_slice())
+                       .map_err(|_| LightningError {
+                               err: format!("Invalid public key on {} message", $msg_type),
+                               action: ErrorAction::SendWarningMessage {
+                                       msg: msgs::WarningMessage {
+                                               channel_id: [0; 32],
+                                               data: format!("Invalid public key on {} message", $msg_type),
+                                       },
+                                       log_level: Level::Trace
+                               }
+                       })?
+       }
+}
+
+impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync<G, U, L>
+where U::Target: UtxoLookup, L::Target: Logger
 {
        fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> {
                self.network_graph.update_node_from_announcement(msg)?;
@@ -337,8 +380,7 @@ where C::Target: chain::Access, L::Target: Logger
        }
 
        fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> {
-               self.network_graph.update_channel_from_announcement(msg, &self.chain_access)?;
-               log_gossip!(self.logger, "Added channel_announcement for {}{}", msg.contents.short_channel_id, if !msg.contents.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" });
+               self.network_graph.update_channel_from_announcement(msg, &self.utxo_lookup)?;
                Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
        }
 
@@ -348,7 +390,7 @@ where C::Target: chain::Access, L::Target: Logger
        }
 
        fn get_next_channel_announcement(&self, starting_point: u64) -> Option<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> {
-               let channels = self.network_graph.channels.read().unwrap();
+               let mut channels = self.network_graph.channels.write().unwrap();
                for (_, ref chan) in channels.range(starting_point..) {
                        if chan.announcement_message.is_some() {
                                let chan_announcement = chan.announcement_message.clone().unwrap();
@@ -369,10 +411,10 @@ where C::Target: chain::Access, L::Target: Logger
                None
        }
 
-       fn get_next_node_announcement(&self, starting_point: Option<&PublicKey>) -> Option<NodeAnnouncement> {
-               let nodes = self.network_graph.nodes.read().unwrap();
-               let iter = if let Some(pubkey) = starting_point {
-                               nodes.range((Bound::Excluded(NodeId::from_pubkey(pubkey)), Bound::Unbounded))
+       fn get_next_node_announcement(&self, starting_point: Option<&NodeId>) -> Option<NodeAnnouncement> {
+               let mut nodes = self.network_graph.nodes.write().unwrap();
+               let iter = if let Some(node_id) = starting_point {
+                               nodes.range((Bound::Excluded(node_id), Bound::Unbounded))
                        } else {
                                nodes.range(..)
                        };
@@ -395,7 +437,7 @@ where C::Target: chain::Access, L::Target: Logger
        /// to request gossip messages for each channel. The sync is considered complete
        /// when the final reply_scids_end message is received, though we are not
        /// tracking this directly.
-       fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init) -> Result<(), ()> {
+       fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init, _inbound: bool) -> Result<(), ()> {
                // We will only perform a sync with peers that support gossip_queries.
                if !init_msg.features.supports_gossip_queries() {
                        // Don't disconnect peers for not supporting gossip queries. We may wish to have
@@ -530,7 +572,7 @@ where C::Target: chain::Access, L::Target: Logger
                // (has at least one update). A peer may still want to know the channel
                // exists even if its not yet routable.
                let mut batches: Vec<Vec<u64>> = vec![Vec::with_capacity(MAX_SCIDS_PER_REPLY)];
-               let channels = self.network_graph.channels.read().unwrap();
+               let mut channels = self.network_graph.channels.write().unwrap();
                for (_, ref chan) in channels.range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) {
                        if let Some(chan_announcement) = &chan.announcement_message {
                                // Construct a new batch if last one is full
@@ -614,11 +656,15 @@ where C::Target: chain::Access, L::Target: Logger
                features.set_gossip_queries_optional();
                features
        }
+
+       fn processing_queue_high(&self) -> bool {
+               self.network_graph.pending_checks.too_many_checks_pending()
+       }
 }
 
-impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, C, L>
+impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, U, L>
 where
-       C::Target: chain::Access,
+       U::Target: UtxoLookup,
        L::Target: Logger,
 {
        fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent> {
@@ -922,7 +968,7 @@ impl<'a> fmt::Debug for DirectedChannelInfo<'a> {
 ///
 /// While this may be smaller than the actual channel capacity, amounts greater than
 /// [`Self::as_msat`] should not be routed through the channel.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 pub enum EffectiveCapacity {
        /// The available liquidity in the channel known from being a channel counterparty, and thus a
        /// direct hop.
@@ -1189,6 +1235,7 @@ impl<L: Deref> ReadableArgs<L> for NetworkGraph<L> where L::Target: Logger {
                        last_rapid_gossip_sync_timestamp: Mutex::new(last_rapid_gossip_sync_timestamp),
                        removed_nodes: Mutex::new(HashMap::new()),
                        removed_channels: Mutex::new(HashMap::new()),
+                       pending_checks: utxo::PendingChecks::new(),
                })
        }
 }
@@ -1228,6 +1275,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        last_rapid_gossip_sync_timestamp: Mutex::new(None),
                        removed_channels: Mutex::new(HashMap::new()),
                        removed_nodes: Mutex::new(HashMap::new()),
+                       pending_checks: utxo::PendingChecks::new(),
                }
        }
 
@@ -1270,7 +1318,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        /// routing messages from a source using a protocol other than the lightning P2P protocol.
        pub fn update_node_from_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), LightningError> {
                let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
-               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id, "node_announcement");
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &get_pubkey_from_node_id!(msg.contents.node_id, "node_announcement"), "node_announcement");
                self.update_node_from_announcement_intern(&msg.contents, Some(&msg))
        }
 
@@ -1283,8 +1331,13 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        }
 
        fn update_node_from_announcement_intern(&self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>) -> Result<(), LightningError> {
-               match self.nodes.write().unwrap().get_mut(&NodeId::from_pubkey(&msg.node_id)) {
-                       None => Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}),
+               let mut nodes = self.nodes.write().unwrap();
+               match nodes.get_mut(&msg.node_id) {
+                       None => {
+                               core::mem::drop(nodes);
+                               self.pending_checks.check_hold_pending_node_announcement(msg, full_msg)?;
+                               Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError})
+                       },
                        Some(node) => {
                                if let Some(node_info) = node.announcement_info.as_ref() {
                                        // The timestamp field is somewhat of a misnomer - the BOLTs use it to order
@@ -1321,35 +1374,35 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
        /// routing messages from a source using a protocol other than the lightning P2P protocol.
        ///
-       /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify
+       /// If a [`UtxoLookup`] object is provided via `utxo_lookup`, it will be called to verify
        /// the corresponding UTXO exists on chain and is correctly-formatted.
-       pub fn update_channel_from_announcement<C: Deref>(
-               &self, msg: &msgs::ChannelAnnouncement, chain_access: &Option<C>,
+       pub fn update_channel_from_announcement<U: Deref>(
+               &self, msg: &msgs::ChannelAnnouncement, utxo_lookup: &Option<U>,
        ) -> Result<(), LightningError>
        where
-               C::Target: chain::Access,
+               U::Target: UtxoLookup,
        {
                let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
-               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1, "channel_announcement");
-               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2, "channel_announcement");
-               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1, "channel_announcement");
-               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2, "channel_announcement");
-               self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), chain_access)
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &get_pubkey_from_node_id!(msg.contents.node_id_1, "channel_announcement"), "channel_announcement");
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &get_pubkey_from_node_id!(msg.contents.node_id_2, "channel_announcement"), "channel_announcement");
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_1, "channel_announcement"), "channel_announcement");
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_2, "channel_announcement"), "channel_announcement");
+               self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), utxo_lookup)
        }
 
        /// Store or update channel info from a channel announcement without verifying the associated
        /// signatures. Because we aren't given the associated signatures here we cannot relay the
        /// channel announcement to any of our peers.
        ///
-       /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify
+       /// If a [`UtxoLookup`] object is provided via `utxo_lookup`, it will be called to verify
        /// the corresponding UTXO exists on chain and is correctly-formatted.
-       pub fn update_channel_from_unsigned_announcement<C: Deref>(
-               &self, msg: &msgs::UnsignedChannelAnnouncement, chain_access: &Option<C>
+       pub fn update_channel_from_unsigned_announcement<U: Deref>(
+               &self, msg: &msgs::UnsignedChannelAnnouncement, utxo_lookup: &Option<U>
        ) -> Result<(), LightningError>
        where
-               C::Target: chain::Access,
+               U::Target: UtxoLookup,
        {
-               self.update_channel_from_unsigned_announcement_intern(msg, None, chain_access)
+               self.update_channel_from_unsigned_announcement_intern(msg, None, utxo_lookup)
        }
 
        /// Update channel from partial announcement data received via rapid gossip sync
@@ -1428,19 +1481,16 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                Ok(())
        }
 
-       fn update_channel_from_unsigned_announcement_intern<C: Deref>(
-               &self, msg: &msgs::UnsignedChannelAnnouncement, full_msg: Option<&msgs::ChannelAnnouncement>, chain_access: &Option<C>
+       fn update_channel_from_unsigned_announcement_intern<U: Deref>(
+               &self, msg: &msgs::UnsignedChannelAnnouncement, full_msg: Option<&msgs::ChannelAnnouncement>, utxo_lookup: &Option<U>
        ) -> Result<(), LightningError>
        where
-               C::Target: chain::Access,
+               U::Target: UtxoLookup,
        {
                if msg.node_id_1 == msg.node_id_2 || msg.bitcoin_key_1 == msg.bitcoin_key_2 {
                        return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
                }
 
-               let node_one = NodeId::from_pubkey(&msg.node_id_1);
-               let node_two = NodeId::from_pubkey(&msg.node_id_2);
-
                {
                        let channels = self.channels.read().unwrap();
 
@@ -1457,13 +1507,13 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                        // We use the Node IDs rather than the bitcoin_keys to check for "equivalence"
                                        // as we didn't (necessarily) store the bitcoin keys, and we only really care
                                        // if the peers on the channel changed anyway.
-                                       if node_one == chan.node_one && node_two == chan.node_two {
+                                       if msg.node_id_1 == chan.node_one && msg.node_id_2 == chan.node_two {
                                                return Err(LightningError {
                                                        err: "Already have chain-validated channel".to_owned(),
                                                        action: ErrorAction::IgnoreDuplicateGossip
                                                });
                                        }
-                               } else if chain_access.is_none() {
+                               } else if utxo_lookup.is_none() {
                                        // Similarly, if we can't check the chain right now anyway, ignore the
                                        // duplicate announcement without bothering to take the channels write lock.
                                        return Err(LightningError {
@@ -1478,40 +1528,16 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        let removed_channels = self.removed_channels.lock().unwrap();
                        let removed_nodes = self.removed_nodes.lock().unwrap();
                        if removed_channels.contains_key(&msg.short_channel_id) ||
-                               removed_nodes.contains_key(&node_one) ||
-                               removed_nodes.contains_key(&node_two) {
+                               removed_nodes.contains_key(&msg.node_id_1) ||
+                               removed_nodes.contains_key(&msg.node_id_2) {
                                return Err(LightningError{
                                        err: format!("Channel with SCID {} or one of its nodes was removed from our network graph recently", &msg.short_channel_id),
                                        action: ErrorAction::IgnoreAndLog(Level::Gossip)});
                        }
                }
 
-               let utxo_value = match &chain_access {
-                       &None => {
-                               // Tentatively accept, potentially exposing us to DoS attacks
-                               None
-                       },
-                       &Some(ref chain_access) => {
-                               match chain_access.get_utxo(&msg.chain_hash, msg.short_channel_id) {
-                                       Ok(TxOut { value, script_pubkey }) => {
-                                               let expected_script =
-                                                       make_funding_redeemscript(&msg.bitcoin_key_1, &msg.bitcoin_key_2).to_v0_p2wsh();
-                                               if script_pubkey != expected_script {
-                                                       return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", expected_script.to_hex(), script_pubkey.to_hex()), action: ErrorAction::IgnoreError});
-                                               }
-                                               //TODO: Check if value is worth storing, use it to inform routing, and compare it
-                                               //to the new HTLC max field in channel_update
-                                               Some(value)
-                                       },
-                                       Err(chain::AccessError::UnknownChain) => {
-                                               return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
-                                       },
-                                       Err(chain::AccessError::UnknownTx) => {
-                                               return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
-                                       },
-                               }
-                       },
-               };
+               let utxo_value = self.pending_checks.check_channel_announcement(
+                       utxo_lookup, msg, full_msg)?;
 
                #[allow(unused_mut, unused_assignments)]
                let mut announcement_received_time = 0;
@@ -1522,9 +1548,9 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
 
                let chan_info = ChannelInfo {
                        features: msg.features.clone(),
-                       node_one,
+                       node_one: msg.node_id_1,
                        one_to_two: None,
-                       node_two,
+                       node_two: msg.node_id_2,
                        two_to_one: None,
                        capacity_sats: utxo_value,
                        announcement_message: if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY
@@ -1532,7 +1558,10 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        announcement_received_time,
                };
 
-               self.add_channel_between_nodes(msg.short_channel_id, chan_info, utxo_value)
+               self.add_channel_between_nodes(msg.short_channel_id, chan_info, utxo_value)?;
+
+               log_gossip!(self.logger, "Added channel_announcement for {}{}", msg.short_channel_id, if !msg.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" });
+               Ok(())
        }
 
        /// Marks a channel in the graph as failed if a corresponding HTLC fail was sent.
@@ -1736,7 +1765,11 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
 
                let mut channels = self.channels.write().unwrap();
                match channels.get_mut(&msg.short_channel_id) {
-                       None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),
+                       None => {
+                               core::mem::drop(channels);
+                               self.pending_checks.check_hold_pending_channel_update(msg, full_msg)?;
+                               return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError});
+                       },
                        Some(channel) => {
                                if msg.htlc_maximum_msat > MAX_VALUE_MSAT {
                                        return Err(LightningError{err:
@@ -1890,13 +1923,13 @@ impl ReadOnlyNetworkGraph<'_> {
 }
 
 #[cfg(test)]
-mod tests {
-       use crate::chain;
+pub(crate) mod tests {
        use crate::ln::channelmanager;
        use crate::ln::chan_utils::make_funding_redeemscript;
        #[cfg(feature = "std")]
        use crate::ln::features::InitFeatures;
        use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY, NodeId, RoutingFees, ChannelUpdateInfo, ChannelInfo, NodeAnnouncementInfo, NodeInfo};
+       use crate::routing::utxo::{UtxoLookupError, UtxoResult};
        use crate::ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
                UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
                ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
@@ -1957,12 +1990,12 @@ mod tests {
                assert!(!gossip_sync.should_request_full_sync(&node_id));
        }
 
-       fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> NodeAnnouncement {
-               let node_id = PublicKey::from_secret_key(&secp_ctx, node_key);
+       pub(crate) fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> NodeAnnouncement {
+               let node_id = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_key));
                let mut unsigned_announcement = UnsignedNodeAnnouncement {
                        features: channelmanager::provided_node_features(&UserConfig::default()),
                        timestamp: 100,
-                       node_id: node_id,
+                       node_id,
                        rgb: [0; 3],
                        alias: [0; 32],
                        addresses: Vec::new(),
@@ -1977,7 +2010,7 @@ mod tests {
                }
        }
 
-       fn get_signed_channel_announcement<F: Fn(&mut UnsignedChannelAnnouncement)>(f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelAnnouncement {
+       pub(crate) fn get_signed_channel_announcement<F: Fn(&mut UnsignedChannelAnnouncement)>(f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelAnnouncement {
                let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_key);
                let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_key);
                let node_1_btckey = &SecretKey::from_slice(&[40; 32]).unwrap();
@@ -1987,10 +2020,10 @@ mod tests {
                        features: channelmanager::provided_channel_features(&UserConfig::default()),
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 0,
-                       node_id_1,
-                       node_id_2,
-                       bitcoin_key_1: PublicKey::from_secret_key(&secp_ctx, node_1_btckey),
-                       bitcoin_key_2: PublicKey::from_secret_key(&secp_ctx, node_2_btckey),
+                       node_id_1: NodeId::from_pubkey(&node_id_1),
+                       node_id_2: NodeId::from_pubkey(&node_id_2),
+                       bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_1_btckey)),
+                       bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_2_btckey)),
                        excess_data: Vec::new(),
                };
                f(&mut unsigned_announcement);
@@ -2004,14 +2037,14 @@ mod tests {
                }
        }
 
-       fn get_channel_script(secp_ctx: &Secp256k1<secp256k1::All>) -> Script {
+       pub(crate) fn get_channel_script(secp_ctx: &Secp256k1<secp256k1::All>) -> Script {
                let node_1_btckey = SecretKey::from_slice(&[40; 32]).unwrap();
                let node_2_btckey = SecretKey::from_slice(&[39; 32]).unwrap();
                make_funding_redeemscript(&PublicKey::from_secret_key(secp_ctx, &node_1_btckey),
                        &PublicKey::from_secret_key(secp_ctx, &node_2_btckey)).to_v0_p2wsh()
        }
 
-       fn get_signed_channel_update<F: Fn(&mut UnsignedChannelUpdate)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelUpdate {
+       pub(crate) fn get_signed_channel_update<F: Fn(&mut UnsignedChannelUpdate)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelUpdate {
                let mut unsigned_channel_update = UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 0,
@@ -2128,7 +2161,7 @@ mod tests {
 
                // Test if an associated transaction were not on-chain (or not confirmed).
                let chain_source = test_utils::TestChainSource::new(Network::Testnet);
-               *chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx);
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Sync(Err(UtxoLookupError::UnknownTx));
                let network_graph = NetworkGraph::new(genesis_hash, &logger);
                gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger);
 
@@ -2141,7 +2174,8 @@ mod tests {
                };
 
                // Now test if the transaction is found in the UTXO set and the script is correct.
-               *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script.clone() });
+               *chain_source.utxo_ret.lock().unwrap() =
+                       UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script.clone() }));
                let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| {
                        unsigned_announcement.short_channel_id += 2;
                }, node_1_privkey, node_2_privkey, &secp_ctx);
@@ -2159,7 +2193,8 @@ mod tests {
 
                // If we receive announcement for the same channel, once we've validated it against the
                // chain, we simply ignore all new (duplicate) announcements.
-               *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script });
+               *chain_source.utxo_ret.lock().unwrap() =
+                       UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script }));
                match gossip_sync.handle_channel_announcement(&valid_announcement) {
                        Ok(_) => panic!(),
                        Err(e) => assert_eq!(e.err, "Already have chain-validated channel")
@@ -2233,7 +2268,8 @@ mod tests {
                {
                        // Announce a channel we will update
                        let good_script = get_channel_script(&secp_ctx);
-                       *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() });
+                       *chain_source.utxo_ret.lock().unwrap() =
+                               UtxoResult::Sync(Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() }));
 
                        let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
                        short_channel_id = valid_channel_announcement.contents.short_channel_id;
@@ -2639,7 +2675,7 @@ mod tests {
                let (secp_ctx, gossip_sync) = create_gossip_sync(&network_graph);
                let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
                let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
-               let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
+               let node_id_1 = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_1_privkey));
 
                // No nodes yet.
                let next_announcements = gossip_sync.get_next_node_announcement(None);
@@ -2755,7 +2791,7 @@ mod tests {
                // It should ignore if gossip_queries feature is not enabled
                {
                        let init_msg = Init { features: InitFeatures::empty(), remote_network_address: None };
-                       gossip_sync.peer_connected(&node_id_1, &init_msg).unwrap();
+                       gossip_sync.peer_connected(&node_id_1, &init_msg, true).unwrap();
                        let events = gossip_sync.get_and_clear_pending_msg_events();
                        assert_eq!(events.len(), 0);
                }
@@ -2765,7 +2801,7 @@ mod tests {
                        let mut features = InitFeatures::empty();
                        features.set_gossip_queries_optional();
                        let init_msg = Init { features, remote_network_address: None };
-                       gossip_sync.peer_connected(&node_id_1, &init_msg).unwrap();
+                       gossip_sync.peer_connected(&node_id_1, &init_msg, true).unwrap();
                        let events = gossip_sync.get_and_clear_pending_msg_events();
                        assert_eq!(events.len(), 1);
                        match &events[0] {
index 9bf0910663d92210ce649bfec959538214cd12cd..7fff856345c84c8f8fadadfe262992a4a4e8f6bc 100644 (file)
@@ -9,6 +9,7 @@
 
 //! Structs and impls for receiving messages about the network and storing the topology live here.
 
+pub mod utxo;
 pub mod gossip;
 pub mod router;
 pub mod scoring;
index 1e2ca10c0bf4a0795bc4089d0145b69ad8914de5..b4e2b138433648d9218ce0e8977cb85f4d9197a8 100644 (file)
@@ -7,10 +7,7 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-//! The top-level routing/network map tracking logic lives here.
-//!
-//! You probably want to create a P2PGossipSync and use that as your RoutingMessageHandler and then
-//! interrogate it to get routes for your own payments.
+//! The router finds paths within a [`NetworkGraph`] for a payment.
 
 use bitcoin::secp256k1::PublicKey;
 use bitcoin::hashes::Hash;
@@ -75,22 +72,6 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> Router for DefaultR
                        &random_seed_bytes
                )
        }
-
-       fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
-               self.scorer.lock().payment_path_failed(path, short_channel_id);
-       }
-
-       fn notify_payment_path_successful(&self, path: &[&RouteHop]) {
-               self.scorer.lock().payment_path_successful(path);
-       }
-
-       fn notify_payment_probe_successful(&self, path: &[&RouteHop]) {
-               self.scorer.lock().probe_successful(path);
-       }
-
-       fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
-               self.scorer.lock().probe_failed(path, short_channel_id);
-       }
 }
 
 /// A trait defining behavior for routing a payment.
@@ -109,14 +90,6 @@ pub trait Router {
        ) -> Result<Route, LightningError> {
                self.find_route(payer, route_params, first_hops, inflight_htlcs)
        }
-       /// Lets the router know that payment through a specific path has failed.
-       fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64);
-       /// Lets the router know that payment through a specific path was successful.
-       fn notify_payment_path_successful(&self, path: &[&RouteHop]);
-       /// Lets the router know that a payment probe was successful.
-       fn notify_payment_probe_successful(&self, path: &[&RouteHop]);
-       /// Lets the router know that a payment probe failed.
-       fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64);
 }
 
 /// [`Score`] implementation that factors in in-flight HTLC liquidity.
@@ -360,7 +333,7 @@ impl Readable for Route {
 /// Parameters needed to find a [`Route`].
 ///
 /// Passed to [`find_route`] and [`build_route_from_hops`], but also provided in
-/// [`Event::PaymentPathFailed`] for retrying a failed payment path.
+/// [`Event::PaymentPathFailed`].
 ///
 /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -372,6 +345,9 @@ pub struct RouteParameters {
        pub final_value_msat: u64,
 
        /// The CLTV on the final hop of the failed payment path.
+       ///
+       /// This field is deprecated, [`PaymentParameters::final_cltv_expiry_delta`] should be used
+       /// instead, if available.
        pub final_cltv_expiry_delta: u32,
 }
 
@@ -452,6 +428,11 @@ pub struct PaymentParameters {
        /// payment to fail. Future attempts for the same payment shouldn't be relayed through any of
        /// these SCIDs.
        pub previously_failed_channels: Vec<u64>,
+
+       /// The minimum CLTV delta at the end of the route.
+       ///
+       /// This field should always be set to `Some` and may be required in a future release.
+       pub final_cltv_expiry_delta: Option<u32>,
 }
 
 impl_writeable_tlv_based!(PaymentParameters, {
@@ -463,11 +444,15 @@ impl_writeable_tlv_based!(PaymentParameters, {
        (5, max_channel_saturation_power_of_half, (default_value, 2)),
        (6, expiry_time, option),
        (7, previously_failed_channels, vec_type),
+       (9, final_cltv_expiry_delta, option),
 });
 
 impl PaymentParameters {
        /// Creates a payee with the node id of the given `pubkey`.
-       pub fn from_node_id(payee_pubkey: PublicKey) -> Self {
+       ///
+       /// The `final_cltv_expiry_delta` should match the expected final CLTV delta the recipient has
+       /// provided.
+       pub fn from_node_id(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self {
                Self {
                        payee_pubkey,
                        features: None,
@@ -477,12 +462,16 @@ impl PaymentParameters {
                        max_path_count: DEFAULT_MAX_PATH_COUNT,
                        max_channel_saturation_power_of_half: 2,
                        previously_failed_channels: Vec::new(),
+                       final_cltv_expiry_delta: Some(final_cltv_expiry_delta),
                }
        }
 
        /// Creates a payee with the node id of the given `pubkey` to use for keysend payments.
-       pub fn for_keysend(payee_pubkey: PublicKey) -> Self {
-               Self::from_node_id(payee_pubkey).with_features(InvoiceFeatures::for_keysend())
+       ///
+       /// The `final_cltv_expiry_delta` should match the expected final CLTV delta the recipient has
+       /// provided.
+       pub fn for_keysend(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self {
+               Self::from_node_id(payee_pubkey, final_cltv_expiry_delta).with_features(InvoiceFeatures::for_keysend())
        }
 
        /// Includes the payee's features.
@@ -948,8 +937,11 @@ pub fn find_route<L: Deref, GL: Deref, S: Score>(
 ) -> Result<Route, LightningError>
 where L::Target: Logger, GL::Target: Logger {
        let graph_lock = network_graph.read_only();
+       let final_cltv_expiry_delta =
+               if let Some(delta) = route_params.payment_params.final_cltv_expiry_delta { delta }
+               else { route_params.final_cltv_expiry_delta };
        let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops,
-               route_params.final_value_msat, route_params.final_cltv_expiry_delta, logger, scorer,
+               route_params.final_value_msat, final_cltv_expiry_delta, logger, scorer,
                random_seed_bytes)?;
        add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
        Ok(route)
@@ -986,6 +978,9 @@ where L::Target: Logger {
        if payment_params.max_total_cltv_expiry_delta <= final_cltv_expiry_delta {
                return Err(LightningError{err: "Can't find a route where the maximum total CLTV expiry delta is below the final CLTV expiry.".to_owned(), action: ErrorAction::IgnoreError});
        }
+       if let Some(delta) = payment_params.final_cltv_expiry_delta {
+               debug_assert_eq!(delta, final_cltv_expiry_delta);
+       }
 
        // The general routing idea is the following:
        // 1. Fill first/last hops communicated by the caller.
@@ -2093,10 +2088,11 @@ fn build_route_from_hops_internal<L: Deref>(
 #[cfg(test)]
 mod tests {
        use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
+       use crate::routing::utxo::UtxoResult;
        use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
                PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
                DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
-       use crate::routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
+       use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
        use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
        use crate::chain::transaction::OutPoint;
        use crate::chain::keysinterface::EntropySource;
@@ -2165,8 +2161,8 @@ mod tests {
        fn simple_route_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2198,8 +2194,8 @@ mod tests {
        fn invalid_first_hop_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2220,8 +2216,8 @@ mod tests {
        fn htlc_minimum_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2348,8 +2344,8 @@ mod tests {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config));
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2486,8 +2482,8 @@ mod tests {
        fn disable_channels_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2546,8 +2542,8 @@ mod tests {
        fn disable_node_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2591,12 +2587,12 @@ mod tests {
        fn our_chans_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                // Route to 1 via 2 and 3 because our channel to 1 is disabled
-               let payment_params = PaymentParameters::from_node_id(nodes[0]);
+               let payment_params = PaymentParameters::from_node_id(nodes[0], 42);
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 3);
 
@@ -2622,7 +2618,7 @@ mod tests {
                assert_eq!(route.paths[0][2].channel_features.le_flags(), &id_to_feature_flags(3));
 
                // If we specify a channel to node7, that overrides our local channel view and that gets used
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
                let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
@@ -2722,7 +2718,7 @@ mod tests {
        fn partial_route_hint_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2746,13 +2742,13 @@ mod tests {
                let mut invalid_last_hops = last_hops_multi_private_channels(&nodes);
                invalid_last_hops.push(invalid_last_hop);
                {
-                       let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(invalid_last_hops);
+                       let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(invalid_last_hops);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
                                assert_eq!(err, "Route hint cannot have the payee as the source.");
                        } else { panic!(); }
                }
 
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops_multi_private_channels(&nodes));
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_multi_private_channels(&nodes));
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 5);
 
@@ -2822,8 +2818,8 @@ mod tests {
        fn ignores_empty_last_hops_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(empty_last_hop(&nodes));
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(empty_last_hop(&nodes));
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -2902,8 +2898,8 @@ mod tests {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let last_hops = multi_hop_last_hops_hint([nodes[2], nodes[3]]);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops.clone());
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone());
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                // Test through channels 2, 3, 0xff00, 0xff01.
@@ -2976,8 +2972,8 @@ mod tests {
                let non_announced_pubkey = PublicKey::from_secret_key(&secp_ctx, &non_announced_privkey);
 
                let last_hops = multi_hop_last_hops_hint([nodes[2], non_announced_pubkey]);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops.clone());
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone());
+               let scorer = ln_test_utils::TestScorer::new();
                // Test through channels 2, 3, 0xff00, 0xff01.
                // Test shows that multiple hop hints are considered.
 
@@ -3082,8 +3078,8 @@ mod tests {
        fn last_hops_with_public_channel_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops_with_public_channel(&nodes));
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_with_public_channel(&nodes));
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                // This test shows that public routes can be present in the invoice
@@ -3134,14 +3130,14 @@ mod tests {
        fn our_chans_last_hop_connect_test() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                // Simple test with outbound channel to 4 to test that last_hops and first_hops connect
                let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
                let mut last_hops = last_hops(&nodes);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops.clone());
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone());
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
 
@@ -3162,7 +3158,7 @@ mod tests {
                last_hops[0].0[0].fees.base_msat = 1000;
 
                // Revert to via 6 as the fee on 8 goes up
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops);
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 4);
 
@@ -3255,9 +3251,9 @@ mod tests {
                        htlc_minimum_msat: None,
                        htlc_maximum_msat: last_hop_htlc_max,
                }]);
-               let payment_params = PaymentParameters::from_node_id(target_node_id).with_route_hints(vec![last_hops]);
+               let payment_params = PaymentParameters::from_node_id(target_node_id, 42).with_route_hints(vec![last_hops]);
                let our_chans = vec![get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)];
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
@@ -3318,11 +3314,11 @@ mod tests {
 
                let (secp_ctx, network_graph, mut gossip_sync, chain_monitor, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // We will use a simple single-path route from
                // our node to node2 via node0: channels {1, 3}.
@@ -3507,8 +3503,9 @@ mod tests {
                .push_opcode(opcodes::all::OP_PUSHNUM_2)
                .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
 
-               *chain_monitor.utxo_ret.lock().unwrap() = Ok(TxOut { value: 15, script_pubkey: good_script.clone() });
-               gossip_sync.add_chain_access(Some(chain_monitor));
+               *chain_monitor.utxo_ret.lock().unwrap() =
+                       UtxoResult::Sync(Ok(TxOut { value: 15, script_pubkey: good_script.clone() }));
+               gossip_sync.add_utxo_lookup(Some(chain_monitor));
 
                add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
                update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
@@ -3593,11 +3590,11 @@ mod tests {
                // one of the latter hops is limited.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
                // {12, 13, 11} have the capacities of 100, {6} has a capacity of 50.
@@ -3719,10 +3716,10 @@ mod tests {
        fn ignore_fee_first_hop_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
 
                // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
                update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
@@ -3767,11 +3764,11 @@ mod tests {
        fn simple_mpp_route_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2])
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
                        .with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 3 paths:
@@ -3927,11 +3924,11 @@ mod tests {
        fn long_mpp_route_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 3 paths:
                // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
@@ -4092,11 +4089,11 @@ mod tests {
        fn mpp_cheaper_route_test() {
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // This test checks that if we have two cheaper paths and one more expensive path,
                // so that liquidity-wise any 2 of 3 combination is sufficient,
@@ -4262,11 +4259,11 @@ mod tests {
                // if the fee is not properly accounted for, the behavior is different.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 2 paths:
                // From our node to node3 via {node0, node2} and {node7, node2, node4}.
@@ -4444,11 +4441,11 @@ mod tests {
                // This bug appeared in production in some specific channel configurations.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(channelmanager::provided_invoice_features(&config))
+               let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap(), 42).with_features(channelmanager::provided_invoice_features(&config))
                        .with_route_hints(vec![RouteHint(vec![RouteHintHop {
                                src_node_id: nodes[2],
                                short_channel_id: 42,
@@ -4536,11 +4533,11 @@ mod tests {
                // path finding we realize that we found more capacity than we need.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config))
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config))
                        .with_max_channel_saturation_power_of_half(0);
 
                // We need a route consisting of 3 paths:
@@ -4698,10 +4695,10 @@ mod tests {
                let network = Arc::new(NetworkGraph::new(genesis_hash, Arc::clone(&logger)));
                let gossip_sync = P2PGossipSync::new(Arc::clone(&network), None, Arc::clone(&logger));
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let payment_params = PaymentParameters::from_node_id(nodes[6]);
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42);
 
                add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
                update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
@@ -4829,10 +4826,10 @@ mod tests {
                // we calculated fees on a higher value, resulting in us ignoring such paths.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]);
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
 
                // We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to
                // send.
@@ -4893,11 +4890,11 @@ mod tests {
                // resulting in us thinking there is no possible path, even if other paths exist.
                let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config));
 
                // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2
                // gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We
@@ -4964,9 +4961,9 @@ mod tests {
                let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
                let logger = Arc::new(ln_test_utils::TestLogger::new());
                let network_graph = NetworkGraph::new(genesis_hash, Arc::clone(&logger));
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[0], 42).with_features(channelmanager::provided_invoice_features(&config));
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -5032,10 +5029,10 @@ mod tests {
        fn prefers_shorter_route_with_higher_fees() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes));
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes));
 
                // Without penalizing each hop 100 msats, a longer path with lower fees is chosen.
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let route = get_route(
@@ -5050,7 +5047,7 @@ mod tests {
 
                // Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6]
                // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper.
-               let scorer = ln_test_utils::TestScorer::with_penalty(100);
+               let scorer = FixedPenaltyScorer::with_penalty(100);
                let route = get_route(
                        &our_id, &payment_params, &network_graph.read_only(), None, 100, 42,
                        Arc::clone(&logger), &scorer, &random_seed_bytes
@@ -5105,11 +5102,11 @@ mod tests {
        fn avoids_routing_through_bad_channels_and_nodes() {
                let (secp_ctx, network, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes));
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes));
                let network_graph = network.read_only();
 
                // A path to nodes[6] exists when no penalties are applied to any channel.
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let route = get_route(
@@ -5224,11 +5221,11 @@ mod tests {
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let network_graph = network.read_only();
 
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
 
                // Make sure that generally there is at least one route available
                let feasible_max_total_cltv_delta = 1008;
-               let feasible_payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
+               let feasible_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes))
                        .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
@@ -5238,7 +5235,7 @@ mod tests {
 
                // But not if we exclude all paths on the basis of their accumulated CLTV delta
                let fail_max_total_cltv_delta = 23;
-               let fail_payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
+               let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes))
                        .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
                match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, 0, Arc::clone(&logger), &scorer, &random_seed_bytes)
                {
@@ -5257,8 +5254,8 @@ mod tests {
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let network_graph = network.read_only();
 
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
-               let mut payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
+               let scorer = ln_test_utils::TestScorer::new();
+               let mut payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes))
                        .with_max_path_count(1);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
@@ -5284,19 +5281,19 @@ mod tests {
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let network_graph = network.read_only();
 
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                // First check we can actually create a long route on this graph.
-               let feasible_payment_params = PaymentParameters::from_node_id(nodes[18]);
+               let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0);
                let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, 0,
                        Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
                assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into());
 
                // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit.
-               let fail_payment_params = PaymentParameters::from_node_id(nodes[19]);
+               let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0);
                match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, 0,
                        Arc::clone(&logger), &scorer, &random_seed_bytes)
                {
@@ -5312,9 +5309,9 @@ mod tests {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
 
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
+               let scorer = ln_test_utils::TestScorer::new();
 
-               let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes));
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes));
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
@@ -5346,8 +5343,8 @@ mod tests {
                let network_graph = network.read_only();
                let network_nodes = network_graph.nodes();
                let network_channels = network_graph.channels();
-               let scorer = ln_test_utils::TestScorer::with_penalty(0);
-               let payment_params = PaymentParameters::from_node_id(nodes[3]);
+               let scorer = ln_test_utils::TestScorer::new();
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[4u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -5414,7 +5411,7 @@ mod tests {
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
-               let payment_params = PaymentParameters::from_node_id(nodes[3]);
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
                let hops = [nodes[1], nodes[2], nodes[4], nodes[3]];
                let route = build_route_from_hops_internal(&our_id, &hops, &payment_params,
                         &network_graph, 100, 0, Arc::clone(&logger), &random_seed_bytes).unwrap();
@@ -5460,7 +5457,7 @@ mod tests {
                });
 
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
+               let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config));
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                // 100,000 sats is less than the available liquidity on each channel, set above.
@@ -5507,7 +5504,7 @@ mod tests {
                                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.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
-                               let payment_params = PaymentParameters::from_node_id(dst);
+                               let payment_params = PaymentParameters::from_node_id(dst, 42);
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
                                let scorer = ProbabilisticScorer::new(params, &graph, &logger);
@@ -5545,7 +5542,7 @@ mod tests {
                                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.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 payment_params = PaymentParameters::from_node_id(dst, 42).with_features(channelmanager::provided_invoice_features(&config));
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
                                let scorer = ProbabilisticScorer::new(params, &graph, &logger);
@@ -5578,7 +5575,7 @@ mod tests {
                assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage), 456);
 
                // Then check we can get a normal route
-               let payment_params = PaymentParameters::from_node_id(nodes[10]);
+               let payment_params = PaymentParameters::from_node_id(nodes[10], 42);
                let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes);
                assert!(route.is_ok());
 
@@ -5745,7 +5742,7 @@ mod benches {
                                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.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
-                               let params = PaymentParameters::from_node_id(dst).with_features(features.clone());
+                               let params = PaymentParameters::from_node_id(dst, 42).with_features(features.clone());
                                let first_hop = first_hop(src);
                                let amt = seed as u64 % 1_000_000;
                                if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, 42, &DummyLogger{}, &scorer, &random_seed_bytes) {
index 5cc9f2965763dc98b64b0c4a6be8dec07c7685eb..7504e0840d2683125cf75144fd445b070c6f08da 100644 (file)
@@ -260,7 +260,7 @@ impl<'a, S: Writeable> Writeable for MutexGuard<'a, S> {
 }
 
 /// Proposed use of a channel passed as a parameter to [`Score::channel_penalty_msat`].
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 pub struct ChannelUsage {
        /// The amount to send through the channel, denominated in millisatoshis.
        pub amount_msat: u64,
@@ -1779,10 +1779,10 @@ mod tests {
                        features: channelmanager::provided_channel_features(&UserConfig::default()),
                        chain_hash: genesis_hash,
                        short_channel_id,
-                       node_id_1: PublicKey::from_secret_key(&secp_ctx, &node_1_key),
-                       node_id_2: PublicKey::from_secret_key(&secp_ctx, &node_2_key),
-                       bitcoin_key_1: PublicKey::from_secret_key(&secp_ctx, &node_1_secret),
-                       bitcoin_key_2: PublicKey::from_secret_key(&secp_ctx, &node_2_secret),
+                       node_id_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_key)),
+                       node_id_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_key)),
+                       bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_secret)),
+                       bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_secret)),
                        excess_data: Vec::new(),
                };
                let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
index a5d2af43c6ccbf90d04a6274d997c34689d03247..b737bab352441a1b2a9289cc143e078ba6384c97 100644 (file)
@@ -27,13 +27,15 @@ use bitcoin::secp256k1::{Secp256k1, All};
 use crate::prelude::*;
 use crate::sync::{self, Arc};
 
+use crate::routing::gossip::NodeId;
+
 // Using the same keys for LN and BTC ids
 pub(super) fn add_channel(
        gossip_sync: &P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
        secp_ctx: &Secp256k1<All>, node_1_privkey: &SecretKey, node_2_privkey: &SecretKey, features: ChannelFeatures, short_channel_id: u64
 ) {
-       let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
-       let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey);
+       let node_id_1 = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_1_privkey));
+       let node_id_2 = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_2_privkey));
 
        let unsigned_announcement = UnsignedChannelAnnouncement {
                features,
@@ -64,7 +66,7 @@ pub(super) fn add_or_update_node(
        gossip_sync: &P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
        secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey, features: NodeFeatures, timestamp: u32
 ) {
-       let node_id = PublicKey::from_secret_key(&secp_ctx, node_privkey);
+       let node_id = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_privkey));
        let unsigned_announcement = UnsignedNodeAnnouncement {
                features,
                timestamp,
diff --git a/lightning/src/routing/utxo.rs b/lightning/src/routing/utxo.rs
new file mode 100644 (file)
index 0000000..020993f
--- /dev/null
@@ -0,0 +1,861 @@
+// 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 module contains traits for LDK to access UTXOs to check gossip data is correct.
+//!
+//! When lightning nodes gossip channel information, they resist DoS attacks by checking that each
+//! channel matches a UTXO on-chain, requiring at least some marginal on-chain transacting in
+//! order to announce a channel. This module handles that checking.
+
+use bitcoin::{BlockHash, TxOut};
+use bitcoin::hashes::hex::ToHex;
+
+use crate::ln::chan_utils::make_funding_redeemscript_from_slices;
+use crate::ln::msgs::{self, LightningError, ErrorAction};
+use crate::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync};
+use crate::util::events::MessageSendEvent;
+use crate::util::logger::{Level, Logger};
+use crate::util::ser::Writeable;
+
+use crate::prelude::*;
+
+use alloc::sync::{Arc, Weak};
+use crate::sync::Mutex;
+use core::ops::Deref;
+
+/// An error when accessing the chain via [`UtxoLookup`].
+#[derive(Clone, Debug)]
+pub enum UtxoLookupError {
+       /// The requested chain is unknown.
+       UnknownChain,
+
+       /// The requested transaction doesn't exist or hasn't confirmed.
+       UnknownTx,
+}
+
+/// The result of a [`UtxoLookup::get_utxo`] call. A call may resolve either synchronously,
+/// returning the `Sync` variant, or asynchronously, returning an [`UtxoFuture`] in the `Async`
+/// variant.
+#[derive(Clone)]
+pub enum UtxoResult {
+       /// A result which was resolved synchronously. It either includes a [`TxOut`] for the output
+       /// requested or a [`UtxoLookupError`].
+       Sync(Result<TxOut, UtxoLookupError>),
+       /// A result which will be resolved asynchronously. It includes a [`UtxoFuture`], a `clone` of
+       /// which you must keep locally and call [`UtxoFuture::resolve`] on once the lookup completes.
+       ///
+       /// Note that in order to avoid runaway memory usage, the number of parallel checks is limited,
+       /// but only fairly loosely. Because a pending checks block all message processing, leaving
+       /// checks pending for an extended time may cause DoS of other functions. It is recommended you
+       /// keep a tight timeout on lookups, on the order of a few seconds.
+       Async(UtxoFuture),
+}
+
+/// The `UtxoLookup` trait defines behavior for accessing on-chain UTXOs.
+pub trait UtxoLookup {
+       /// Returns the transaction output of a funding transaction encoded by [`short_channel_id`].
+       /// Returns an error if `genesis_hash` is for a different chain or if such a transaction output
+       /// is unknown.
+       ///
+       /// [`short_channel_id`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#definition-of-short_channel_id
+       fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> UtxoResult;
+}
+
+enum ChannelAnnouncement {
+       Full(msgs::ChannelAnnouncement),
+       Unsigned(msgs::UnsignedChannelAnnouncement),
+}
+impl ChannelAnnouncement {
+       fn node_id_1(&self) -> &NodeId {
+               match self {
+                       ChannelAnnouncement::Full(msg) => &msg.contents.node_id_1,
+                       ChannelAnnouncement::Unsigned(msg) => &msg.node_id_1,
+               }
+       }
+}
+
+enum NodeAnnouncement {
+       Full(msgs::NodeAnnouncement),
+       Unsigned(msgs::UnsignedNodeAnnouncement),
+}
+impl NodeAnnouncement {
+       fn timestamp(&self) -> u32 {
+               match self {
+                       NodeAnnouncement::Full(msg) => msg.contents.timestamp,
+                       NodeAnnouncement::Unsigned(msg) => msg.timestamp,
+               }
+       }
+}
+
+enum ChannelUpdate {
+       Full(msgs::ChannelUpdate),
+       Unsigned(msgs::UnsignedChannelUpdate),
+}
+impl ChannelUpdate {
+       fn timestamp(&self) -> u32 {
+               match self {
+                       ChannelUpdate::Full(msg) => msg.contents.timestamp,
+                       ChannelUpdate::Unsigned(msg) => msg.timestamp,
+               }
+       }
+}
+
+struct UtxoMessages {
+       complete: Option<Result<TxOut, UtxoLookupError>>,
+       channel_announce: Option<ChannelAnnouncement>,
+       latest_node_announce_a: Option<NodeAnnouncement>,
+       latest_node_announce_b: Option<NodeAnnouncement>,
+       latest_channel_update_a: Option<ChannelUpdate>,
+       latest_channel_update_b: Option<ChannelUpdate>,
+}
+
+/// Represents a future resolution of a [`UtxoLookup::get_utxo`] query resolving async.
+///
+/// See [`UtxoResult::Async`] and [`UtxoFuture::resolve`] for more info.
+#[derive(Clone)]
+pub struct UtxoFuture {
+       state: Arc<Mutex<UtxoMessages>>,
+}
+
+/// A trivial implementation of [`UtxoLookup`] which is used to call back into the network graph
+/// once we have a concrete resolution of a request.
+struct UtxoResolver(Result<TxOut, UtxoLookupError>);
+impl UtxoLookup for UtxoResolver {
+       fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> UtxoResult {
+               UtxoResult::Sync(self.0.clone())
+       }
+}
+
+impl UtxoFuture {
+       /// Builds a new future for later resolution.
+       pub fn new() -> Self {
+               Self { state: Arc::new(Mutex::new(UtxoMessages {
+                       complete: None,
+                       channel_announce: None,
+                       latest_node_announce_a: None,
+                       latest_node_announce_b: None,
+                       latest_channel_update_a: None,
+                       latest_channel_update_b: None,
+               }))}
+       }
+
+       /// Resolves this future against the given `graph` and with the given `result`.
+       ///
+       /// This is identical to calling [`UtxoFuture::resolve`] with a dummy `gossip`, disabling
+       /// forwarding the validated gossip message onwards to peers.
+       ///
+       /// Because this may cause the [`NetworkGraph`]'s [`processing_queue_high`] to flip, in order
+       /// to allow us to interact with peers again, you should call [`PeerManager::process_events`]
+       /// after this.
+       ///
+       /// [`processing_queue_high`]: crate::ln::msgs::RoutingMessageHandler::processing_queue_high
+       /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events
+       pub fn resolve_without_forwarding<L: Deref>(&self,
+               graph: &NetworkGraph<L>, result: Result<TxOut, UtxoLookupError>)
+       where L::Target: Logger {
+               self.do_resolve(graph, result);
+       }
+
+       /// Resolves this future against the given `graph` and with the given `result`.
+       ///
+       /// The given `gossip` is used to broadcast any validated messages onwards to all peers which
+       /// have available buffer space.
+       ///
+       /// Because this may cause the [`NetworkGraph`]'s [`processing_queue_high`] to flip, in order
+       /// to allow us to interact with peers again, you should call [`PeerManager::process_events`]
+       /// after this.
+       ///
+       /// [`processing_queue_high`]: crate::ln::msgs::RoutingMessageHandler::processing_queue_high
+       /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events
+       pub fn resolve<L: Deref, G: Deref<Target=NetworkGraph<L>>, U: Deref, GS: Deref<Target = P2PGossipSync<G, U, L>>>(&self,
+               graph: &NetworkGraph<L>, gossip: GS, result: Result<TxOut, UtxoLookupError>
+       ) where L::Target: Logger, U::Target: UtxoLookup {
+               let mut res = self.do_resolve(graph, result);
+               for msg_opt in res.iter_mut() {
+                       if let Some(msg) = msg_opt.take() {
+                               gossip.forward_gossip_msg(msg);
+                       }
+               }
+       }
+
+       fn do_resolve<L: Deref>(&self, graph: &NetworkGraph<L>, result: Result<TxOut, UtxoLookupError>)
+       -> [Option<MessageSendEvent>; 5] where L::Target: Logger {
+               let (announcement, node_a, node_b, update_a, update_b) = {
+                       let mut pending_checks = graph.pending_checks.internal.lock().unwrap();
+                       let mut async_messages = self.state.lock().unwrap();
+
+                       if async_messages.channel_announce.is_none() {
+                               // We raced returning to `check_channel_announcement` which hasn't updated
+                               // `channel_announce` yet. That's okay, we can set the `complete` field which it will
+                               // check once it gets control again.
+                               async_messages.complete = Some(result);
+                               return [None, None, None, None, None];
+                       }
+
+                       let announcement_msg = match async_messages.channel_announce.as_ref().unwrap() {
+                               ChannelAnnouncement::Full(signed_msg) => &signed_msg.contents,
+                               ChannelAnnouncement::Unsigned(msg) => &msg,
+                       };
+
+                       pending_checks.lookup_completed(announcement_msg, &Arc::downgrade(&self.state));
+
+                       (async_messages.channel_announce.take().unwrap(),
+                               async_messages.latest_node_announce_a.take(),
+                               async_messages.latest_node_announce_b.take(),
+                               async_messages.latest_channel_update_a.take(),
+                               async_messages.latest_channel_update_b.take())
+               };
+
+               let mut res = [None, None, None, None, None];
+               let mut res_idx = 0;
+
+               // Now that we've updated our internal state, pass the pending messages back through the
+               // network graph with a different `UtxoLookup` which will resolve immediately.
+               // Note that we ignore errors as we don't disconnect peers anyway, so there's nothing to do
+               // with them.
+               let resolver = UtxoResolver(result);
+               match announcement {
+                       ChannelAnnouncement::Full(signed_msg) => {
+                               if graph.update_channel_from_announcement(&signed_msg, &Some(&resolver)).is_ok() {
+                                       res[res_idx] = Some(MessageSendEvent::BroadcastChannelAnnouncement {
+                                               msg: signed_msg, update_msg: None,
+                                       });
+                                       res_idx += 1;
+                               }
+                       },
+                       ChannelAnnouncement::Unsigned(msg) => {
+                               let _ = graph.update_channel_from_unsigned_announcement(&msg, &Some(&resolver));
+                       },
+               }
+
+               for announce in core::iter::once(node_a).chain(core::iter::once(node_b)) {
+                       match announce {
+                               Some(NodeAnnouncement::Full(signed_msg)) => {
+                                       if graph.update_node_from_announcement(&signed_msg).is_ok() {
+                                               res[res_idx] = Some(MessageSendEvent::BroadcastNodeAnnouncement {
+                                                       msg: signed_msg,
+                                               });
+                                               res_idx += 1;
+                                       }
+                               },
+                               Some(NodeAnnouncement::Unsigned(msg)) => {
+                                       let _ = graph.update_node_from_unsigned_announcement(&msg);
+                               },
+                               None => {},
+                       }
+               }
+
+               for update in core::iter::once(update_a).chain(core::iter::once(update_b)) {
+                       match update {
+                               Some(ChannelUpdate::Full(signed_msg)) => {
+                                       if graph.update_channel(&signed_msg).is_ok() {
+                                               res[res_idx] = Some(MessageSendEvent::BroadcastChannelUpdate {
+                                                       msg: signed_msg,
+                                               });
+                                               res_idx += 1;
+                                       }
+                               },
+                               Some(ChannelUpdate::Unsigned(msg)) => {
+                                       let _ = graph.update_channel_unsigned(&msg);
+                               },
+                               None => {},
+                       }
+               }
+
+               res
+       }
+}
+
+struct PendingChecksContext {
+       channels: HashMap<u64, Weak<Mutex<UtxoMessages>>>,
+       nodes: HashMap<NodeId, Vec<Weak<Mutex<UtxoMessages>>>>,
+}
+
+impl PendingChecksContext {
+       fn lookup_completed(&mut self,
+               msg: &msgs::UnsignedChannelAnnouncement, completed_state: &Weak<Mutex<UtxoMessages>>
+       ) {
+               if let hash_map::Entry::Occupied(e) = self.channels.entry(msg.short_channel_id) {
+                       if Weak::ptr_eq(e.get(), &completed_state) {
+                               e.remove();
+                       }
+               }
+
+               if let hash_map::Entry::Occupied(mut e) = self.nodes.entry(msg.node_id_1) {
+                       e.get_mut().retain(|elem| !Weak::ptr_eq(&elem, &completed_state));
+                       if e.get().is_empty() { e.remove(); }
+               }
+               if let hash_map::Entry::Occupied(mut e) = self.nodes.entry(msg.node_id_2) {
+                       e.get_mut().retain(|elem| !Weak::ptr_eq(&elem, &completed_state));
+                       if e.get().is_empty() { e.remove(); }
+               }
+       }
+}
+
+/// A set of messages which are pending UTXO lookups for processing.
+pub(super) struct PendingChecks {
+       internal: Mutex<PendingChecksContext>,
+}
+
+impl PendingChecks {
+       pub(super) fn new() -> Self {
+               PendingChecks { internal: Mutex::new(PendingChecksContext {
+                       channels: HashMap::new(), nodes: HashMap::new(),
+               }) }
+       }
+
+       /// Checks if there is a pending `channel_update` UTXO validation for the given channel,
+       /// and, if so, stores the channel message for handling later and returns an `Err`.
+       pub(super) fn check_hold_pending_channel_update(
+               &self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>
+       ) -> Result<(), LightningError> {
+               let mut pending_checks = self.internal.lock().unwrap();
+               if let hash_map::Entry::Occupied(e) = pending_checks.channels.entry(msg.short_channel_id) {
+                       let is_from_a = (msg.flags & 1) == 1;
+                       match Weak::upgrade(e.get()) {
+                               Some(msgs_ref) => {
+                                       let mut messages = msgs_ref.lock().unwrap();
+                                       let latest_update = if is_from_a {
+                                                       &mut messages.latest_channel_update_a
+                                               } else {
+                                                       &mut messages.latest_channel_update_b
+                                               };
+                                       if latest_update.is_none() || latest_update.as_ref().unwrap().timestamp() < msg.timestamp {
+                                               // If the messages we got has a higher timestamp, just blindly assume the
+                                               // signatures on the new message are correct and drop the old message. This
+                                               // may cause us to end up dropping valid `channel_update`s if a peer is
+                                               // malicious, but we should get the correct ones when the node updates them.
+                                               *latest_update = Some(
+                                                       if let Some(msg) = full_msg { ChannelUpdate::Full(msg.clone()) }
+                                                       else { ChannelUpdate::Unsigned(msg.clone()) });
+                                       }
+                                       return Err(LightningError {
+                                               err: "Awaiting channel_announcement validation to accept channel_update".to_owned(),
+                                               action: ErrorAction::IgnoreAndLog(Level::Gossip),
+                                       });
+                               },
+                               None => { e.remove(); },
+                       }
+               }
+               Ok(())
+       }
+
+       /// Checks if there is a pending `node_announcement` UTXO validation for a channel with the
+       /// given node and, if so, stores the channel message for handling later and returns an `Err`.
+       pub(super) fn check_hold_pending_node_announcement(
+               &self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>
+       ) -> Result<(), LightningError> {
+               let mut pending_checks = self.internal.lock().unwrap();
+               if let hash_map::Entry::Occupied(mut e) = pending_checks.nodes.entry(msg.node_id) {
+                       let mut found_at_least_one_chan = false;
+                       e.get_mut().retain(|node_msgs| {
+                               match Weak::upgrade(&node_msgs) {
+                                       Some(chan_mtx) => {
+                                               let mut chan_msgs = chan_mtx.lock().unwrap();
+                                               if let Some(chan_announce) = &chan_msgs.channel_announce {
+                                                       let latest_announce =
+                                                               if *chan_announce.node_id_1() == msg.node_id {
+                                                                       &mut chan_msgs.latest_node_announce_a
+                                                               } else {
+                                                                       &mut chan_msgs.latest_node_announce_b
+                                                               };
+                                                       if latest_announce.is_none() ||
+                                                               latest_announce.as_ref().unwrap().timestamp() < msg.timestamp
+                                                       {
+                                                               *latest_announce = Some(
+                                                                       if let Some(msg) = full_msg { NodeAnnouncement::Full(msg.clone()) }
+                                                                       else { NodeAnnouncement::Unsigned(msg.clone()) });
+                                                       }
+                                                       found_at_least_one_chan = true;
+                                                       true
+                                               } else {
+                                                       debug_assert!(false, "channel_announce is set before struct is added to node map");
+                                                       false
+                                               }
+                                       },
+                                       None => false,
+                               }
+                       });
+                       if e.get().is_empty() { e.remove(); }
+                       if found_at_least_one_chan {
+                               return Err(LightningError {
+                                       err: "Awaiting channel_announcement validation to accept node_announcement".to_owned(),
+                                       action: ErrorAction::IgnoreAndLog(Level::Gossip),
+                               });
+                       }
+               }
+               Ok(())
+       }
+
+       fn check_replace_previous_entry(msg: &msgs::UnsignedChannelAnnouncement,
+               full_msg: Option<&msgs::ChannelAnnouncement>, replacement: Option<Weak<Mutex<UtxoMessages>>>,
+               pending_channels: &mut HashMap<u64, Weak<Mutex<UtxoMessages>>>
+       ) -> Result<(), msgs::LightningError> {
+               match pending_channels.entry(msg.short_channel_id) {
+                       hash_map::Entry::Occupied(mut e) => {
+                               // There's already a pending lookup for the given SCID. Check if the messages
+                               // are the same and, if so, return immediately (don't bother spawning another
+                               // lookup if we haven't gotten that far yet).
+                               match Weak::upgrade(&e.get()) {
+                                       Some(pending_msgs) => {
+                                               let pending_matches = match &pending_msgs.lock().unwrap().channel_announce {
+                                                       Some(ChannelAnnouncement::Full(pending_msg)) => Some(pending_msg) == full_msg,
+                                                       Some(ChannelAnnouncement::Unsigned(pending_msg)) => pending_msg == msg,
+                                                       None => {
+                                                               // This shouldn't actually be reachable. We set the
+                                                               // `channel_announce` field under the same lock as setting the
+                                                               // channel map entry. Still, we can just treat it as
+                                                               // non-matching and let the new request fly.
+                                                               debug_assert!(false);
+                                                               false
+                                                       },
+                                               };
+                                               if pending_matches {
+                                                       return Err(LightningError {
+                                                               err: "Channel announcement is already being checked".to_owned(),
+                                                               action: ErrorAction::IgnoreDuplicateGossip,
+                                                       });
+                                               } else {
+                                                       // The earlier lookup is a different message. If we have another
+                                                       // request in-flight now replace the original.
+                                                       // Note that in the replace case whether to replace is somewhat
+                                                       // arbitrary - both results will be handled, we're just updating the
+                                                       // value that will be compared to future lookups with the same SCID.
+                                                       if let Some(item) = replacement {
+                                                               *e.get_mut() = item;
+                                                       }
+                                               }
+                                       },
+                                       None => {
+                                               // The earlier lookup already resolved. We can't be sure its the same
+                                               // so just remove/replace it and move on.
+                                               if let Some(item) = replacement {
+                                                       *e.get_mut() = item;
+                                               } else { e.remove(); }
+                                       },
+                               }
+                       },
+                       hash_map::Entry::Vacant(v) => {
+                               if let Some(item) = replacement { v.insert(item); }
+                       },
+               }
+               Ok(())
+       }
+
+       pub(super) fn check_channel_announcement<U: Deref>(&self,
+               utxo_lookup: &Option<U>, msg: &msgs::UnsignedChannelAnnouncement,
+               full_msg: Option<&msgs::ChannelAnnouncement>
+       ) -> Result<Option<u64>, msgs::LightningError> where U::Target: UtxoLookup {
+               let handle_result = |res| {
+                       match res {
+                               Ok(TxOut { value, script_pubkey }) => {
+                                       let expected_script =
+                                               make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_slice(), msg.bitcoin_key_2.as_slice()).to_v0_p2wsh();
+                                       if script_pubkey != expected_script {
+                                               return Err(LightningError{
+                                                       err: format!("Channel announcement key ({}) didn't match on-chain script ({})",
+                                                               expected_script.to_hex(), script_pubkey.to_hex()),
+                                                       action: ErrorAction::IgnoreError
+                                               });
+                                       }
+                                       Ok(Some(value))
+                               },
+                               Err(UtxoLookupError::UnknownChain) => {
+                                       Err(LightningError {
+                                               err: format!("Channel announced on an unknown chain ({})",
+                                                       msg.chain_hash.encode().to_hex()),
+                                               action: ErrorAction::IgnoreError
+                                       })
+                               },
+                               Err(UtxoLookupError::UnknownTx) => {
+                                       Err(LightningError {
+                                               err: "Channel announced without corresponding UTXO entry".to_owned(),
+                                               action: ErrorAction::IgnoreError
+                                       })
+                               },
+                       }
+               };
+
+               Self::check_replace_previous_entry(msg, full_msg, None,
+                       &mut self.internal.lock().unwrap().channels)?;
+
+               match utxo_lookup {
+                       &None => {
+                               // Tentatively accept, potentially exposing us to DoS attacks
+                               Ok(None)
+                       },
+                       &Some(ref utxo_lookup) => {
+                               match utxo_lookup.get_utxo(&msg.chain_hash, msg.short_channel_id) {
+                                       UtxoResult::Sync(res) => handle_result(res),
+                                       UtxoResult::Async(future) => {
+                                               let mut pending_checks = self.internal.lock().unwrap();
+                                               let mut async_messages = future.state.lock().unwrap();
+                                               if let Some(res) = async_messages.complete.take() {
+                                                       // In the unlikely event the future resolved before we managed to get it,
+                                                       // handle the result in-line.
+                                                       handle_result(res)
+                                               } else {
+                                                       Self::check_replace_previous_entry(msg, full_msg,
+                                                               Some(Arc::downgrade(&future.state)), &mut pending_checks.channels)?;
+                                                       async_messages.channel_announce = Some(
+                                                               if let Some(msg) = full_msg { ChannelAnnouncement::Full(msg.clone()) }
+                                                               else { ChannelAnnouncement::Unsigned(msg.clone()) });
+                                                       pending_checks.nodes.entry(msg.node_id_1)
+                                                               .or_insert(Vec::new()).push(Arc::downgrade(&future.state));
+                                                       pending_checks.nodes.entry(msg.node_id_2)
+                                                               .or_insert(Vec::new()).push(Arc::downgrade(&future.state));
+                                                       Err(LightningError {
+                                                               err: "Channel being checked async".to_owned(),
+                                                               action: ErrorAction::IgnoreAndLog(Level::Gossip),
+                                                       })
+                                               }
+                                       },
+                               }
+                       }
+               }
+       }
+
+       /// The maximum number of pending gossip checks before [`Self::too_many_checks_pending`]
+       /// returns `true`. Note that this isn't a strict upper-bound on the number of checks pending -
+       /// each peer may, at a minimum, read one more socket buffer worth of `channel_announcement`s
+       /// which we'll have to process. With a socket buffer of 4KB and a minimum
+       /// `channel_announcement` size of, roughly, 429 bytes, this may leave us with `10*our peer
+       /// count` messages to process beyond this limit. Because we'll probably have a few peers,
+       /// there's no reason for this constant to be materially less than 30 or so, and 32 in-flight
+       /// checks should be more than enough for decent parallelism.
+       const MAX_PENDING_LOOKUPS: usize = 32;
+
+       /// Returns true if there are a large number of async checks pending and future
+       /// `channel_announcement` messages should be delayed. Note that this is only a hint and
+       /// messages already in-flight may still have to be handled for various reasons.
+       pub(super) fn too_many_checks_pending(&self) -> bool {
+               let mut pending_checks = self.internal.lock().unwrap();
+               if pending_checks.channels.len() > Self::MAX_PENDING_LOOKUPS {
+                       // If we have many channel checks pending, ensure we don't have any dangling checks
+                       // (i.e. checks where the user told us they'd call back but drop'd the `UtxoFuture`
+                       // instead) before we commit to applying backpressure.
+                       pending_checks.channels.retain(|_, chan| {
+                               Weak::upgrade(&chan).is_some()
+                       });
+                       pending_checks.nodes.retain(|_, channels| {
+                               channels.retain(|chan| Weak::upgrade(&chan).is_some());
+                               !channels.is_empty()
+                       });
+                       pending_checks.channels.len() > Self::MAX_PENDING_LOOKUPS
+               } else {
+                       false
+               }
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use super::*;
+       use crate::routing::gossip::tests::*;
+       use crate::util::test_utils::{TestChainSource, TestLogger};
+       use crate::ln::msgs;
+
+       use bitcoin::blockdata::constants::genesis_block;
+       use bitcoin::secp256k1::{Secp256k1, SecretKey};
+
+       use core::sync::atomic::Ordering;
+
+       fn get_network() -> (TestChainSource, NetworkGraph<Box<TestLogger>>) {
+               let logger = Box::new(TestLogger::new());
+               let genesis_hash = genesis_block(bitcoin::Network::Testnet).header.block_hash();
+               let chain_source = TestChainSource::new(bitcoin::Network::Testnet);
+               let network_graph = NetworkGraph::new(genesis_hash, logger);
+
+               (chain_source, network_graph)
+       }
+
+       fn get_test_objects() -> (msgs::ChannelAnnouncement, TestChainSource,
+               NetworkGraph<Box<TestLogger>>, bitcoin::Script, msgs::NodeAnnouncement,
+               msgs::NodeAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, msgs::ChannelUpdate)
+       {
+               let secp_ctx = Secp256k1::new();
+
+               let (chain_source, network_graph) = get_network();
+
+               let good_script = get_channel_script(&secp_ctx);
+               let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
+               let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
+               let valid_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
+
+               let node_a_announce = get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx);
+               let node_b_announce = get_signed_node_announcement(|_| {}, node_2_privkey, &secp_ctx);
+
+               // Note that we have to set the "direction" flag correctly on both messages
+               let chan_update_a = get_signed_channel_update(|msg| msg.flags = 0, node_1_privkey, &secp_ctx);
+               let chan_update_b = get_signed_channel_update(|msg| msg.flags = 1, node_2_privkey, &secp_ctx);
+               let chan_update_c = get_signed_channel_update(|msg| {
+                       msg.flags = 1; msg.timestamp += 1; }, node_2_privkey, &secp_ctx);
+
+               (valid_announcement, chain_source, network_graph, good_script, node_a_announce,
+                       node_b_announce, chan_update_a, chan_update_b, chan_update_c)
+       }
+
+       #[test]
+       fn test_fast_async_lookup() {
+               // Check that async lookups which resolve quicker than the future is returned to the
+               // `get_utxo` call can read it still resolve properly.
+               let (valid_announcement, chain_source, network_graph, good_script, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap();
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_some());
+       }
+
+       #[test]
+       fn test_async_lookup() {
+               // Test a simple async lookup
+               let (valid_announcement, chain_source, network_graph, good_script,
+                       node_a_announce, node_b_announce, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 0, script_pubkey: good_script }));
+               network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap();
+               network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap();
+
+               assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1)
+                       .unwrap().announcement_info.is_none());
+
+               network_graph.update_node_from_announcement(&node_a_announce).unwrap();
+               network_graph.update_node_from_announcement(&node_b_announce).unwrap();
+
+               assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1)
+                       .unwrap().announcement_info.is_some());
+       }
+
+       #[test]
+       fn test_invalid_async_lookup() {
+               // Test an async lookup which returns an incorrect script
+               let (valid_announcement, chain_source, network_graph, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 1_000_000, script_pubkey: bitcoin::Script::new() }));
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+       }
+
+       #[test]
+       fn test_failing_async_lookup() {
+               // Test an async lookup which returns an error
+               let (valid_announcement, chain_source, network_graph, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+
+               future.resolve_without_forwarding(&network_graph, Err(UtxoLookupError::UnknownTx));
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+       }
+
+       #[test]
+       fn test_updates_async_lookup() {
+               // Test async lookups will process pending channel_update/node_announcements once they
+               // complete.
+               let (valid_announcement, chain_source, network_graph, good_script, node_a_announce,
+                       node_b_announce, chan_update_a, chan_update_b, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+
+               assert_eq!(
+                       network_graph.update_node_from_announcement(&node_a_announce).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept node_announcement");
+               assert_eq!(
+                       network_graph.update_node_from_announcement(&node_b_announce).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept node_announcement");
+
+               assert_eq!(network_graph.update_channel(&chan_update_a).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept channel_update");
+               assert_eq!(network_graph.update_channel(&chan_update_b).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept channel_update");
+
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+
+               assert!(network_graph.read_only().channels()
+                       .get(&valid_announcement.contents.short_channel_id).unwrap().one_to_two.is_some());
+               assert!(network_graph.read_only().channels()
+                       .get(&valid_announcement.contents.short_channel_id).unwrap().two_to_one.is_some());
+
+               assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1)
+                       .unwrap().announcement_info.is_some());
+               assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_2)
+                       .unwrap().announcement_info.is_some());
+       }
+
+       #[test]
+       fn test_latest_update_async_lookup() {
+               // Test async lookups will process the latest channel_update if two are received while
+               // awaiting an async UTXO lookup.
+               let (valid_announcement, chain_source, network_graph, good_script, _,
+                       _, chan_update_a, chan_update_b, chan_update_c, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
+
+               assert_eq!(network_graph.update_channel(&chan_update_a).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept channel_update");
+               assert_eq!(network_graph.update_channel(&chan_update_b).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept channel_update");
+               assert_eq!(network_graph.update_channel(&chan_update_c).unwrap_err().err,
+                       "Awaiting channel_announcement validation to accept channel_update");
+
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+
+               assert_eq!(chan_update_a.contents.timestamp, chan_update_b.contents.timestamp);
+               assert!(network_graph.read_only().channels()
+                               .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap()
+                               .one_to_two.as_ref().unwrap().last_update !=
+                       network_graph.read_only().channels()
+                               .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap()
+                               .two_to_one.as_ref().unwrap().last_update);
+       }
+
+       #[test]
+       fn test_no_double_lookups() {
+               // Test that a pending async lookup will prevent a second async lookup from flying, but
+               // only if the channel_announcement message is identical.
+               let (valid_announcement, chain_source, network_graph, good_script, ..) = get_test_objects();
+
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 1);
+
+               // If we make a second request with the same message, the call count doesn't increase...
+               let future_b = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future_b.clone());
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel announcement is already being checked");
+               assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 1);
+
+               // But if we make a third request with a tweaked message, we should get a second call
+               // against our new future...
+               let secp_ctx = Secp256k1::new();
+               let replacement_pk_1 = &SecretKey::from_slice(&[99; 32]).unwrap();
+               let replacement_pk_2 = &SecretKey::from_slice(&[98; 32]).unwrap();
+               let invalid_announcement = get_signed_channel_announcement(|_| {}, replacement_pk_1, replacement_pk_2, &secp_ctx);
+               assert_eq!(
+                       network_graph.update_channel_from_announcement(&invalid_announcement, &Some(&chain_source)).unwrap_err().err,
+                       "Channel being checked async");
+               assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 2);
+
+               // Still, if we resolve the original future, the original channel will be accepted.
+               future.resolve_without_forwarding(&network_graph,
+                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+               assert!(!network_graph.read_only().channels()
+                       .get(&valid_announcement.contents.short_channel_id).unwrap()
+                       .announcement_message.as_ref().unwrap()
+                       .contents.features.supports_unknown_test_feature());
+       }
+
+       #[test]
+       fn test_checks_backpressure() {
+               // Test that too_many_checks_pending returns true when there are many checks pending, and
+               // returns false once they complete.
+               let secp_ctx = Secp256k1::new();
+               let (chain_source, network_graph) = get_network();
+
+               // We cheat and use a single future for all the lookups to complete them all at once.
+               let future = UtxoFuture::new();
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
+
+               let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
+               let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
+
+               for i in 0..PendingChecks::MAX_PENDING_LOOKUPS {
+                       let valid_announcement = get_signed_channel_announcement(
+                               |msg| msg.short_channel_id += 1 + i as u64, node_1_privkey, node_2_privkey, &secp_ctx);
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err();
+                       assert!(!network_graph.pending_checks.too_many_checks_pending());
+               }
+
+               let valid_announcement = get_signed_channel_announcement(
+                       |_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
+               network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err();
+               assert!(network_graph.pending_checks.too_many_checks_pending());
+
+               // Once the future completes the "too many checks" flag should reset.
+               future.resolve_without_forwarding(&network_graph, Err(UtxoLookupError::UnknownTx));
+               assert!(!network_graph.pending_checks.too_many_checks_pending());
+       }
+
+       #[test]
+       fn test_checks_backpressure_drop() {
+               // Test that too_many_checks_pending returns true when there are many checks pending, and
+               // returns false if we drop some of the futures without completion.
+               let secp_ctx = Secp256k1::new();
+               let (chain_source, network_graph) = get_network();
+
+               // We cheat and use a single future for all the lookups to complete them all at once.
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(UtxoFuture::new());
+
+               let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
+               let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
+
+               for i in 0..PendingChecks::MAX_PENDING_LOOKUPS {
+                       let valid_announcement = get_signed_channel_announcement(
+                               |msg| msg.short_channel_id += 1 + i as u64, node_1_privkey, node_2_privkey, &secp_ctx);
+                       network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err();
+                       assert!(!network_graph.pending_checks.too_many_checks_pending());
+               }
+
+               let valid_announcement = get_signed_channel_announcement(
+                       |_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
+               network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err();
+               assert!(network_graph.pending_checks.too_many_checks_pending());
+
+               // Once the future is drop'd (by resetting the `utxo_ret` value) the "too many checks" flag
+               // should reset to false.
+               *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Sync(Err(UtxoLookupError::UnknownTx));
+               assert!(!network_graph.pending_checks.too_many_checks_pending());
+       }
+}
index 9f7caa2c1804350818a5804f49fb0896c6d33f0f..5631093723733f16f4d7447c0865f58219d1cf40 100644 (file)
@@ -14,6 +14,8 @@ use std::sync::Condvar as StdCondvar;
 
 use crate::prelude::HashMap;
 
+use super::{LockTestExt, LockHeldState};
+
 #[cfg(feature = "backtrace")]
 use {crate::prelude::hash_map, backtrace::Backtrace, std::sync::Once};
 
@@ -168,6 +170,18 @@ impl LockMetadata {
        fn pre_lock(this: &Arc<LockMetadata>) { Self::_pre_lock(this, false); }
        fn pre_read_lock(this: &Arc<LockMetadata>) -> bool { Self::_pre_lock(this, true) }
 
+       fn held_by_thread(this: &Arc<LockMetadata>) -> LockHeldState {
+               let mut res = LockHeldState::NotHeldByThread;
+               LOCKS_HELD.with(|held| {
+                       for (locked_idx, _locked) in held.borrow().iter() {
+                               if *locked_idx == this.lock_idx {
+                                       res = LockHeldState::HeldByThread;
+                               }
+                       }
+               });
+               res
+       }
+
        fn try_locked(this: &Arc<LockMetadata>) {
                LOCKS_HELD.with(|held| {
                        // Since a try-lock will simply fail if the lock is held already, we do not
@@ -248,6 +262,13 @@ impl<T> Mutex<T> {
        }
 }
 
+impl <T> LockTestExt for Mutex<T> {
+       #[inline]
+       fn held_by_thread(&self) -> LockHeldState {
+               LockMetadata::held_by_thread(&self.deps)
+       }
+}
+
 pub struct RwLock<T: Sized> {
        inner: StdRwLock<T>,
        deps: Arc<LockMetadata>,
@@ -332,4 +353,11 @@ impl<T> RwLock<T> {
        }
 }
 
+impl <T> LockTestExt for RwLock<T> {
+       #[inline]
+       fn held_by_thread(&self) -> LockHeldState {
+               LockMetadata::held_by_thread(&self.deps)
+       }
+}
+
 pub type FairRwLock<T> = RwLock<T>;
diff --git a/lightning/src/sync/fairrwlock.rs b/lightning/src/sync/fairrwlock.rs
new file mode 100644 (file)
index 0000000..a9519ac
--- /dev/null
@@ -0,0 +1,59 @@
+use std::sync::{LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult};
+use std::sync::atomic::{AtomicUsize, Ordering};
+use super::{LockHeldState, LockTestExt};
+
+/// Rust libstd's RwLock does not provide any fairness guarantees (and, in fact, when used on
+/// Linux with pthreads under the hood, readers trivially and completely starve writers).
+/// Because we often hold read locks while doing message processing in multiple threads which
+/// can use significant CPU time, with write locks being time-sensitive but relatively small in
+/// CPU time, we can end up with starvation completely blocking incoming connections or pings,
+/// especially during initial graph sync.
+///
+/// Thus, we need to block readers when a writer is pending, which we do with a trivial RwLock
+/// wrapper here. Its not particularly optimized, but provides some reasonable fairness by
+/// blocking readers (by taking the write lock) if there are writers pending when we go to take
+/// a read lock.
+pub struct FairRwLock<T> {
+       lock: RwLock<T>,
+       waiting_writers: AtomicUsize,
+}
+
+impl<T> FairRwLock<T> {
+       pub fn new(t: T) -> Self {
+               Self { lock: RwLock::new(t), waiting_writers: AtomicUsize::new(0) }
+       }
+
+       // Note that all atomic accesses are relaxed, as we do not rely on the atomics here for any
+       // ordering at all, instead relying on the underlying RwLock to provide ordering of unrelated
+       // memory.
+       pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
+               self.waiting_writers.fetch_add(1, Ordering::Relaxed);
+               let res = self.lock.write();
+               self.waiting_writers.fetch_sub(1, Ordering::Relaxed);
+               res
+       }
+
+       pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
+               if self.waiting_writers.load(Ordering::Relaxed) != 0 {
+                       let _write_queue_lock = self.lock.write();
+               }
+               // Note that we don't consider ensuring that an underlying RwLock allowing writers to
+               // starve readers doesn't exhibit the same behavior here. I'm not aware of any
+               // libstd-backing RwLock which exhibits this behavior, and as documented in the
+               // struct-level documentation, it shouldn't pose a significant issue for our current
+               // codebase.
+               self.lock.read()
+       }
+
+       pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
+               self.lock.try_write()
+       }
+}
+
+impl<T> LockTestExt for FairRwLock<T> {
+       #[inline]
+       fn held_by_thread(&self) -> LockHeldState {
+               // fairrwlock is only built in non-test modes, so we should never support tests.
+               LockHeldState::Unsupported
+       }
+}
index f7226a5fa34eef114d27c6569207dbc68354b950..50ef40e295f50d0a0d9095a0f3dfe4c73916a340 100644 (file)
@@ -1,3 +1,16 @@
+#[allow(dead_code)] // Depending on the compilation flags some variants are never used
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) enum LockHeldState {
+       HeldByThread,
+       NotHeldByThread,
+       #[cfg(any(feature = "_bench_unstable", not(test)))]
+       Unsupported,
+}
+
+pub(crate) trait LockTestExt {
+       fn held_by_thread(&self) -> LockHeldState;
+}
+
 #[cfg(all(feature = "std", not(feature = "_bench_unstable"), test))]
 mod debug_sync;
 #[cfg(all(feature = "std", not(feature = "_bench_unstable"), test))]
@@ -7,9 +20,22 @@ pub use debug_sync::*;
 mod test_lockorder_checks;
 
 #[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
-pub use ::std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
+pub(crate) mod fairrwlock;
+#[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
+pub use {std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}, fairrwlock::FairRwLock};
+
 #[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
-pub use crate::util::fairrwlock::FairRwLock;
+mod ext_impl {
+       use super::*;
+       impl<T> LockTestExt for Mutex<T> {
+               #[inline]
+               fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported }
+       }
+       impl<T> LockTestExt for RwLock<T> {
+               #[inline]
+               fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported }
+       }
+}
 
 #[cfg(not(feature = "std"))]
 mod nostd_sync;
index caf88a7cc04a8617a86e63988a7cc7a291fe96bc..e17aa6ab15faa5dc33b66dbc1b80ab79fd36cb18 100644 (file)
@@ -2,6 +2,7 @@ pub use ::alloc::sync::Arc;
 use core::ops::{Deref, DerefMut};
 use core::time::Duration;
 use core::cell::{RefCell, Ref, RefMut};
+use super::{LockTestExt, LockHeldState};
 
 pub type LockResult<Guard> = Result<Guard, ()>;
 
@@ -61,6 +62,14 @@ impl<T> Mutex<T> {
        }
 }
 
+impl<T> LockTestExt for Mutex<T> {
+       #[inline]
+       fn held_by_thread(&self) -> LockHeldState {
+               if self.lock().is_err() { return LockHeldState::HeldByThread; }
+               else { return LockHeldState::NotHeldByThread; }
+       }
+}
+
 pub struct RwLock<T: ?Sized> {
        inner: RefCell<T>
 }
@@ -116,4 +125,12 @@ impl<T> RwLock<T> {
        }
 }
 
+impl<T> LockTestExt for RwLock<T> {
+       #[inline]
+       fn held_by_thread(&self) -> LockHeldState {
+               if self.write().is_err() { return LockHeldState::HeldByThread; }
+               else { return LockHeldState::NotHeldByThread; }
+       }
+}
+
 pub type FairRwLock<T> = RwLock<T>;
index f9f30e2cfa28efb4d42960d3fb4c1afc713b8933..a3f746b11dc80dd32bd7badf5f9786acf6426a89 100644 (file)
@@ -1,5 +1,10 @@
 use crate::sync::debug_sync::{RwLock, Mutex};
 
+use super::{LockHeldState, LockTestExt};
+
+use std::sync::Arc;
+use std::thread;
+
 #[test]
 #[should_panic]
 #[cfg(not(feature = "backtrace"))]
@@ -92,3 +97,22 @@ fn read_write_lockorder_fail() {
                let _a = a.write().unwrap();
        }
 }
+
+#[test]
+fn test_thread_locked_state() {
+       let mtx = Arc::new(Mutex::new(()));
+       let mtx_ref = Arc::clone(&mtx);
+       assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
+
+       let lck = mtx.lock().unwrap();
+       assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
+
+       let thrd = std::thread::spawn(move || {
+               assert_eq!(mtx_ref.held_by_thread(), LockHeldState::NotHeldByThread);
+       });
+       thrd.join().unwrap();
+       assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
+
+       std::mem::drop(lck);
+       assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
+}
index 475533c902a372fdb0bea1b86cb0e754dc90fbe4..4d68d01f6ed9301661145b222cf5b0aea2dba870 100644 (file)
@@ -565,11 +565,9 @@ pub enum Event {
        /// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentPathFailed`
        /// event. In this situation, you SHOULD treat this payment as having succeeded.
        PaymentSent {
-               /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::retry_payment`].
+               /// The id returned by [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
-               /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
                payment_id: Option<PaymentId>,
                /// The preimage to the hash given to ChannelManager::send_payment.
                /// Note that this serves as a payment receipt, if you wish to have such a thing, you must
@@ -594,16 +592,16 @@ pub enum Event {
        /// provide failure information for each MPP part in the payment.
        ///
        /// This event is provided once there are no further pending HTLCs for the payment and the
-       /// payment is no longer retryable due to [`ChannelManager::abandon_payment`] having been
-       /// called for the corresponding payment.
+       /// payment is no longer retryable, due either to the [`Retry`] provided or
+       /// [`ChannelManager::abandon_payment`] having been called for the corresponding payment.
        ///
+       /// [`Retry`]: crate::ln::channelmanager::Retry
        /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
        PaymentFailed {
                /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::retry_payment`] and [`ChannelManager::abandon_payment`].
+               /// [`ChannelManager::abandon_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
-               /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
                /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
                payment_id: PaymentId,
                /// The hash that was given to [`ChannelManager::send_payment`].
@@ -616,11 +614,9 @@ pub enum Event {
        /// Always generated after [`Event::PaymentSent`] and thus useful for scoring channels. See
        /// [`Event::PaymentSent`] for obtaining the payment preimage.
        PaymentPathSuccessful {
-               /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::retry_payment`].
+               /// The id returned by [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
-               /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
                payment_id: PaymentId,
                /// The hash that was given to [`ChannelManager::send_payment`].
                ///
@@ -631,24 +627,22 @@ pub enum Event {
                /// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
                path: Vec<RouteHop>,
        },
-       /// Indicates an outbound HTLC we sent failed. Probably some intermediary node dropped
-       /// something. You may wish to retry with a different route.
-       ///
-       /// If you have given up retrying this payment and wish to fail it, you MUST call
-       /// [`ChannelManager::abandon_payment`] at least once for a given [`PaymentId`] or memory
-       /// related to payment tracking will leak.
+       /// Indicates an outbound HTLC we sent failed, likely due to an intermediary node being unable to
+       /// handle the HTLC.
        ///
        /// Note that this does *not* indicate that all paths for an MPP payment have failed, see
        /// [`Event::PaymentFailed`] and [`all_paths_failed`].
        ///
+       /// See [`ChannelManager::abandon_payment`] for giving up on this payment before its retries have
+       /// been exhausted.
+       ///
        /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
        /// [`all_paths_failed`]: Self::PaymentPathFailed::all_paths_failed
        PaymentPathFailed {
                /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::retry_payment`] and [`ChannelManager::abandon_payment`].
+               /// [`ChannelManager::abandon_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
-               /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
                /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
                payment_id: Option<PaymentId>,
                /// The hash that was given to [`ChannelManager::send_payment`].
@@ -656,8 +650,8 @@ pub enum Event {
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_hash: PaymentHash,
                /// Indicates the payment was rejected for some reason by the recipient. This implies that
-               /// the payment has failed, not just the route in question. If this is not set, you may
-               /// retry the payment via a different route.
+               /// the payment has failed, not just the route in question. If this is not set, the payment may
+               /// be retried via a different route.
                payment_failed_permanently: bool,
                /// Any failure information conveyed via the Onion return packet by a node along the failed
                /// payment route.
@@ -670,20 +664,6 @@ pub enum Event {
                /// For both single-path and multi-path payments, this is set if all paths of the payment have
                /// failed. This will be set to false if (1) this is an MPP payment and (2) other parts of the
                /// larger MPP payment were still in flight when this event was generated.
-               ///
-               /// Note that if you are retrying individual MPP parts, using this value to determine if a
-               /// payment has fully failed is race-y. Because multiple failures can happen prior to events
-               /// being processed, you may retry in response to a first failure, with a second failure
-               /// (with `all_paths_failed` set) still pending. Then, when the second failure is processed
-               /// you will see `all_paths_failed` set even though the retry of the first failure still
-               /// has an associated in-flight HTLC. See (1) for an example of such a failure.
-               ///
-               /// If you wish to retry individual MPP parts and learn when a payment has failed, you must
-               /// call [`ChannelManager::abandon_payment`] and wait for a [`Event::PaymentFailed`] event.
-               ///
-               /// (1) <https://github.com/lightningdevkit/rust-lightning/issues/1164>
-               ///
-               /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
                all_paths_failed: bool,
                /// The payment path that failed.
                path: Vec<RouteHop>,
@@ -696,12 +676,9 @@ pub enum Event {
                /// If this is `Some`, then the corresponding channel should be avoided when the payment is
                /// retried. May be `None` for older [`Event`] serializations.
                short_channel_id: Option<u64>,
-               /// Parameters needed to compute a new [`Route`] when retrying the failed payment path.
-               ///
-               /// See [`find_route`] for details.
+               /// Parameters used by LDK to compute a new [`Route`] when retrying the failed payment path.
                ///
                /// [`Route`]: crate::routing::router::Route
-               /// [`find_route`]: crate::routing::router::find_route
                retry: Option<RouteParameters>,
 #[cfg(test)]
                error_code: Option<u16>,
@@ -1612,13 +1589,18 @@ pub enum MessageSendEvent {
                /// The channel_announcement which should be sent.
                msg: msgs::ChannelAnnouncement,
                /// The followup channel_update which should be sent.
-               update_msg: msgs::ChannelUpdate,
+               update_msg: Option<msgs::ChannelUpdate>,
        },
        /// Used to indicate that a channel_update should be broadcast to all peers.
        BroadcastChannelUpdate {
                /// The channel_update which should be sent.
                msg: msgs::ChannelUpdate,
        },
+       /// Used to indicate that a node_announcement should be broadcast to all peers.
+       BroadcastNodeAnnouncement {
+               /// The node_announcement which should be sent.
+               msg: msgs::NodeAnnouncement,
+       },
        /// Used to indicate that a channel_update should be sent to a single peer.
        /// In contrast to [`Self::BroadcastChannelUpdate`], this is used when the channel is a
        /// private channel and we shouldn't be informing all of our peers of channel parameters.
diff --git a/lightning/src/util/fairrwlock.rs b/lightning/src/util/fairrwlock.rs
deleted file mode 100644 (file)
index 5715a8c..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-use std::sync::{LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult};
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-/// Rust libstd's RwLock does not provide any fairness guarantees (and, in fact, when used on
-/// Linux with pthreads under the hood, readers trivially and completely starve writers).
-/// Because we often hold read locks while doing message processing in multiple threads which
-/// can use significant CPU time, with write locks being time-sensitive but relatively small in
-/// CPU time, we can end up with starvation completely blocking incoming connections or pings,
-/// especially during initial graph sync.
-///
-/// Thus, we need to block readers when a writer is pending, which we do with a trivial RwLock
-/// wrapper here. Its not particularly optimized, but provides some reasonable fairness by
-/// blocking readers (by taking the write lock) if there are writers pending when we go to take
-/// a read lock.
-pub struct FairRwLock<T> {
-       lock: RwLock<T>,
-       waiting_writers: AtomicUsize,
-}
-
-impl<T> FairRwLock<T> {
-       pub fn new(t: T) -> Self {
-               Self { lock: RwLock::new(t), waiting_writers: AtomicUsize::new(0) }
-       }
-
-       // Note that all atomic accesses are relaxed, as we do not rely on the atomics here for any
-       // ordering at all, instead relying on the underlying RwLock to provide ordering of unrelated
-       // memory.
-       pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
-               self.waiting_writers.fetch_add(1, Ordering::Relaxed);
-               let res = self.lock.write();
-               self.waiting_writers.fetch_sub(1, Ordering::Relaxed);
-               res
-       }
-
-       pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
-               if self.waiting_writers.load(Ordering::Relaxed) != 0 {
-                       let _write_queue_lock = self.lock.write();
-               }
-               // Note that we don't consider ensuring that an underlying RwLock allowing writers to
-               // starve readers doesn't exhibit the same behavior here. I'm not aware of any
-               // libstd-backing RwLock which exhibits this behavior, and as documented in the
-               // struct-level documentation, it shouldn't pose a significant issue for our current
-               // codebase.
-               self.lock.read()
-       }
-
-       pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
-               self.lock.try_write()
-       }
-}
index cccbfe7bc7a43434a12b8c7608dff2d935e5c1dc..3d45172517db3e706dcbf4884dd75923c872c8a5 100644 (file)
@@ -1,10 +1,11 @@
 //! 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 alloc::vec::Vec;
+use alloc::slice::Iter;
 use core::hash::Hash;
 use core::cmp::Ord;
-use core::ops::RangeBounds;
+use core::ops::{Bound, RangeBounds};
 
 /// A map which can be iterated in a deterministic order.
 ///
@@ -21,11 +22,10 @@ use core::ops::RangeBounds;
 /// keys in the order defined by [`Ord`].
 ///
 /// [`BTreeMap`]: alloc::collections::BTreeMap
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, 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>,
+       keys: Vec<K>,
 }
 
 impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
@@ -33,7 +33,7 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
        pub fn new() -> Self {
                Self {
                        map: HashMap::new(),
-                       keys: BTreeSet::new(),
+                       keys: Vec::new(),
                }
        }
 
@@ -58,7 +58,8 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
        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");
+                       let idx = self.keys.iter().position(|k| k == key).expect("map and keys must be consistent");
+                       self.keys.remove(idx);
                }
                ret
        }
@@ -68,7 +69,7 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
        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");
+                       self.keys.push(key);
                }
                ret
        }
@@ -109,9 +110,21 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
        }
 
        /// 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> {
+       pub fn range<R: RangeBounds<K>>(&mut self, range: R) -> Range<K, V> {
+               self.keys.sort_unstable();
+               let start = match range.start_bound() {
+                       Bound::Unbounded => 0,
+                       Bound::Included(key) => self.keys.binary_search(key).unwrap_or_else(|index| index),
+                       Bound::Excluded(key) => self.keys.binary_search(key).and_then(|index| Ok(index + 1)).unwrap_or_else(|index| index),
+               };
+               let end = match range.end_bound() {
+                       Bound::Unbounded => self.keys.len(),
+                       Bound::Included(key) => self.keys.binary_search(key).and_then(|index| Ok(index + 1)).unwrap_or_else(|index| index),
+                       Bound::Excluded(key) => self.keys.binary_search(key).unwrap_or_else(|index| index),
+               };
+
                Range {
-                       inner_range: self.keys.range(range),
+                       inner_range: self.keys[start..end].iter(),
                        map: &self.map,
                }
        }
@@ -127,9 +140,15 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
        }
 }
 
+impl<K: Hash + Ord + PartialEq, V: PartialEq> PartialEq for IndexedMap<K, V> {
+       fn eq(&self, other: &Self) -> bool {
+               self.map == other.map
+       }
+}
+
 /// 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>,
+       inner_range: Iter<'a, K>,
        map: &'a HashMap<K, V>,
 }
 impl<'a, K: Hash + Ord, V: 'a> Iterator for Range<'a, K, V> {
@@ -148,7 +167,7 @@ pub struct VacantEntry<'a, K: Hash + Ord, V> {
        #[cfg(not(feature = "hashbrown"))]
        underlying_entry: hash_map::VacantEntry<'a, K, V>,
        key: K,
-       keys: &'a mut BTreeSet<K>,
+       keys: &'a mut Vec<K>,
 }
 
 /// An [`Entry`] for an existing key-value pair
@@ -157,7 +176,7 @@ pub struct OccupiedEntry<'a, K: Hash + Ord, V> {
        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>,
+       keys: &'a mut Vec<K>,
 }
 
 /// A mutable reference to a position in the map. This can be used to reference, add, or update the
@@ -172,7 +191,7 @@ pub enum Entry<'a, K: Hash + Ord, 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.keys.push(self.key);
                self.underlying_entry.insert(value)
        }
 }
@@ -181,7 +200,8 @@ 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");
+               let idx = self.keys.iter().position(|k| k == &res.0).expect("map and keys must be consistent");
+               self.keys.remove(idx);
                res
        }
 
index 1673bd07f69b24d7af49f7d9c3604ea33f000422..7bcbc5a41fbf72c346f6e2ed81ddebfad43ce9f1 100644 (file)
@@ -27,8 +27,6 @@ pub mod wakers;
 pub(crate) mod atomic_counter;
 pub(crate) mod byte_utils;
 pub(crate) mod chacha20;
-#[cfg(all(any(feature = "_bench_unstable", not(test)), feature = "std"))]
-pub(crate) mod fairrwlock;
 #[cfg(fuzzing)]
 pub mod zbase32;
 #[cfg(not(fuzzing))]
index 928cc61946e46f358a70e82672b06bda1dec4867..847005e324e60f5a0e2e42d67e31009571b27e2b 100644 (file)
@@ -770,6 +770,7 @@ impl Readable for Vec<u8> {
 }
 
 impl_for_vec!(ecdsa::Signature);
+impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
 impl_for_vec!((A, B), A, B);
 
 impl Writeable for Script {
index 2dd764022cd63a2a253910fac4be5be1d8c77ed9..0a5c0b643dd0c315f2782d94b7caa469dcf4e46d 100644 (file)
@@ -459,20 +459,50 @@ macro_rules! _decode_tlv_stream_range {
        } }
 }
 
+/// Implements [`Readable`]/[`Writeable`] for a message struct that may include non-TLV and
+/// TLV-encoded parts.
+///
+/// This is useful to implement a [`CustomMessageReader`].
+///
+/// Currently `$fieldty` may only be `option`, i.e., `$tlvfield` is optional field.
+///
+/// For example,
+/// ```
+/// # use lightning::impl_writeable_msg;
+/// struct MyCustomMessage {
+///    pub field_1: u32,
+///    pub field_2: bool,
+///    pub field_3: String,
+///    pub tlv_optional_integer: Option<u32>,
+/// }
+///
+/// impl_writeable_msg!(MyCustomMessage, {
+///    field_1,
+///    field_2,
+///    field_3
+/// }, {
+///    (1, tlv_optional_integer, option),
+/// });
+/// ```
+///
+/// [`Readable`]: crate::util::ser::Readable
+/// [`Writeable`]: crate::util::ser::Writeable
+/// [`CustomMessageReader`]: crate::ln::wire::CustomMessageReader
+#[macro_export]
 macro_rules! impl_writeable_msg {
        ($st:ident, {$($field:ident),* $(,)*}, {$(($type: expr, $tlvfield: ident, $fieldty: tt)),* $(,)*}) => {
                impl $crate::util::ser::Writeable for $st {
                        fn write<W: $crate::util::ser::Writer>(&self, w: &mut W) -> Result<(), $crate::io::Error> {
                                $( self.$field.write(w)?; )*
-                               encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*});
+                               $crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*});
                                Ok(())
                        }
                }
                impl $crate::util::ser::Readable for $st {
                        fn read<R: $crate::io::Read>(r: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
                                $(let $field = $crate::util::ser::Readable::read(r)?;)*
-                               $(_init_tlv_field_var!($tlvfield, $fieldty);)*
-                               decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
+                               $($crate::_init_tlv_field_var!($tlvfield, $fieldty);)*
+                               $crate::decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
                                Ok(Self {
                                        $($field),*,
                                        $($tlvfield),*
@@ -644,10 +674,10 @@ macro_rules! _init_and_read_tlv_fields {
 }
 
 /// Implements [`Readable`]/[`Writeable`] for a struct storing it as a set of TLVs
-/// If `$fieldty` is `required`, then `$field` is a required field that is not an Option nor a Vec.
+/// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
 /// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
 /// If `$fieldty` is `option`, then `$field` is optional field.
-/// If `$fieldty` is `vec_type`, then `$field` is a Vec, which needs to have its individual elements serialized.
+/// If `$fieldty` is `vec_type`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
 ///
 /// For example,
 /// ```
index 1dae61ab3ef5b1841241b069612f71c7e5cc8f38..344f5b4c62d01736afd85654064735c68f0456bd 100644 (file)
@@ -22,9 +22,10 @@ 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::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
+use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
 use crate::routing::router::{find_route, InFlightHtlcs, Route, RouteHop, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
-use crate::routing::scoring::FixedPenaltyScorer;
+use crate::routing::scoring::{ChannelUsage, Score};
 use crate::util::config::UserConfig;
 use crate::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
 use crate::util::events;
@@ -47,6 +48,7 @@ use regex;
 
 use crate::io;
 use crate::prelude::*;
+use core::cell::RefCell;
 use core::time::Duration;
 use crate::sync::{Mutex, Arc};
 use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
@@ -77,17 +79,18 @@ impl chaininterface::FeeEstimator for TestFeeEstimator {
 
 pub struct TestRouter<'a> {
        pub network_graph: Arc<NetworkGraph<&'a TestLogger>>,
-       pub next_routes: Mutex<VecDeque<Result<Route, LightningError>>>,
+       pub next_routes: Mutex<VecDeque<(RouteParameters, Result<Route, LightningError>)>>,
+       pub scorer: &'a Mutex<TestScorer>,
 }
 
 impl<'a> TestRouter<'a> {
-       pub fn new(network_graph: Arc<NetworkGraph<&'a TestLogger>>) -> Self {
-               Self { network_graph, next_routes: Mutex::new(VecDeque::new()), }
+       pub fn new(network_graph: Arc<NetworkGraph<&'a TestLogger>>, scorer: &'a Mutex<TestScorer>) -> Self {
+               Self { network_graph, next_routes: Mutex::new(VecDeque::new()), scorer }
        }
 
-       pub fn expect_find_route(&self, result: Result<Route, LightningError>) {
+       pub fn expect_find_route(&self, query: RouteParameters, result: Result<Route, LightningError>) {
                let mut expected_routes = self.next_routes.lock().unwrap();
-               expected_routes.push_back(result);
+               expected_routes.push_back((query, result));
        }
 }
 
@@ -96,27 +99,50 @@ 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
+               if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() {
+                       assert_eq!(find_route_query, *params);
+                       if let Ok(ref route) = find_route_res {
+                               let locked_scorer = self.scorer.lock().unwrap();
+                               let scorer = ScorerAccountingForInFlightHtlcs::new(locked_scorer, inflight_htlcs);
+                               for path in &route.paths {
+                                       let mut aggregate_msat = 0u64;
+                                       for (idx, hop) in path.iter().rev().enumerate() {
+                                               aggregate_msat += hop.fee_msat;
+                                               let usage = ChannelUsage {
+                                                       amount_msat: aggregate_msat,
+                                                       inflight_htlc_msat: 0,
+                                                       effective_capacity: EffectiveCapacity::Unknown,
+                                               };
+
+                                               // Since the path is reversed, the last element in our iteration is the first
+                                               // hop.
+                                               if idx == path.len() - 1 {
+                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage);
+                                               } else {
+                                                       let curr_hop_path_idx = path.len() - 1 - idx;
+                                                       scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage);
+                                               }
+                                       }
+                               }
+                       }
+                       return find_route_res;
                }
                let logger = TestLogger::new();
+               let scorer = self.scorer.lock().unwrap();
                find_route(
                        payer, params, &self.network_graph, first_hops, &logger,
-                       &ScorerAccountingForInFlightHtlcs::new(TestScorer::with_penalty(0), &inflight_htlcs),
+                       &ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs),
                        &[42; 32]
                )
        }
-       fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
-       fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {}
-       fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {}
-       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;
+               #[cfg(feature = "std")] {
+                       if std::thread::panicking() {
+                               return;
+                       }
                }
                assert!(self.next_routes.lock().unwrap().is_empty());
        }
@@ -305,6 +331,7 @@ impl chaininterface::BroadcasterInterface for TestBroadcaster {
 pub struct TestChannelMessageHandler {
        pub pending_events: Mutex<Vec<events::MessageSendEvent>>,
        expected_recv_msgs: Mutex<Option<Vec<wire::Message<()>>>>,
+       connected_peers: Mutex<HashSet<PublicKey>>,
 }
 
 impl TestChannelMessageHandler {
@@ -312,6 +339,7 @@ impl TestChannelMessageHandler {
                TestChannelMessageHandler {
                        pending_events: Mutex::new(Vec::new()),
                        expected_recv_msgs: Mutex::new(None),
+                       connected_peers: Mutex::new(HashSet::new()),
                }
        }
 
@@ -396,8 +424,11 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
        fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, msg: &msgs::ChannelReestablish) {
                self.received_msg(wire::Message::ChannelReestablish(msg.clone()));
        }
-       fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
-       fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) -> Result<(), ()> {
+       fn peer_disconnected(&self, their_node_id: &PublicKey) {
+               assert!(self.connected_peers.lock().unwrap().remove(their_node_id));
+       }
+       fn peer_connected(&self, their_node_id: &PublicKey, _msg: &msgs::Init, _inbound: bool) -> Result<(), ()> {
+               assert!(self.connected_peers.lock().unwrap().insert(their_node_id.clone()));
                // Don't bother with `received_msg` for Init as its auto-generated and we don't want to
                // bother re-generating the expected Init message in all tests.
                Ok(())
@@ -434,10 +465,10 @@ fn get_dummy_channel_announcement(short_chan_id: u64) -> msgs::ChannelAnnounceme
                features: ChannelFeatures::empty(),
                chain_hash: genesis_block(network).header.block_hash(),
                short_channel_id: short_chan_id,
-               node_id_1: PublicKey::from_secret_key(&secp_ctx, &node_1_privkey),
-               node_id_2: PublicKey::from_secret_key(&secp_ctx, &node_2_privkey),
-               bitcoin_key_1: PublicKey::from_secret_key(&secp_ctx, &node_1_btckey),
-               bitcoin_key_2: PublicKey::from_secret_key(&secp_ctx, &node_2_btckey),
+               node_id_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_privkey)),
+               node_id_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_privkey)),
+               bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_btckey)),
+               bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_btckey)),
                excess_data: Vec::new(),
        };
 
@@ -509,11 +540,11 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler {
                Some((chan_ann, Some(chan_upd_1), Some(chan_upd_2)))
        }
 
-       fn get_next_node_announcement(&self, _starting_point: Option<&PublicKey>) -> Option<msgs::NodeAnnouncement> {
+       fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option<msgs::NodeAnnouncement> {
                None
        }
 
-       fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init) -> Result<(), ()> {
+       fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init, _inbound: bool) -> Result<(), ()> {
                if !init_msg.features.supports_gossip_queries() {
                        return Ok(());
                }
@@ -569,6 +600,8 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler {
                features.set_gossip_queries_optional();
                features
        }
+
+       fn processing_queue_high(&self) -> bool { false }
 }
 
 impl events::MessageSendEventsProvider for TestRoutingMessageHandler {
@@ -837,7 +870,8 @@ impl core::fmt::Debug for OnGetShutdownScriptpubkey {
 
 pub struct TestChainSource {
        pub genesis_hash: BlockHash,
-       pub utxo_ret: Mutex<Result<TxOut, chain::AccessError>>,
+       pub utxo_ret: Mutex<UtxoResult>,
+       pub get_utxo_call_count: AtomicUsize,
        pub watched_txn: Mutex<HashSet<(Txid, Script)>>,
        pub watched_outputs: Mutex<HashSet<(OutPoint, Script)>>,
 }
@@ -847,17 +881,19 @@ impl TestChainSource {
                let script_pubkey = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
                Self {
                        genesis_hash: genesis_block(network).block_hash(),
-                       utxo_ret: Mutex::new(Ok(TxOut { value: u64::max_value(), script_pubkey })),
+                       utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: u64::max_value(), script_pubkey }))),
+                       get_utxo_call_count: AtomicUsize::new(0),
                        watched_txn: Mutex::new(HashSet::new()),
                        watched_outputs: Mutex::new(HashSet::new()),
                }
        }
 }
 
-impl chain::Access for TestChainSource {
-       fn get_utxo(&self, genesis_hash: &BlockHash, _short_channel_id: u64) -> Result<TxOut, chain::AccessError> {
+impl UtxoLookup for TestChainSource {
+       fn get_utxo(&self, genesis_hash: &BlockHash, _short_channel_id: u64) -> UtxoResult {
+               self.get_utxo_call_count.fetch_add(1, Ordering::Relaxed);
                if self.genesis_hash != *genesis_hash {
-                       return Err(chain::AccessError::UnknownChain);
+                       return UtxoResult::Sync(Err(UtxoLookupError::UnknownChain));
                }
 
                self.utxo_ret.lock().unwrap().clone()
@@ -882,5 +918,65 @@ impl Drop for TestChainSource {
        }
 }
 
-/// A scorer useful in testing, when the passage of time isn't a concern.
-pub type TestScorer = FixedPenaltyScorer;
+pub struct TestScorer {
+       /// Stores a tuple of (scid, ChannelUsage)
+       scorer_expectations: RefCell<Option<VecDeque<(u64, ChannelUsage)>>>,
+}
+
+impl TestScorer {
+       pub fn new() -> Self {
+               Self {
+                       scorer_expectations: RefCell::new(None),
+               }
+       }
+
+       pub fn expect_usage(&self, scid: u64, expectation: ChannelUsage) {
+               self.scorer_expectations.borrow_mut().get_or_insert_with(|| VecDeque::new()).push_back((scid, expectation));
+       }
+}
+
+#[cfg(c_bindings)]
+impl crate::util::ser::Writeable for TestScorer {
+       fn write<W: crate::util::ser::Writer>(&self, _: &mut W) -> Result<(), crate::io::Error> { unreachable!(); }
+}
+
+impl Score for TestScorer {
+       fn channel_penalty_msat(
+               &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage
+       ) -> u64 {
+               if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
+                       match scorer_expectations.pop_front() {
+                               Some((scid, expectation)) => {
+                                       assert_eq!(expectation, usage);
+                                       assert_eq!(scid, short_channel_id);
+                               },
+                               None => {},
+                       }
+               }
+               0
+       }
+
+       fn payment_path_failed(&mut self, _actual_path: &[&RouteHop], _actual_short_channel_id: u64) {}
+
+       fn payment_path_successful(&mut self, _actual_path: &[&RouteHop]) {}
+
+       fn probe_failed(&mut self, _actual_path: &[&RouteHop], _: u64) {}
+
+       fn probe_successful(&mut self, _actual_path: &[&RouteHop]) {}
+}
+
+impl Drop for TestScorer {
+       fn drop(&mut self) {
+               #[cfg(feature = "std")] {
+                       if std::thread::panicking() {
+                               return;
+                       }
+               }
+
+               if let Some(scorer_expectations) = self.scorer_expectations.borrow().as_ref() {
+                       if !scorer_expectations.is_empty() {
+                               panic!("Unsatisfied scorer expectations: {:?}", scorer_expectations)
+                       }
+               }
+       }
+}