Merge pull request #1615 from TheBlueMatt/2022-07-screw-dependabot
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Thu, 14 Jul 2022 00:53:17 +0000 (00:53 +0000)
committerGitHub <noreply@github.com>
Thu, 14 Jul 2022 00:53:17 +0000 (00:53 +0000)
Rip out dependabot - its worse than useless - its annoying

61 files changed:
CHANGELOG.md
SECURITY.md [new file with mode: 0644]
fuzz/src/bin/gen_target.sh
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/msg_targets/gen_target.sh
fuzz/src/msg_targets/mod.rs
fuzz/src/msg_targets/msg_accept_channel.rs
fuzz/src/msg_targets/msg_announcement_signatures.rs
fuzz/src/msg_targets/msg_channel_announcement.rs
fuzz/src/msg_targets/msg_channel_details.rs [new file with mode: 0644]
fuzz/src/msg_targets/msg_channel_ready.rs
fuzz/src/msg_targets/msg_channel_reestablish.rs
fuzz/src/msg_targets/msg_channel_update.rs
fuzz/src/msg_targets/msg_closing_signed.rs
fuzz/src/msg_targets/msg_commitment_signed.rs
fuzz/src/msg_targets/msg_decoded_onion_error_packet.rs
fuzz/src/msg_targets/msg_error_message.rs
fuzz/src/msg_targets/msg_funding_created.rs
fuzz/src/msg_targets/msg_funding_signed.rs
fuzz/src/msg_targets/msg_gossip_timestamp_filter.rs
fuzz/src/msg_targets/msg_init.rs
fuzz/src/msg_targets/msg_node_announcement.rs
fuzz/src/msg_targets/msg_onion_hop_data.rs
fuzz/src/msg_targets/msg_open_channel.rs
fuzz/src/msg_targets/msg_ping.rs
fuzz/src/msg_targets/msg_pong.rs
fuzz/src/msg_targets/msg_query_channel_range.rs
fuzz/src/msg_targets/msg_query_short_channel_ids.rs
fuzz/src/msg_targets/msg_reply_channel_range.rs
fuzz/src/msg_targets/msg_reply_short_channel_ids_end.rs
fuzz/src/msg_targets/msg_revoke_and_ack.rs
fuzz/src/msg_targets/msg_shutdown.rs
fuzz/src/msg_targets/msg_target_template.txt
fuzz/src/msg_targets/msg_update_add_htlc.rs
fuzz/src/msg_targets/msg_update_fail_htlc.rs
fuzz/src/msg_targets/msg_update_fail_malformed_htlc.rs
fuzz/src/msg_targets/msg_update_fee.rs
fuzz/src/msg_targets/msg_update_fulfill_htlc.rs
fuzz/src/msg_targets/msg_warning_message.rs
fuzz/src/process_network_graph.rs
fuzz/src/router.rs
fuzz/targets.h
lightning-invoice/src/payment.rs
lightning/src/chain/chaininterface.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/onchaintx.rs
lightning/src/chain/package.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/mod.rs
lightning/src/ln/msgs.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/reorg_tests.rs
lightning/src/routing/router.rs
lightning/src/routing/scoring.rs
lightning/src/util/config.rs
lightning/src/util/events.rs
lightning/src/util/ser.rs
lightning/src/util/ser_macros.rs

index 5d49d0ef2a4df0c802ad38d2eb9e9216d656cbb7..961b1121196a94b76f0fac5ec76c1613d83858c0 100644 (file)
@@ -1,4 +1,4 @@
-# 0.0.109 - 2022-06-30
+# 0.0.109 - 2022-07-01
 
 ## API Updates
  * `ChannelManager::update_channel_config` has been added to allow the fields
@@ -14,6 +14,9 @@
    option to prefer channels which afford better privacy when routing (#1555).
  * `ProbabilisticScorer` now provides access to its estimated liquidity range
    for a given channel via `estimated_channel_liquidity_range` (#1549).
+ * `ChannelManager::force_close_channel` has been renamed
+   `force_close_broadcasting_latest_txn` and
+   `force_close_without_broadcasting_txn` has been added (#1564).
  * Options which cannot be changed at runtime have been moved from
    `ChannelConfig` to `ChannelHandshakeConfig` (#1529).
  * `find_route` takes `&NetworkGraph` instead of `ReadOnlyNetworkGraph (#1583).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644 (file)
index 0000000..d4b33ec
--- /dev/null
@@ -0,0 +1,20 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+Please report security vulnerabilities, including denial-of-service
+vulnerabilities such as spurious panics, via email to
+security@lightningdevkit.org.
+
+If possible, please PGP-encrypt such emails to the following keys (available on
+keyservers and WKD via `gpg --auto-key-locate wkd  --locate-external-keys
+ldk-security-1@mattcorallo.com ldk-security-2@mattcorallo.com`). Please include
+your own public key as an attachment or inline for replies.
+
+ * 07DF3E57A548CCFB7530709189BBB8663E2E65CE (Matt Corallo)
+ * 5DBC576CCCF546CA72AB06CE912EF12EA67705F5 (Jeffrey Czyz)
+ * 729E9D9D92C75A5FBFEEE057B5DD717BEF7CA5B1 (Wilmer Paulino)
+ * BD6EED4D339EDBF7E7CE7F8836153082BDF676FD (Elias Rohrer)
+ * 6E0287D8849AE741E47CC586FD3E106A2CE099B4 (Valentine Wallace)
+ * 69CFEA635D0E6E6F13FD9D9136D932FCAC0305F0 (Arik Sosman)
+ * A5A6868D7AA91DD00AC1A67F817FFA028EF61C94 (Antoine Riard)
index b88b72503779d72854fbbb213a77b0f82e474336..c0daa5a3a0f36abfb9b898438a0641135302c770 100755 (executable)
@@ -47,3 +47,5 @@ GEN_TEST msg_channel_update msg_targets::
 GEN_TEST msg_onion_hop_data msg_targets::
 GEN_TEST msg_ping msg_targets::
 GEN_TEST msg_pong msg_targets::
+
+GEN_TEST msg_channel_details msg_targets::
index 615f3aad995ce054d9b073923bf31e23725b7bef..9d5ccaa8105e954a541ef1e19fa83ff26c148b83 100644 (file)
@@ -850,6 +850,12 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
                                                events::Event::PaymentClaimed { .. } => {},
                                                events::Event::PaymentPathSuccessful { .. } => {},
                                                events::Event::PaymentPathFailed { .. } => {},
+                                               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
+                                                       // trivial for the fuzzer to build payments that accidentally end up
+                                                       // looking like probes.
+                                               },
                                                events::Event::PaymentForwarded { .. } if $node == 1 => {},
                                                events::Event::PendingHTLCsForwardable { .. } => {
                                                        nodes[$node].process_pending_htlc_forwards();
index b4ca316ed0dbba1f695a913e747239dca3ffef90..fa0211aa280bc0794fa37f67d53332b1793d3129 100644 (file)
@@ -393,7 +393,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
        // Adding new calls to `KeysInterface::get_secure_random_bytes` during startup can change all the
        // keys subsequently generated in this test. Rather than regenerating all the messages manually,
        // it's easier to just increment the counter here so the keys don't change.
-       keys_manager.counter.fetch_sub(1, Ordering::AcqRel);
+       keys_manager.counter.fetch_sub(2, Ordering::AcqRel);
        let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret(Recipient::Node).unwrap());
        let network_graph = Arc::new(NetworkGraph::new(genesis_block(network).block_hash(), Arc::clone(&logger)));
        let gossip_sync = Arc::new(P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger)));
index 848793db50082b20cbe1c520dd430bde30466140..753a98325a4c37713ee8ecaa837dfb85d30869d4 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GEN_TEST() {
-       tn=msg_$(echo $1 | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g' | tr '[:upper:]' '[:lower:]')
+       tn=msg_$(echo $1 | sed s'/.*:://g' | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g' | tr '[:upper:]' '[:lower:]')
        fn=${tn}.rs
        cat msg_target_template.txt | sed s/MSG_TARGET/$1/ | sed "s/TARGET_NAME/$tn/" | sed "s/TEST_MSG/$2/" | sed "s/EXTRA_ARGS/$3/" > $fn
        echo "pub mod $tn;" >> mod.rs
@@ -11,37 +11,39 @@ echo "mod utils;" > mod.rs
 
 # Note when adding new targets here you should add a similar line in src/bin/gen_target.sh
 
-GEN_TEST AcceptChannel test_msg_simple ""
-GEN_TEST AnnouncementSignatures test_msg_simple ""
-GEN_TEST ClosingSigned test_msg_simple ""
-GEN_TEST CommitmentSigned test_msg_simple ""
-GEN_TEST FundingCreated test_msg_simple ""
-GEN_TEST ChannelReady test_msg_simple ""
-GEN_TEST FundingSigned test_msg_simple ""
-GEN_TEST GossipTimestampFilter test_msg_simple ""
-GEN_TEST Init test_msg_simple ""
-GEN_TEST OnionHopData test_msg_simple ""
-GEN_TEST OpenChannel test_msg_simple ""
-GEN_TEST Ping test_msg_simple ""
-GEN_TEST Pong test_msg_simple ""
-GEN_TEST QueryChannelRange test_msg_simple ""
-GEN_TEST ReplyShortChannelIdsEnd test_msg_simple ""
-GEN_TEST RevokeAndACK test_msg_simple ""
-GEN_TEST Shutdown test_msg_simple ""
-GEN_TEST UpdateAddHTLC test_msg_simple ""
-GEN_TEST UpdateFailHTLC test_msg_simple ""
-GEN_TEST UpdateFailMalformedHTLC test_msg_simple ""
-GEN_TEST UpdateFee test_msg_simple ""
-GEN_TEST UpdateFulfillHTLC test_msg_simple ""
-
-GEN_TEST ChannelReestablish test_msg ""
-GEN_TEST DecodedOnionErrorPacket test_msg ""
-
-GEN_TEST ChannelAnnouncement test_msg_exact ""
-GEN_TEST NodeAnnouncement test_msg_exact ""
-GEN_TEST QueryShortChannelIds test_msg ""
-GEN_TEST ReplyChannelRange test_msg ""
-
-GEN_TEST ErrorMessage test_msg_hole ", 32, 2"
-GEN_TEST WarningMessage test_msg_hole ", 32, 2"
-GEN_TEST ChannelUpdate test_msg_hole ", 108, 1"
+GEN_TEST lightning::ln::msgs::AcceptChannel test_msg_simple ""
+GEN_TEST lightning::ln::msgs::AnnouncementSignatures test_msg_simple ""
+GEN_TEST lightning::ln::msgs::ClosingSigned test_msg_simple ""
+GEN_TEST lightning::ln::msgs::CommitmentSigned test_msg_simple ""
+GEN_TEST lightning::ln::msgs::FundingCreated test_msg_simple ""
+GEN_TEST lightning::ln::msgs::ChannelReady test_msg_simple ""
+GEN_TEST lightning::ln::msgs::FundingSigned test_msg_simple ""
+GEN_TEST lightning::ln::msgs::GossipTimestampFilter test_msg_simple ""
+GEN_TEST lightning::ln::msgs::Init test_msg_simple ""
+GEN_TEST lightning::ln::msgs::OnionHopData test_msg_simple ""
+GEN_TEST lightning::ln::msgs::OpenChannel test_msg_simple ""
+GEN_TEST lightning::ln::msgs::Ping test_msg_simple ""
+GEN_TEST lightning::ln::msgs::Pong test_msg_simple ""
+GEN_TEST lightning::ln::msgs::QueryChannelRange test_msg_simple ""
+GEN_TEST lightning::ln::msgs::ReplyShortChannelIdsEnd test_msg_simple ""
+GEN_TEST lightning::ln::msgs::RevokeAndACK test_msg_simple ""
+GEN_TEST lightning::ln::msgs::Shutdown test_msg_simple ""
+GEN_TEST lightning::ln::msgs::UpdateAddHTLC test_msg_simple ""
+GEN_TEST lightning::ln::msgs::UpdateFailHTLC test_msg_simple ""
+GEN_TEST lightning::ln::msgs::UpdateFailMalformedHTLC test_msg_simple ""
+GEN_TEST lightning::ln::msgs::UpdateFee test_msg_simple ""
+GEN_TEST lightning::ln::msgs::UpdateFulfillHTLC test_msg_simple ""
+
+GEN_TEST lightning::ln::msgs::ChannelReestablish test_msg ""
+GEN_TEST lightning::ln::msgs::DecodedOnionErrorPacket test_msg ""
+
+GEN_TEST lightning::ln::msgs::ChannelAnnouncement test_msg_exact ""
+GEN_TEST lightning::ln::msgs::NodeAnnouncement test_msg_exact ""
+GEN_TEST lightning::ln::msgs::QueryShortChannelIds test_msg ""
+GEN_TEST lightning::ln::msgs::ReplyChannelRange test_msg ""
+
+GEN_TEST lightning::ln::msgs::ErrorMessage test_msg_hole ", 32, 2"
+GEN_TEST lightning::ln::msgs::WarningMessage test_msg_hole ", 32, 2"
+GEN_TEST lightning::ln::msgs::ChannelUpdate test_msg_hole ", 108, 1"
+
+GEN_TEST lightning::ln::channelmanager::ChannelDetails test_msg_simple ""
index dd1540ce51ec51f21c3bdc28fed92d31bd194127..67d66e23f5da8635a9c3d8e78e11358b71563a7f 100644 (file)
@@ -30,3 +30,4 @@ pub mod msg_reply_channel_range;
 pub mod msg_error_message;
 pub mod msg_warning_message;
 pub mod msg_channel_update;
+pub mod msg_channel_details;
index a8ec438784bca1a4c6d4fae28d5d9fd2b735ce5f..1732bf2f791073077265b9e287a521652381367f 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_accept_channel_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::AcceptChannel, data);
+       test_msg_simple!(lightning::ln::msgs::AcceptChannel, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_accept_channel_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::AcceptChannel, data);
+       test_msg_simple!(lightning::ln::msgs::AcceptChannel, data);
 }
index 0fc40fcb69bd7353a1a261370f81fccf166c3c32..15e4e6d8044fb4fcdc3fcf16d0ab0d8216d70298 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_announcement_signatures_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::AnnouncementSignatures, data);
+       test_msg_simple!(lightning::ln::msgs::AnnouncementSignatures, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_announcement_signatures_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::AnnouncementSignatures, data);
+       test_msg_simple!(lightning::ln::msgs::AnnouncementSignatures, data);
 }
index 53ffe0eff76996237476fb14e7c107e8d5c1ada7..7a36520fb2f602f14d3b71abb9f0a9f58915e2a5 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_channel_announcement_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_exact!(msgs::ChannelAnnouncement, data);
+       test_msg_exact!(lightning::ln::msgs::ChannelAnnouncement, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_channel_announcement_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_exact!(msgs::ChannelAnnouncement, data);
+       test_msg_exact!(lightning::ln::msgs::ChannelAnnouncement, data);
 }
diff --git a/fuzz/src/msg_targets/msg_channel_details.rs b/fuzz/src/msg_targets/msg_channel_details.rs
new file mode 100644 (file)
index 0000000..f448a71
--- /dev/null
@@ -0,0 +1,25 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This file is auto-generated by gen_target.sh based on msg_target_template.txt
+// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+
+use msg_targets::utils::VecWriter;
+use utils::test_logger;
+
+#[inline]
+pub fn msg_channel_details_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
+       test_msg_simple!(lightning::ln::channelmanager::ChannelDetails, data);
+}
+
+#[no_mangle]
+pub extern "C" fn msg_channel_details_run(data: *const u8, datalen: usize) {
+       let data = unsafe { std::slice::from_raw_parts(data, datalen) };
+       test_msg_simple!(lightning::ln::channelmanager::ChannelDetails, data);
+}
index e5f3b25c691ab87fb7d242787450eb9d958bc21e..d95a86004fa7c2ee591a5a1bf2392946380b683f 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_channel_ready_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::ChannelReady, data);
+       test_msg_simple!(lightning::ln::msgs::ChannelReady, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_channel_ready_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::ChannelReady, data);
+       test_msg_simple!(lightning::ln::msgs::ChannelReady, data);
 }
index 7316bfbdf801dad578db052af768889022ab1632..2b934c00c294a8e141ec7bc5a3bb2b5f3abb2bdf 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_channel_reestablish_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg!(msgs::ChannelReestablish, data);
+       test_msg!(lightning::ln::msgs::ChannelReestablish, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_channel_reestablish_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg!(msgs::ChannelReestablish, data);
+       test_msg!(lightning::ln::msgs::ChannelReestablish, data);
 }
index 1cd9ddbbfe01e2532900e6dd24b70048518e3b6e..7c7822e659513b28ce9ed17a082cd440cf2450b7 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_channel_update_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_hole!(msgs::ChannelUpdate, data, 108, 1);
+       test_msg_hole!(lightning::ln::msgs::ChannelUpdate, data, 108, 1);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_channel_update_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_hole!(msgs::ChannelUpdate, data, 108, 1);
+       test_msg_hole!(lightning::ln::msgs::ChannelUpdate, data, 108, 1);
 }
index 52f39af29a98f82150d6150493065c7b942cebe0..f494acf62a7db8251e5bc98716945131c2c2ede5 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_closing_signed_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::ClosingSigned, data);
+       test_msg_simple!(lightning::ln::msgs::ClosingSigned, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_closing_signed_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::ClosingSigned, data);
+       test_msg_simple!(lightning::ln::msgs::ClosingSigned, data);
 }
index 163ce74460678cc6365cc2f94ccf11b70252e31d..63c38ce8e54e022c7e0efb25b675bdb5f49d6ec8 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_commitment_signed_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::CommitmentSigned, data);
+       test_msg_simple!(lightning::ln::msgs::CommitmentSigned, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_commitment_signed_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::CommitmentSigned, data);
+       test_msg_simple!(lightning::ln::msgs::CommitmentSigned, data);
 }
index 92fb532e643932541cd3323eb454004248c74db8..af4963245b4bb7df6d11f524692ad595357f7f55 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_decoded_onion_error_packet_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg!(msgs::DecodedOnionErrorPacket, data);
+       test_msg!(lightning::ln::msgs::DecodedOnionErrorPacket, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_decoded_onion_error_packet_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg!(msgs::DecodedOnionErrorPacket, data);
+       test_msg!(lightning::ln::msgs::DecodedOnionErrorPacket, data);
 }
index 7fba2c4dc8e9366e2d6b74138faa5bbde7bafc6d..4a70074043fc27ecd40e266f3d74c4755676b971 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_error_message_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_hole!(msgs::ErrorMessage, data, 32, 2);
+       test_msg_hole!(lightning::ln::msgs::ErrorMessage, data, 32, 2);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_error_message_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_hole!(msgs::ErrorMessage, data, 32, 2);
+       test_msg_hole!(lightning::ln::msgs::ErrorMessage, data, 32, 2);
 }
index e0005cb082a4523d181fb94b344afe900a86d8fb..7fad86e743085016362a378e91f896780fc3b7a6 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_funding_created_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::FundingCreated, data);
+       test_msg_simple!(lightning::ln::msgs::FundingCreated, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_funding_created_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::FundingCreated, data);
+       test_msg_simple!(lightning::ln::msgs::FundingCreated, data);
 }
index f0586e7b294a06b48200f304c35c51eb98160e51..82886d6393af85183778ad9be722309708b99f1e 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_funding_signed_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::FundingSigned, data);
+       test_msg_simple!(lightning::ln::msgs::FundingSigned, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_funding_signed_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::FundingSigned, data);
+       test_msg_simple!(lightning::ln::msgs::FundingSigned, data);
 }
index 448aaffc90c2b88432500cf6b08ea5143e0d61e1..5c14a24162d62aa2ccd22534e9c0af7b94d551f9 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_gossip_timestamp_filter_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::GossipTimestampFilter, data);
+       test_msg_simple!(lightning::ln::msgs::GossipTimestampFilter, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_gossip_timestamp_filter_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::GossipTimestampFilter, data);
+       test_msg_simple!(lightning::ln::msgs::GossipTimestampFilter, data);
 }
index 4aa5c4a3143235ee9bfa817d48c17db63b5c2e17..efa53a473e97030ce6ecde031d8e0a891527ecf7 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_init_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::Init, data);
+       test_msg_simple!(lightning::ln::msgs::Init, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_init_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::Init, data);
+       test_msg_simple!(lightning::ln::msgs::Init, data);
 }
index 8f5751b9a01f0ec4aeaf16b8d82e0dbb82df1750..57c05145fc8f99c6c3476a62b43b0414a0aabd8b 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_node_announcement_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_exact!(msgs::NodeAnnouncement, data);
+       test_msg_exact!(lightning::ln::msgs::NodeAnnouncement, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_node_announcement_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_exact!(msgs::NodeAnnouncement, data);
+       test_msg_exact!(lightning::ln::msgs::NodeAnnouncement, data);
 }
index 757f316190cfa5b1bc57c9760372c9f123e01c1f..d73523dc15315fefa78edfbb70bd908f2a01652b 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_onion_hop_data_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::OnionHopData, data);
+       test_msg_simple!(lightning::ln::msgs::OnionHopData, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_onion_hop_data_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::OnionHopData, data);
+       test_msg_simple!(lightning::ln::msgs::OnionHopData, data);
 }
index ce637c167efe20f83253ca7b5c39d969e5c88441..2508fa353bb58806c9c802291541d832b121e92d 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_open_channel_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::OpenChannel, data);
+       test_msg_simple!(lightning::ln::msgs::OpenChannel, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_open_channel_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::OpenChannel, data);
+       test_msg_simple!(lightning::ln::msgs::OpenChannel, data);
 }
index 7b44ae1804ddb6fb4d3e38b8b2a28e75d4db8da1..36d4d0d8ae258b9ee353934af8fc7e41846dda93 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_ping_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::Ping, data);
+       test_msg_simple!(lightning::ln::msgs::Ping, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_ping_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::Ping, data);
+       test_msg_simple!(lightning::ln::msgs::Ping, data);
 }
index cff4a54fac291300b46dbdb394f97232dc4878bb..ea8a1bdd8aa5f5851200a918f78a6509d503a79c 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_pong_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::Pong, data);
+       test_msg_simple!(lightning::ln::msgs::Pong, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_pong_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::Pong, data);
+       test_msg_simple!(lightning::ln::msgs::Pong, data);
 }
index 4b3de6aa895b151a6817acdbff939ac4598329ee..75a2f042a32945c96c086e70a589170a9763a9a5 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_query_channel_range_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::QueryChannelRange, data);
+       test_msg_simple!(lightning::ln::msgs::QueryChannelRange, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_query_channel_range_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::QueryChannelRange, data);
+       test_msg_simple!(lightning::ln::msgs::QueryChannelRange, data);
 }
index 99cde111751b3a22fd76ac4b8ec9ecfdc194df27..f536c7f4f360bca71ad360189f465efd8d161db2 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_query_short_channel_ids_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg!(msgs::QueryShortChannelIds, data);
+       test_msg!(lightning::ln::msgs::QueryShortChannelIds, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_query_short_channel_ids_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg!(msgs::QueryShortChannelIds, data);
+       test_msg!(lightning::ln::msgs::QueryShortChannelIds, data);
 }
index d23b58a2db8f7656e5fb7d32010334c0656ee004..0fd0ed6340c649994fd1adc06da4a0e6d4478db6 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_reply_channel_range_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg!(msgs::ReplyChannelRange, data);
+       test_msg!(lightning::ln::msgs::ReplyChannelRange, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_reply_channel_range_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg!(msgs::ReplyChannelRange, data);
+       test_msg!(lightning::ln::msgs::ReplyChannelRange, data);
 }
index 7634329a435a7d995aa3a52fd87e11744b8b6369..712bb3ac478a9a8a911dcb804cc17db1182b2e9b 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_reply_short_channel_ids_end_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::ReplyShortChannelIdsEnd, data);
+       test_msg_simple!(lightning::ln::msgs::ReplyShortChannelIdsEnd, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_reply_short_channel_ids_end_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::ReplyShortChannelIdsEnd, data);
+       test_msg_simple!(lightning::ln::msgs::ReplyShortChannelIdsEnd, data);
 }
index 873939ca7c9d85b34c1d8cf15eb33f707adaec77..cd3e64c36db6d02c53a688bb1042d6440a18159c 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_revoke_and_ack_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::RevokeAndACK, data);
+       test_msg_simple!(lightning::ln::msgs::RevokeAndACK, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_revoke_and_ack_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::RevokeAndACK, data);
+       test_msg_simple!(lightning::ln::msgs::RevokeAndACK, data);
 }
index e6e74cc661a9c5c586cb98793281a42f7a3e1fd7..465d1e39ebf241b09fc8c3ae76b97247265803ff 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_shutdown_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::Shutdown, data);
+       test_msg_simple!(lightning::ln::msgs::Shutdown, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_shutdown_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::Shutdown, data);
+       test_msg_simple!(lightning::ln::msgs::Shutdown, data);
 }
index ebe832d59ba88f7faae6c6b1b72d49f6e811558e..14580183e5968f330f7d6f8e833b5ec7e1d9adf6 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn TARGET_NAME_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       TEST_MSG!(msgs::MSG_TARGET, dataEXTRA_ARGS);
+       TEST_MSG!(MSG_TARGET, dataEXTRA_ARGS);
 }
 
 #[no_mangle]
 pub extern "C" fn TARGET_NAME_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       TEST_MSG!(msgs::MSG_TARGET, dataEXTRA_ARGS);
+       TEST_MSG!(MSG_TARGET, dataEXTRA_ARGS);
 }
index 409f0fac8dff62e7f097ba6fad7a279230c29181..f031a4d89e904d01645406c2eddcb120d6e85dff 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_update_add_htlc_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::UpdateAddHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateAddHTLC, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_update_add_htlc_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::UpdateAddHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateAddHTLC, data);
 }
index 12d3f1c3fc3f0697d0cb0b5f130afa566fa7fca6..8d9dfedfcf8a8fa99f726637543f63e0df1d4e2d 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_update_fail_htlc_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::UpdateFailHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFailHTLC, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_update_fail_htlc_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::UpdateFailHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFailHTLC, data);
 }
index 0b36070d1e59d6d5076ef6e4579c1ba92290cc25..2635a4cb6a34fef8339529a2679ba632d831528d 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_update_fail_malformed_htlc_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::UpdateFailMalformedHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFailMalformedHTLC, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_update_fail_malformed_htlc_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::UpdateFailMalformedHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFailMalformedHTLC, data);
 }
index 3c23a902f5723dab1fef5cc3fe2e7a01aee2a52b..b891a363198c54e9b2e4c48db1f8b489317532a4 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_update_fee_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::UpdateFee, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFee, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_update_fee_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::UpdateFee, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFee, data);
 }
index 460ff0e167880a6771804c0a19213233575ef4c8..a96aa3729a30dc705be1b816bae91bf348d2ded3 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_update_fulfill_htlc_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_simple!(msgs::UpdateFulfillHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFulfillHTLC, data);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_update_fulfill_htlc_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_simple!(msgs::UpdateFulfillHTLC, data);
+       test_msg_simple!(lightning::ln::msgs::UpdateFulfillHTLC, data);
 }
index f033b6fd6e989ac119173fd0145cad370485a4ea..abcef229bd33f3c1afc13174ce0381c5b7406b5d 100644 (file)
 // This file is auto-generated by gen_target.sh based on msg_target_template.txt
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
-use lightning::ln::msgs;
-
 use msg_targets::utils::VecWriter;
 use utils::test_logger;
 
 #[inline]
 pub fn msg_warning_message_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_hole!(msgs::WarningMessage, data, 32, 2);
+       test_msg_hole!(lightning::ln::msgs::WarningMessage, data, 32, 2);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_warning_message_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_hole!(msgs::WarningMessage, data, 32, 2);
+       test_msg_hole!(lightning::ln::msgs::WarningMessage, data, 32, 2);
 }
index 8b6462e81e48c95ab30d3db7409b3c63a18be28a..d649710526ad77f43e8c5dc969a6cdbdca7dd382 100644 (file)
@@ -1,11 +1,8 @@
 // Imports that need to be added manually
-use lightning::util::logger::Logger;
 use lightning_rapid_gossip_sync::RapidGossipSync;
 
 use utils::test_logger;
 
-use std::sync::Arc;
-
 /// Actual fuzz test, method signature and name are fixed
 fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
        let block_hash = bitcoin::BlockHash::default();
index 5dc158053b7bdfa4a10e3a465314223b542180cf..9a11935cad6d1fdcee64a5d983211be802d7ae3e 100644 (file)
@@ -19,7 +19,6 @@ use lightning::ln::msgs;
 use lightning::routing::gossip::{NetworkGraph, RoutingFees};
 use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
 use lightning::routing::scoring::FixedPenaltyScorer;
-use lightning::util::logger::Logger;
 use lightning::util::ser::Readable;
 
 use bitcoin::hashes::Hash;
index d142aa6487eb36e8e436457be951d84771162f8f..7958a6f614d817ee6783e3d4a7c175912204d15c 100644 (file)
@@ -36,3 +36,4 @@ void msg_channel_update_run(const unsigned char* data, size_t data_len);
 void msg_onion_hop_data_run(const unsigned char* data, size_t data_len);
 void msg_ping_run(const unsigned char* data, size_t data_len);
 void msg_pong_run(const unsigned char* data, size_t data_len);
+void msg_channel_details_run(const unsigned char* data, size_t data_len);
index e672b89c919c4aefaa6cb1c7bb6074bf54059941..051893ea0a3a5c9ce0405045e828644928f5c8d0 100644 (file)
@@ -94,6 +94,8 @@
 //! #     ) -> 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 {}
@@ -584,6 +586,18 @@ where
                                        .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.scorer.lock().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.scorer.lock().probe_failed(&path, *short_channel_id);
+                               }
+                       },
                        _ => {},
                }
 
@@ -1296,7 +1310,7 @@ mod tests {
                        .expect_send(Amount::ForInvoice(final_value_msat))
                        .expect_send(Amount::OnRetry(final_value_msat / 2));
                let router = TestRouter {};
-               let scorer = RefCell::new(TestScorer::new().expect(PaymentPath::Failure {
+               let scorer = RefCell::new(TestScorer::new().expect(TestResult::PaymentFailure {
                        path: path.clone(), short_channel_id: path[0].short_channel_id,
                }));
                let logger = TestLogger::new();
@@ -1332,8 +1346,8 @@ mod tests {
                let payer = TestPayer::new().expect_send(Amount::ForInvoice(final_value_msat));
                let router = TestRouter {};
                let scorer = RefCell::new(TestScorer::new()
-                       .expect(PaymentPath::Success { path: route.paths[0].clone() })
-                       .expect(PaymentPath::Success { path: route.paths[1].clone() })
+                       .expect(TestResult::PaymentSuccess { path: route.paths[0].clone() })
+                       .expect(TestResult::PaymentSuccess { path: route.paths[1].clone() })
                );
                let logger = TestLogger::new();
                let invoice_payer =
@@ -1416,13 +1430,15 @@ mod tests {
        }
 
        struct TestScorer {
-               expectations: Option<VecDeque<PaymentPath>>,
+               expectations: Option<VecDeque<TestResult>>,
        }
 
        #[derive(Debug)]
-       enum PaymentPath {
-               Failure { path: Vec<RouteHop>, short_channel_id: u64 },
-               Success { path: Vec<RouteHop> },
+       enum TestResult {
+               PaymentFailure { path: Vec<RouteHop>, short_channel_id: u64 },
+               PaymentSuccess { path: Vec<RouteHop> },
+               ProbeFailure { path: Vec<RouteHop>, short_channel_id: u64 },
+               ProbeSuccess { path: Vec<RouteHop> },
        }
 
        impl TestScorer {
@@ -1432,7 +1448,7 @@ mod tests {
                        }
                }
 
-               fn expect(mut self, expectation: PaymentPath) -> Self {
+               fn expect(mut self, expectation: TestResult) -> Self {
                        self.expectations.get_or_insert_with(|| VecDeque::new()).push_back(expectation);
                        self
                }
@@ -1451,13 +1467,19 @@ mod tests {
                fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
                        if let Some(expectations) = &mut self.expectations {
                                match expectations.pop_front() {
-                                       Some(PaymentPath::Failure { path, short_channel_id }) => {
+                                       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(PaymentPath::Success { path }) => {
+                                       Some(TestResult::PaymentSuccess { path }) => {
                                                panic!("Unexpected successful payment path: {:?}", path)
                                        },
+                                       Some(TestResult::ProbeFailure { path, .. }) => {
+                                               panic!("Unexpected failed payment probe: {:?}", path)
+                                       },
+                                       Some(TestResult::ProbeSuccess { path }) => {
+                                               panic!("Unexpected successful payment probe: {:?}", path)
+                                       },
                                        None => panic!("Unexpected payment_path_failed call: {:?}", actual_path),
                                }
                        }
@@ -1466,10 +1488,56 @@ mod tests {
                fn payment_path_successful(&mut self, actual_path: &[&RouteHop]) {
                        if let Some(expectations) = &mut self.expectations {
                                match expectations.pop_front() {
-                                       Some(PaymentPath::Failure { path, .. }) => {
+                                       Some(TestResult::PaymentFailure { path, .. }) => {
                                                panic!("Unexpected payment path failure: {:?}", path)
                                        },
-                                       Some(PaymentPath::Success { path }) => {
+                                       Some(TestResult::PaymentSuccess { path }) => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                       },
+                                       Some(TestResult::ProbeFailure { path, .. }) => {
+                                               panic!("Unexpected failed payment probe: {:?}", path)
+                                       },
+                                       Some(TestResult::ProbeSuccess { path }) => {
+                                               panic!("Unexpected successful payment probe: {:?}", path)
+                                       },
+                                       None => panic!("Unexpected payment_path_successful call: {:?}", actual_path),
+                               }
+                       }
+               }
+
+               fn probe_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
+                       if let Some(expectations) = &mut self.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)
+                                       },
+                                       Some(TestResult::ProbeFailure { path, short_channel_id }) => {
+                                               assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
+                                               assert_eq!(actual_short_channel_id, short_channel_id);
+                                       },
+                                       Some(TestResult::ProbeSuccess { path }) => {
+                                               panic!("Unexpected successful payment probe: {:?}", path)
+                                       },
+                                       None => panic!("Unexpected payment_path_failed call: {:?}", actual_path),
+                               }
+                       }
+               }
+               fn probe_successful(&mut self, actual_path: &[&RouteHop]) {
+                       if let Some(expectations) = &mut self.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)
+                                       },
+                                       Some(TestResult::ProbeFailure { path, .. }) => {
+                                               panic!("Unexpected failed payment probe: {:?}", path)
+                                       },
+                                       Some(TestResult::ProbeSuccess { path }) => {
                                                assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
                                        },
                                        None => panic!("Unexpected payment_path_successful call: {:?}", actual_path),
index 9a45a88ffe407898e1b38ee42f3356856b7f9cd4..2ec7f318ff57bb5a3e798a0ecd651cc1fb5f4e1d 100644 (file)
@@ -13,6 +13,8 @@
 //! Includes traits for monitoring and receiving notifications of new blocks and block
 //! disconnections, transaction broadcasting, and feerate information requests.
 
+use core::{cmp, ops::Deref};
+
 use bitcoin::blockdata::transaction::Transaction;
 
 /// An interface to send a transaction to the Bitcoin network.
@@ -41,14 +43,79 @@ pub enum ConfirmationTarget {
 pub trait FeeEstimator {
        /// Gets estimated satoshis of fee required per 1000 Weight-Units.
        ///
-       /// Must return a value no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later
-       /// round-downs don't put us below 1 satoshi-per-byte).
+       /// LDK will wrap this method and ensure that the value returned is no smaller than 253
+       /// (ie 1 satoshi-per-byte rounded up to ensure later round-downs don't put us below 1 satoshi-per-byte).
        ///
-       /// This method can be implemented with the following unit conversions:
-       ///  * max(satoshis-per-byte * 250, 253)
-       ///  * max(satoshis-per-kbyte / 4, 253)
+       /// The following unit conversions can be used to convert to sats/KW:
+       ///  * satoshis-per-byte * 250
+       ///  * satoshis-per-kbyte / 4
        fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32;
 }
 
+// We need `FeeEstimator` implemented so that in some places where we only have a shared
+// reference to a `Deref` to a `FeeEstimator`, we can still wrap it.
+impl<D: Deref> FeeEstimator for D where D::Target: FeeEstimator {
+       fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
+               (**self).get_est_sat_per_1000_weight(confirmation_target)
+       }
+}
+
 /// Minimum relay fee as required by bitcoin network mempool policy.
 pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
+/// Minimum feerate that takes a sane approach to bitcoind weight-to-vbytes rounding.
+/// See the following Core Lightning commit for an explanation:
+/// https://github.com/ElementsProject/lightning/commit/2e687b9b352c9092b5e8bd4a688916ac50b44af0
+pub const FEERATE_FLOOR_SATS_PER_KW: u32 = 253;
+
+/// Wraps a `Deref` to a `FeeEstimator` so that any fee estimations provided by it
+/// are bounded below by `FEERATE_FLOOR_SATS_PER_KW` (253 sats/KW)
+pub(crate) struct LowerBoundedFeeEstimator<F: Deref>(pub F) where F::Target: FeeEstimator;
+
+impl<F: Deref> LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
+       /// Creates a new `LowerBoundedFeeEstimator` which wraps the provided fee_estimator
+       pub fn new(fee_estimator: F) -> Self {
+               LowerBoundedFeeEstimator(fee_estimator)
+       }
+}
+
+impl<F: Deref> FeeEstimator for LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
+       fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
+               cmp::max(
+                       self.0.get_est_sat_per_1000_weight(confirmation_target),
+                       FEERATE_FLOOR_SATS_PER_KW,
+               )
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use super::{FEERATE_FLOOR_SATS_PER_KW, LowerBoundedFeeEstimator, ConfirmationTarget, FeeEstimator};
+
+       struct TestFeeEstimator {
+               sat_per_kw: u32,
+       }
+
+       impl FeeEstimator for TestFeeEstimator {
+               fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 {
+                       self.sat_per_kw
+               }
+       }
+
+       #[test]
+       fn test_fee_estimator_less_than_floor() {
+               let sat_per_kw = FEERATE_FLOOR_SATS_PER_KW - 1;
+               let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
+               let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
+
+               assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), FEERATE_FLOOR_SATS_PER_KW);
+       }
+
+       #[test]
+       fn test_fee_estimator_greater_than_floor() {
+               let sat_per_kw = FEERATE_FLOOR_SATS_PER_KW + 1;
+               let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
+               let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
+
+               assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), sat_per_kw);
+       }
+}
index 48f821d5f0cb712292fee1afda7e94e627c85a36..80cd9cb9d45958629e1789513190a4de63b87e7b 100644 (file)
@@ -40,7 +40,7 @@ use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLC
 use ln::channelmanager::HTLCSource;
 use chain;
 use chain::{BestBlock, WatchedOutput};
-use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
+use chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
 use chain::transaction::{OutPoint, TransactionData};
 use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
 use chain::onchaintx::OnchainTxHandler;
@@ -722,6 +722,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
        // the full block_connected).
        best_block: BestBlock,
 
+       /// The node_id of our counterparty
+       counterparty_node_id: Option<PublicKey>,
+
        secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
 }
 
@@ -954,6 +957,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
                        (3, self.htlcs_resolved_on_chain, vec_type),
                        (5, self.pending_monitor_events, vec_type),
                        (7, self.funding_spend_seen, required),
+                       (9, self.counterparty_node_id, option),
                });
 
                Ok(())
@@ -967,7 +971,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                          funding_redeemscript: Script, channel_value_satoshis: u64,
                          commitment_transaction_number_obscure_factor: u64,
                          initial_holder_commitment_tx: HolderCommitmentTransaction,
-                         best_block: BestBlock) -> ChannelMonitor<Signer> {
+                         best_block: BestBlock, counterparty_node_id: PublicKey) -> ChannelMonitor<Signer> {
 
                assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
                let payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize());
@@ -1057,6 +1061,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                                htlcs_resolved_on_chain: Vec::new(),
 
                                best_block,
+                               counterparty_node_id: Some(counterparty_node_id),
 
                                secp_ctx,
                        }),
@@ -1099,7 +1104,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                payment_hash: &PaymentHash,
                payment_preimage: &PaymentPreimage,
                broadcaster: &B,
-               fee_estimator: &F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: &L,
        ) where
                B::Target: BroadcasterInterface,
@@ -1295,8 +1300,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                F::Target: FeeEstimator,
                L::Target: Logger,
        {
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
                self.inner.lock().unwrap().transactions_confirmed(
-                       header, txdata, height, broadcaster, fee_estimator, logger)
+                       header, txdata, height, broadcaster, &bounded_fee_estimator, logger)
        }
 
        /// Processes a transaction that was reorganized out of the chain.
@@ -1316,8 +1322,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                F::Target: FeeEstimator,
                L::Target: Logger,
        {
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
                self.inner.lock().unwrap().transaction_unconfirmed(
-                       txid, broadcaster, fee_estimator, logger);
+                       txid, broadcaster, &bounded_fee_estimator, logger);
        }
 
        /// Updates the monitor with the current best chain tip, returning new outputs to watch. See
@@ -1340,8 +1347,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                F::Target: FeeEstimator,
                L::Target: Logger,
        {
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
                self.inner.lock().unwrap().best_block_updated(
-                       header, height, broadcaster, fee_estimator, logger)
+                       header, height, broadcaster, &bounded_fee_estimator, logger)
        }
 
        /// Returns the set of txids that should be monitored for re-organization out of the chain.
@@ -1877,7 +1885,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 
        /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
        /// commitment_tx_infos which contain the payment hash have been revoked.
-       fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L)
+       fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(
+               &mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B,
+               fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
        where B::Target: BroadcasterInterface,
                    F::Target: FeeEstimator,
                    L::Target: Logger,
@@ -1975,7 +1985,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                },
                                ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
                                        log_trace!(logger, "Updating ChannelMonitor with payment preimage");
-                                       self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger)
+                                       let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
+                                       self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger)
                                },
                                ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
                                        log_trace!(logger, "Updating ChannelMonitor with commitment secret");
@@ -2401,7 +2412,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                let block_hash = header.block_hash();
                self.best_block = BestBlock::new(block_hash, height);
 
-               self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger)
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
+               self.transactions_confirmed(header, txdata, height, broadcaster, &bounded_fee_estimator, logger)
        }
 
        fn best_block_updated<B: Deref, F: Deref, L: Deref>(
@@ -2409,7 +2421,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                header: &BlockHeader,
                height: u32,
                broadcaster: B,
-               fee_estimator: F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: L,
        ) -> Vec<TransactionOutputs>
        where
@@ -2436,7 +2448,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                txdata: &TransactionData,
                height: u32,
                broadcaster: B,
-               fee_estimator: F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: L,
        ) -> Vec<TransactionOutputs>
        where
@@ -2533,7 +2545,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                mut watch_outputs: Vec<TransactionOutputs>,
                mut claimable_outpoints: Vec<PackageTemplate>,
                broadcaster: &B,
-               fee_estimator: &F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: &L,
        ) -> Vec<TransactionOutputs>
        where
@@ -2671,7 +2683,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                //- maturing spendable output has transaction paying us has been disconnected
                self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height < height);
 
-               self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
+               self.onchain_tx_handler.block_disconnected(height, broadcaster, &bounded_fee_estimator, logger);
 
                self.best_block = BestBlock::new(header.prev_blockhash, height - 1);
        }
@@ -2680,7 +2693,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                &mut self,
                txid: &Txid,
                broadcaster: B,
-               fee_estimator: F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: L,
        ) where
                B::Target: BroadcasterInterface,
@@ -3336,11 +3349,13 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                let mut funding_spend_confirmed = None;
                let mut htlcs_resolved_on_chain = Some(Vec::new());
                let mut funding_spend_seen = Some(false);
+               let mut counterparty_node_id = None;
                read_tlv_fields!(reader, {
                        (1, funding_spend_confirmed, option),
                        (3, htlcs_resolved_on_chain, vec_type),
                        (5, pending_monitor_events, vec_type),
                        (7, funding_spend_seen, option),
+                       (9, counterparty_node_id, option),
                });
 
                let mut secp_ctx = Secp256k1::new();
@@ -3395,6 +3410,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                                htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
 
                                best_block,
+                               counterparty_node_id,
 
                                secp_ctx,
                        }),
@@ -3420,6 +3436,8 @@ mod tests {
 
        use hex;
 
+       use crate::chain::chaininterface::LowerBoundedFeeEstimator;
+
        use super::ChannelMonitorUpdateStep;
        use ::{check_added_monitors, check_closed_broadcast, check_closed_event, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash, unwrap_send_err};
        use chain::{BestBlock, Confirm};
@@ -3541,7 +3559,7 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(TestLogger::new());
                let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))});
-               let fee_estimator = Arc::new(TestFeeEstimator { sat_per_kw: Mutex::new(253) });
+               let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::new(253) };
 
                let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
@@ -3631,7 +3649,7 @@ mod tests {
                                                  (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
                                                  &channel_parameters,
                                                  Script::new(), 46, 0,
-                                                 HolderCommitmentTransaction::dummy(), best_block);
+                                                 HolderCommitmentTransaction::dummy(), best_block, dummy_key);
 
                monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap();
                let dummy_txid = dummy_tx.txid();
@@ -3640,7 +3658,8 @@ mod tests {
                monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger);
                monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger);
                for &(ref preimage, ref hash) in preimages.iter() {
-                       monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger);
+                       let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
+                       monitor.provide_payment_preimage(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger);
                }
 
                // Now provide a secret, pruning preimages 10-15
index 1ca3effabd7e537afc0832cff5085abd3a6abf47..ac01cacaa8649d6676050e3b6eb4d173026250ed 100644 (file)
@@ -24,7 +24,7 @@ use bitcoin::secp256k1;
 use ln::msgs::DecodeError;
 use ln::PaymentPreimage;
 use ln::chan_utils::{ChannelTransactionParameters, HolderCommitmentTransaction};
-use chain::chaininterface::{FeeEstimator, BroadcasterInterface};
+use chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator};
 use chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER};
 use chain::keysinterface::{Sign, KeysInterface};
 use chain::package::PackageTemplate;
@@ -377,7 +377,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
        /// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
        /// Panics if there are signing errors, because signing operations in reaction to on-chain events
        /// are not expected to fail, and if they do, we may lose funds.
-       fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &F, logger: &L) -> Option<(Option<u32>, u64, Transaction)>
+       fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(Option<u32>, u64, Transaction)>
                where F::Target: FeeEstimator,
                                        L::Target: Logger,
        {
@@ -415,7 +415,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
        /// `conf_height` represents the height at which the transactions in `txn_matched` were
        /// confirmed. This does not need to equal the current blockchain tip height, which should be
        /// provided via `cur_height`, however it must never be higher than `cur_height`.
-       pub(crate) fn update_claims_view<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], requests: Vec<PackageTemplate>, conf_height: u32, cur_height: u32, broadcaster: &B, fee_estimator: &F, logger: &L)
+       pub(crate) fn update_claims_view<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], requests: Vec<PackageTemplate>, conf_height: u32, cur_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
                where B::Target: BroadcasterInterface,
                      F::Target: FeeEstimator,
                                        L::Target: Logger,
@@ -617,7 +617,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                &mut self,
                txid: &Txid,
                broadcaster: B,
-               fee_estimator: F,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
                logger: L,
        ) where
                B::Target: BroadcasterInterface,
@@ -637,7 +637,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                }
        }
 
-       pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
+       pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L)
                where B::Target: BroadcasterInterface,
                      F::Target: FeeEstimator,
                                        L::Target: Logger,
@@ -667,7 +667,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                        }
                }
                for (_, request) in bump_candidates.iter_mut() {
-                       if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &request, &&*fee_estimator, &&*logger) {
+                       if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &request, fee_estimator, &&*logger) {
                                request.set_timer(new_timer);
                                request.set_feerate(new_feerate);
                                log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx));
index b0961293c07c59a3ab71d51912576add191928da..b0cfa9bf000e712f797b3087d7d37b066b0510b7 100644 (file)
@@ -38,6 +38,8 @@ use core::mem;
 use core::ops::Deref;
 use bitcoin::Witness;
 
+use super::chaininterface::LowerBoundedFeeEstimator;
+
 const MAX_ALLOC_SIZE: usize = 64*1024;
 
 
@@ -665,7 +667,7 @@ impl PackageTemplate {
        /// Returns value in satoshis to be included as package outgoing output amount and feerate
        /// which was used to generate the value. Will not return less than `dust_limit_sats` for the
        /// value.
-       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
                where F::Target: FeeEstimator,
                      L::Target: Logger,
        {
@@ -772,7 +774,7 @@ impl Readable for PackageTemplate {
 /// If the proposed fee is less than the available spent output's values, we return the proposed
 /// fee and the corresponding updated feerate. If the proposed fee is equal or more than the
 /// available spent output's values, we return nothing
-fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
        where F::Target: FeeEstimator,
              L::Target: Logger,
 {
@@ -808,7 +810,7 @@ fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predic
 /// attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous feerate. We also
 /// verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required adjust
 /// the new fee to meet the RBF policy requirement.
-fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
        where F::Target: FeeEstimator,
              L::Target: Logger,
 {
index c5133a850584fd5b6e91d9c91e43a087c3c268d3..f612cb97943beb94853f29c83fc363d0ab4bbb68 100644 (file)
@@ -31,7 +31,7 @@ use ln::channelmanager::{CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSour
 use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
 use ln::chan_utils;
 use chain::BestBlock;
-use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
+use chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
 use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
 use chain::transaction::{OutPoint, TransactionData};
 use chain::keysinterface::{Sign, KeysInterface};
@@ -886,7 +886,7 @@ impl<Signer: Sign> Channel<Signer> {
 
        // Constructors:
        pub fn new_outbound<K: Deref, F: Deref>(
-               fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
+               fee_estimator: &LowerBoundedFeeEstimator<F>, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
                channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig, current_chain_height: u32,
                outbound_scid_alias: u64
        ) -> Result<Channel<Signer>, APIError>
@@ -1056,7 +1056,7 @@ impl<Signer: Sign> Channel<Signer> {
                })
        }
 
-       fn check_remote_fee<F: Deref>(fee_estimator: &F, feerate_per_kw: u32) -> Result<(), ChannelError>
+       fn check_remote_fee<F: Deref>(fee_estimator: &LowerBoundedFeeEstimator<F>, feerate_per_kw: u32) -> Result<(), ChannelError>
                where F::Target: FeeEstimator
        {
                // We only bound the fee updates on the upper side to prevent completely absurd feerates,
@@ -1082,7 +1082,7 @@ impl<Signer: Sign> Channel<Signer> {
        /// Creates a new channel from a remote sides' request for one.
        /// Assumes chain_hash has already been checked and corresponds with what we expect!
        pub fn new_from_req<K: Deref, F: Deref, L: Deref>(
-               fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
+               fee_estimator: &LowerBoundedFeeEstimator<F>, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
                msg: &msgs::OpenChannel, user_id: u64, config: &UserConfig, current_chain_height: u32, logger: &L,
                outbound_scid_alias: u64
        ) -> Result<Channel<Signer>, ChannelError>
@@ -2209,7 +2209,7 @@ impl<Signer: Sign> Channel<Signer> {
                                                          &self.channel_transaction_parameters,
                                                          funding_redeemscript.clone(), self.channel_value_satoshis,
                                                          obscure_factor,
-                                                         holder_commitment_tx, best_block);
+                                                         holder_commitment_tx, best_block, self.counterparty_node_id);
 
                channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger);
 
@@ -2286,7 +2286,7 @@ impl<Signer: Sign> Channel<Signer> {
                                                          &self.channel_transaction_parameters,
                                                          funding_redeemscript.clone(), self.channel_value_satoshis,
                                                          obscure_factor,
-                                                         holder_commitment_tx, best_block);
+                                                         holder_commitment_tx, best_block, self.counterparty_node_id);
 
                channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_bitcoin_tx.txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger);
 
@@ -3687,7 +3687,7 @@ impl<Signer: Sign> Channel<Signer> {
                }
        }
 
-       pub fn update_fee<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::UpdateFee) -> Result<(), ChannelError>
+       pub fn update_fee<F: Deref>(&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, msg: &msgs::UpdateFee) -> Result<(), ChannelError>
                where F::Target: FeeEstimator
        {
                if self.is_outbound() {
@@ -4013,7 +4013,8 @@ impl<Signer: Sign> Channel<Signer> {
        /// Calculates and returns our minimum and maximum closing transaction fee amounts, in whole
        /// satoshis. The amounts remain consistent unless a peer disconnects/reconnects or we restart,
        /// at which point they will be recalculated.
-       fn calculate_closing_fee_limits<F: Deref>(&mut self, fee_estimator: &F) -> (u64, u64)
+       fn calculate_closing_fee_limits<F: Deref>(&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>)
+               -> (u64, u64)
                where F::Target: FeeEstimator
        {
                if let Some((min, max)) = self.closing_fee_limits { return (min, max); }
@@ -4087,7 +4088,8 @@ impl<Signer: Sign> Channel<Signer> {
                Ok(())
        }
 
-       pub fn maybe_propose_closing_signed<F: Deref, L: Deref>(&mut self, fee_estimator: &F, logger: &L)
+       pub fn maybe_propose_closing_signed<F: Deref, L: Deref>(
+               &mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
                -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
                where F::Target: FeeEstimator, L::Target: Logger
        {
@@ -4241,7 +4243,9 @@ impl<Signer: Sign> Channel<Signer> {
                tx
        }
 
-       pub fn closing_signed<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
+       pub fn closing_signed<F: Deref>(
+               &mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, msg: &msgs::ClosingSigned)
+               -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
                where F::Target: FeeEstimator
        {
                if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
@@ -4936,8 +4940,9 @@ impl<Signer: Sign> Channel<Signer> {
                        // the funding transaction is at least still in the mempool of most nodes).
                        //
                        // Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf or
-                       // 0-conf channel, but not doing so may lead to the `ChannelManager::short_to_id` map
-                       // being inconsistent, so we currently have to.
+                       // 0-conf channel, but not doing so may lead to the
+                       // `ChannelManager::short_to_chan_info` map  being inconsistent, so we currently have
+                       // to.
                        if funding_tx_confirmations == 0 && self.funding_tx_confirmed_in.is_some() {
                                let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
                                        self.minimum_depth.unwrap(), funding_tx_confirmations);
@@ -6572,7 +6577,7 @@ mod tests {
        use ln::chan_utils;
        use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
        use chain::BestBlock;
-       use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
+       use chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
        use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface};
        use chain::transaction::OutPoint;
        use util::config::UserConfig;
@@ -6611,7 +6616,9 @@ mod tests {
        fn test_no_fee_check_overflow() {
                // Previously, calling `check_remote_fee` with a fee of 0xffffffff would overflow in
                // arithmetic, causing a panic with debug assertions enabled.
-               assert!(Channel::<InMemorySigner>::check_remote_fee(&&TestFeeEstimator { fee_est: 42 }, u32::max_value()).is_err());
+               let fee_est = TestFeeEstimator { fee_est: 42 };
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est);
+               assert!(Channel::<InMemorySigner>::check_remote_fee(&bounded_fee_estimator, u32::max_value()).is_err());
        }
 
        struct Keys {
@@ -6661,11 +6668,10 @@ mod tests {
                        returns: non_v0_segwit_shutdown_script.clone(),
                });
 
-               let fee_estimator = TestFeeEstimator { fee_est: 253 };
                let secp_ctx = Secp256k1::new();
                let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               match Channel::<EnforcingSigner>::new_outbound(&&fee_estimator, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) {
+               match Channel::<EnforcingSigner>::new_outbound(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) {
                        Err(APIError::IncompatibleShutdownScript { script }) => {
                                assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner());
                        },
@@ -6680,6 +6686,7 @@ mod tests {
        fn test_open_channel_msg_fee() {
                let original_fee = 253;
                let mut fee_est = TestFeeEstimator{fee_est: original_fee };
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est);
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -6687,7 +6694,7 @@ mod tests {
 
                let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&bounded_fee_estimator, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
 
                // Now change the fee so we can check that the fee in the open_channel message is the
                // same as the old fee.
@@ -6700,7 +6707,7 @@ mod tests {
        fn test_holder_vs_counterparty_dust_limit() {
                // Test that when calculating the local and remote commitment transaction fees, the correct
                // dust limits are used.
-               let feeest = TestFeeEstimator{fee_est: 15000};
+               let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -6713,13 +6720,13 @@ mod tests {
                // Create Node A's channel pointing to Node B's pubkey
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
 
                // Create Node B's channel by receiving Node A's open_channel message
                // Make sure A's dust limit is as we expect.
                let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
-               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
 
                // Node B --> Node A: accept channel, explicitly setting B's dust limit.
                let mut accept_channel_msg = node_b_chan.accept_inbound_channel(0);
@@ -6775,7 +6782,7 @@ mod tests {
                // calculate the real dust limits for HTLCs (i.e. the dust limit given by the counterparty
                // *plus* the fees paid for the HTLC) they don't swap `HTLC_SUCCESS_TX_WEIGHT` for
                // `HTLC_TIMEOUT_TX_WEIGHT`, and vice versa.
-               let fee_est = TestFeeEstimator{fee_est: 253 };
+               let fee_est = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 253 });
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -6783,7 +6790,7 @@ mod tests {
 
                let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+               let mut chan = Channel::<EnforcingSigner>::new_outbound(&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
 
                let commitment_tx_fee_0_htlcs = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 0, chan.opt_anchors());
                let commitment_tx_fee_1_htlc = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 1, chan.opt_anchors());
@@ -6818,7 +6825,7 @@ mod tests {
 
        #[test]
        fn channel_reestablish_no_updates() {
-               let feeest = TestFeeEstimator{fee_est: 15000};
+               let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let logger = test_utils::TestLogger::new();
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
@@ -6832,12 +6839,12 @@ mod tests {
                // Create Node A's channel pointing to Node B's pubkey
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
 
                // Create Node B's channel by receiving Node A's open_channel message
                let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
-               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+               let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
 
                // Node B --> Node A: accept channel
                let accept_channel_msg = node_b_chan.accept_inbound_channel(0);
@@ -6884,7 +6891,7 @@ mod tests {
 
        #[test]
        fn test_configured_holder_max_htlc_value_in_flight() {
-               let feeest = TestFeeEstimator{fee_est: 15000};
+               let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let logger = test_utils::TestLogger::new();
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
@@ -6905,12 +6912,12 @@ mod tests {
                // Test that `new_outbound` creates a channel with the correct value for
                // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
                // which is set to the lower bound + 1 (2%) of the `channel_value`.
-               let chan_1 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
+               let chan_1 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
                let chan_1_value_msat = chan_1.channel_value_satoshis * 1000;
                assert_eq!(chan_1.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64);
 
                // Test with the upper bound - 1 of valid values (99%).
-               let chan_2 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
+               let chan_2 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
                let chan_2_value_msat = chan_2.channel_value_satoshis * 1000;
                assert_eq!(chan_2.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64);
 
@@ -6919,45 +6926,45 @@ mod tests {
                // Test that `new_from_req` creates a channel with the correct value for
                // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
                // which is set to the lower bound - 1 (2%) of the `channel_value`.
-               let chan_3 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
+               let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
                let chan_3_value_msat = chan_3.channel_value_satoshis * 1000;
                assert_eq!(chan_3.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64);
 
                // Test with the upper bound - 1 of valid values (99%).
-               let chan_4 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
+               let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
                let chan_4_value_msat = chan_4.channel_value_satoshis * 1000;
                assert_eq!(chan_4.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64);
 
                // Test that `new_outbound` uses the lower bound of the configurable percentage values (1%)
                // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
-               let chan_5 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
+               let chan_5 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
                let chan_5_value_msat = chan_5.channel_value_satoshis * 1000;
                assert_eq!(chan_5.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64);
 
                // Test that `new_outbound` uses the upper bound of the configurable percentage values
                // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
                // than 100.
-               let chan_6 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
+               let chan_6 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
                let chan_6_value_msat = chan_6.channel_value_satoshis * 1000;
                assert_eq!(chan_6.holder_max_htlc_value_in_flight_msat, chan_6_value_msat);
 
                // Test that `new_from_req` uses the lower bound of the configurable percentage values (1%)
                // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
-               let chan_7 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
+               let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
                let chan_7_value_msat = chan_7.channel_value_satoshis * 1000;
                assert_eq!(chan_7.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64);
 
                // Test that `new_from_req` uses the upper bound of the configurable percentage values
                // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
                // than 100.
-               let chan_8 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
+               let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
                let chan_8_value_msat = chan_8.channel_value_satoshis * 1000;
                assert_eq!(chan_8.holder_max_htlc_value_in_flight_msat, chan_8_value_msat);
        }
 
        #[test]
        fn channel_update() {
-               let feeest = TestFeeEstimator{fee_est: 15000};
+               let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -6967,7 +6974,7 @@ mod tests {
                // Create a channel.
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
                assert!(node_a_chan.counterparty_forwarding_info.is_none());
                assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
                assert!(node_a_chan.counterparty_forwarding_info().is_none());
@@ -7046,7 +7053,7 @@ mod tests {
                let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let mut config = UserConfig::default();
                config.channel_handshake_config.announced_channel = false;
-               let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
+               let mut chan = Channel::<InMemorySigner>::new_outbound(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
                chan.holder_dust_limit_satoshis = 546;
                chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
 
@@ -7884,7 +7891,7 @@ mod tests {
 
        #[test]
        fn test_zero_conf_channel_type_support() {
-               let feeest = TestFeeEstimator{fee_est: 15000};
+               let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -7893,7 +7900,7 @@ mod tests {
 
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider,
+               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider,
                        node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
 
                let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key();
@@ -7902,7 +7909,7 @@ mod tests {
                let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
                open_channel_msg.channel_type = Some(channel_type_features);
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
-               let res = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider,
+               let res = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider,
                        node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42);
                assert!(res.is_ok());
        }
index 871ebb92d32270d1d1730dc1c947f1015d2596b8..bae408d29f0ba8d2b077711baacdb0c0de34b5bb 100644 (file)
@@ -36,7 +36,7 @@ use bitcoin::secp256k1;
 
 use chain;
 use chain::{Confirm, ChannelMonitorUpdateErr, Watch, BestBlock};
-use chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
+use chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
 use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID};
 use chain::transaction::{OutPoint, TransactionData};
 // Since this struct is returned in `list_channels` methods, expose it here in case users want to
@@ -397,10 +397,12 @@ pub(super) enum RAACommitmentOrder {
 // Note this is only exposed in cfg(test):
 pub(super) struct ChannelHolder<Signer: Sign> {
        pub(super) by_id: HashMap<[u8; 32], Channel<Signer>>,
-       /// SCIDs (and outbound SCID aliases) to the real channel id. Outbound SCID aliases are added
-       /// here once the channel is available for normal use, with SCIDs being added once the funding
-       /// transaction is confirmed at the channel's required confirmation depth.
-       pub(super) short_to_id: HashMap<u64, [u8; 32]>,
+       /// SCIDs (and outbound SCID aliases) -> `counterparty_node_id`s and `channel_id`s.
+       ///
+       /// Outbound SCID aliases are added here once the channel is available for normal use, with
+       /// SCIDs being added once the funding transaction is confirmed at the channel's required
+       /// confirmation depth.
+       pub(super) short_to_chan_info: HashMap<u64, (PublicKey, [u8; 32])>,
        /// SCID/SCID Alias -> forward infos. Key of 0 means payments received.
        ///
        /// Note that because we may have an SCID Alias as the key we can have two entries per channel,
@@ -686,7 +688,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
 {
        default_configuration: UserConfig,
        genesis_hash: BlockHash,
-       fee_estimator: F,
+       fee_estimator: LowerBoundedFeeEstimator<F>,
        chain_monitor: M,
        tx_broadcaster: T,
 
@@ -728,6 +730,25 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
        /// active channel list on load.
        outbound_scid_aliases: Mutex<HashSet<u64>>,
 
+       /// `channel_id` -> `counterparty_node_id`.
+       ///
+       /// Only `channel_id`s are allowed as keys in this map, and not `temporary_channel_id`s. As
+       /// multiple channels with the same `temporary_channel_id` to different peers can exist,
+       /// allowing `temporary_channel_id`s in this map would cause collisions for such channels.
+       ///
+       /// Note that this map should only be used for `MonitorEvent` handling, to be able to access
+       /// the corresponding channel for the event, as we only have access to the `channel_id` during
+       /// the handling of the events.
+       ///
+       /// TODO:
+       /// The `counterparty_node_id` isn't passed with `MonitorEvent`s currently. To pass it, we need
+       /// to make `counterparty_node_id`'s a required field in `ChannelMonitor`s, which unfortunately
+       /// would break backwards compatability.
+       /// We should add `counterparty_node_id`s to `MonitorEvent`s, and eventually rely on it in the
+       /// future. That would make this map redundant, as only the `ChannelManager::per_peer_state` is
+       /// required to access the channel with the `counterparty_node_id`.
+       id_to_peer: Mutex<HashMap<[u8; 32], PublicKey>>,
+
        our_network_key: SecretKey,
        our_network_pubkey: PublicKey,
 
@@ -740,6 +761,11 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
        /// [fake scids]: crate::util::scid_utils::fake_scid
        fake_scid_rand_bytes: [u8; 32],
 
+       /// When we send payment probes, we generate the [`PaymentHash`] based on this cookie secret
+       /// and a random [`PaymentId`]. This allows us to discern probes from real payments, without
+       /// keeping additional state.
+       probing_cookie_secret: [u8; 32],
+
        /// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
        /// value increases strictly since we don't assume access to a time source.
        last_node_announcement_serial: AtomicUsize,
@@ -1230,9 +1256,9 @@ macro_rules! handle_error {
 }
 
 macro_rules! update_maps_on_chan_removal {
-       ($self: expr, $short_to_id: expr, $channel: expr) => {
+       ($self: expr, $short_to_chan_info: expr, $channel: expr) => {
                if let Some(short_id) = $channel.get_short_channel_id() {
-                       $short_to_id.remove(&short_id);
+                       $short_to_chan_info.remove(&short_id);
                } else {
                        // If the channel was never confirmed on-chain prior to its closure, remove the
                        // outbound SCID alias we used for it from the collision-prevention set. While we
@@ -1243,13 +1269,14 @@ macro_rules! update_maps_on_chan_removal {
                        let alias_removed = $self.outbound_scid_aliases.lock().unwrap().remove(&$channel.outbound_scid_alias());
                        debug_assert!(alias_removed);
                }
-               $short_to_id.remove(&$channel.outbound_scid_alias());
+               $self.id_to_peer.lock().unwrap().remove(&$channel.channel_id());
+               $short_to_chan_info.remove(&$channel.outbound_scid_alias());
        }
 }
 
 /// Returns (boolean indicating if we should remove the Channel object from memory, a mapped error)
 macro_rules! convert_chan_err {
-       ($self: ident, $err: expr, $short_to_id: expr, $channel: expr, $channel_id: expr) => {
+       ($self: ident, $err: expr, $short_to_chan_info: expr, $channel: expr, $channel_id: expr) => {
                match $err {
                        ChannelError::Warn(msg) => {
                                (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn(msg), $channel_id.clone()))
@@ -1259,7 +1286,7 @@ macro_rules! convert_chan_err {
                        },
                        ChannelError::Close(msg) => {
                                log_error!($self.logger, "Closing channel {} due to close-required error: {}", log_bytes!($channel_id[..]), msg);
-                               update_maps_on_chan_removal!($self, $short_to_id, $channel);
+                               update_maps_on_chan_removal!($self, $short_to_chan_info, $channel);
                                let shutdown_res = $channel.force_shutdown(true);
                                (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, $channel.get_user_id(),
                                        shutdown_res, $self.get_channel_update_for_broadcast(&$channel).ok()))
@@ -1273,7 +1300,7 @@ macro_rules! break_chan_entry {
                match $res {
                        Ok(res) => res,
                        Err(e) => {
-                               let (drop, res) = convert_chan_err!($self, e, $channel_state.short_to_id, $entry.get_mut(), $entry.key());
+                               let (drop, res) = convert_chan_err!($self, e, $channel_state.short_to_chan_info, $entry.get_mut(), $entry.key());
                                if drop {
                                        $entry.remove_entry();
                                }
@@ -1288,7 +1315,7 @@ macro_rules! try_chan_entry {
                match $res {
                        Ok(res) => res,
                        Err(e) => {
-                               let (drop, res) = convert_chan_err!($self, e, $channel_state.short_to_id, $entry.get_mut(), $entry.key());
+                               let (drop, res) = convert_chan_err!($self, e, $channel_state.short_to_chan_info, $entry.get_mut(), $entry.key());
                                if drop {
                                        $entry.remove_entry();
                                }
@@ -1302,18 +1329,18 @@ macro_rules! remove_channel {
        ($self: expr, $channel_state: expr, $entry: expr) => {
                {
                        let channel = $entry.remove_entry().1;
-                       update_maps_on_chan_removal!($self, $channel_state.short_to_id, channel);
+                       update_maps_on_chan_removal!($self, $channel_state.short_to_chan_info, channel);
                        channel
                }
        }
 }
 
 macro_rules! handle_monitor_err {
-       ($self: ident, $err: expr, $short_to_id: 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) => {
+       ($self: ident, $err: expr, $short_to_chan_info: 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 {
                        ChannelMonitorUpdateErr::PermanentFailure => {
                                log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateErr::PermanentFailure", log_bytes!($chan_id[..]));
-                               update_maps_on_chan_removal!($self, $short_to_id, $chan);
+                               update_maps_on_chan_removal!($self, $short_to_chan_info, $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.
@@ -1353,7 +1380,7 @@ macro_rules! handle_monitor_err {
                }
        };
        ($self: ident, $err: expr, $channel_state: 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_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $resend_channel_ready, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
+               let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_chan_info, $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();
                }
@@ -1399,19 +1426,19 @@ macro_rules! maybe_break_monitor_err {
 }
 
 macro_rules! send_channel_ready {
-       ($short_to_id: expr, $pending_msg_events: expr, $channel: expr, $channel_ready_msg: expr) => {
+       ($short_to_chan_info: expr, $pending_msg_events: expr, $channel: expr, $channel_ready_msg: expr) => {
                $pending_msg_events.push(events::MessageSendEvent::SendChannelReady {
                        node_id: $channel.get_counterparty_node_id(),
                        msg: $channel_ready_msg,
                });
                // Note that we may send a `channel_ready` multiple times for a channel if we reconnect, so
                // we allow collisions, but we shouldn't ever be updating the channel ID pointed to.
-               let outbound_alias_insert = $short_to_id.insert($channel.outbound_scid_alias(), $channel.channel_id());
-               assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == $channel.channel_id(),
+               let outbound_alias_insert = $short_to_chan_info.insert($channel.outbound_scid_alias(), ($channel.get_counterparty_node_id(), $channel.channel_id()));
+               assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
                        "SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
                if let Some(real_scid) = $channel.get_short_channel_id() {
-                       let scid_insert = $short_to_id.insert(real_scid, $channel.channel_id());
-                       assert!(scid_insert.is_none() || scid_insert.unwrap() == $channel.channel_id(),
+                       let scid_insert = $short_to_chan_info.insert(real_scid, ($channel.get_counterparty_node_id(), $channel.channel_id()));
+                       assert!(scid_insert.is_none() || scid_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
                                "SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
                }
        }
@@ -1451,7 +1478,7 @@ macro_rules! handle_chan_restoration_locked {
                                // Similar to the above, this implies that we're letting the channel_ready fly
                                // before it should be allowed to.
                                assert!(chanmon_update.is_none());
-                               send_channel_ready!($channel_state.short_to_id, $channel_state.pending_msg_events, $channel_entry.get(), msg);
+                               send_channel_ready!($channel_state.short_to_chan_info, $channel_state.pending_msg_events, $channel_entry.get(), msg);
                        }
                        if let Some(msg) = $announcement_sigs {
                                $channel_state.pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
@@ -1565,7 +1592,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                ChannelManager {
                        default_configuration: config.clone(),
                        genesis_hash: genesis_block(params.network).header.block_hash(),
-                       fee_estimator: fee_est,
+                       fee_estimator: LowerBoundedFeeEstimator::new(fee_est),
                        chain_monitor,
                        tx_broadcaster,
 
@@ -1573,7 +1600,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
 
                        channel_state: Mutex::new(ChannelHolder{
                                by_id: HashMap::new(),
-                               short_to_id: HashMap::new(),
+                               short_to_chan_info: HashMap::new(),
                                forward_htlcs: HashMap::new(),
                                claimable_htlcs: HashMap::new(),
                                pending_msg_events: Vec::new(),
@@ -1581,6 +1608,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        outbound_scid_aliases: Mutex::new(HashSet::new()),
                        pending_inbound_payments: Mutex::new(HashMap::new()),
                        pending_outbound_payments: Mutex::new(HashMap::new()),
+                       id_to_peer: Mutex::new(HashMap::new()),
 
                        our_network_key: keys_manager.get_node_secret(Recipient::Node).unwrap(),
                        our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret(Recipient::Node).unwrap()),
@@ -1589,6 +1617,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        inbound_payment_key: expanded_inbound_key,
                        fake_scid_rand_bytes: keys_manager.get_secure_random_bytes(),
 
+                       probing_cookie_secret: keys_manager.get_secure_random_bytes(),
+
                        last_node_announcement_serial: AtomicUsize::new(0),
                        highest_seen_timestamp: AtomicUsize::new(0),
 
@@ -1831,7 +1861,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        if let Some(monitor_update) = monitor_update {
                                                if let Err(e) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
                                                        let (result, is_permanent) =
-                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
+                                                               handle_monitor_err!(self, e, channel_state.short_to_chan_info, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
                                                        if is_permanent {
                                                                remove_channel!(self, channel_state, chan_entry);
                                                                break result;
@@ -2219,7 +2249,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        // with a short_channel_id of 0. This is important as various things later assume
                        // short_channel_id is non-0 in any ::Forward.
                        if let &PendingHTLCRouting::Forward { ref short_channel_id, .. } = routing {
-                               let id_option = channel_state.as_ref().unwrap().short_to_id.get(&short_channel_id).cloned();
+                               let id_option = channel_state.as_ref().unwrap().short_to_chan_info.get(&short_channel_id).cloned();
                                if let Some((err, code, chan_update)) = loop {
                                        let forwarding_id_opt = match id_option {
                                                None => { // unknown_next_peer
@@ -2231,7 +2261,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                                break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
                                                        }
                                                },
-                                               Some(id) => Some(id.clone()),
+                                               Some((_cp_id, chan_id)) => Some(chan_id.clone()),
                                        };
                                        let chan_update_opt = if let Some(forwarding_id) = forwarding_id_opt {
                                                let chan = channel_state.as_mut().unwrap().by_id.get_mut(&forwarding_id).unwrap();
@@ -2412,9 +2442,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                }
                        }
 
-                       let id = match channel_lock.short_to_id.get(&path.first().unwrap().short_channel_id) {
+                       let id = match channel_lock.short_to_chan_info.get(&path.first().unwrap().short_channel_id) {
                                None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!".to_owned()}),
-                               Some(id) => id.clone(),
+                               Some((_cp_id, chan_id)) => chan_id.clone(),
                        };
 
                        macro_rules! insert_outbound_payment {
@@ -2731,6 +2761,43 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                }
        }
 
+       /// Send a payment that is probing the given route for liquidity. We calculate the
+       /// [`PaymentHash`] of probes based on a static secret and a random [`PaymentId`], which allows
+       /// us to easily discern them from real payments.
+       pub fn send_probe(&self, hops: Vec<RouteHop>) -> Result<(PaymentHash, PaymentId), PaymentSendFailure> {
+               let payment_id = PaymentId(self.keys_manager.get_secure_random_bytes());
+
+               let payment_hash = self.probing_cookie_from_id(&payment_id);
+
+               if hops.len() < 2 {
+                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                               err: "No need probing a path with less than two hops".to_string()
+                       }))
+               }
+
+               let route = Route { paths: vec![hops], payment_params: None };
+
+               match self.send_payment_internal(&route, payment_hash, &None, None, Some(payment_id), None) {
+                       Ok(payment_id) => Ok((payment_hash, payment_id)),
+                       Err(e) => Err(e)
+               }
+       }
+
+       /// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a
+       /// payment probe.
+       pub(crate) fn payment_is_probe(&self, payment_hash: &PaymentHash, payment_id: &PaymentId) -> bool {
+               let target_payment_hash = self.probing_cookie_from_id(payment_id);
+               target_payment_hash == *payment_hash
+       }
+
+       /// Returns the 'probing cookie' for the given [`PaymentId`].
+       fn probing_cookie_from_id(&self, payment_id: &PaymentId) -> PaymentHash {
+               let mut preimage = [0u8; 64];
+               preimage[..32].copy_from_slice(&self.probing_cookie_secret);
+               preimage[32..].copy_from_slice(&payment_id.0);
+               PaymentHash(Sha256::hash(&preimage).into_inner())
+       }
+
        /// Handles the generation of a funding transaction, optionally (for tests) with a function
        /// which checks the correctness of the funding transaction given the associated channel.
        fn funding_transaction_generated_intern<FundingOutput: Fn(&Channel<Signer>, &Transaction) -> Result<OutPoint, APIError>>(
@@ -2769,6 +2836,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                panic!("Generated duplicate funding txid?");
                        },
                        hash_map::Entry::Vacant(e) => {
+                               let mut id_to_peer = self.id_to_peer.lock().unwrap();
+                               if id_to_peer.insert(chan.channel_id(), chan.get_counterparty_node_id()).is_some() {
+                                       panic!("id_to_peer map already contained funding txid, which shouldn't be possible");
+                               }
                                e.insert(chan);
                        }
                }
@@ -2863,15 +2934,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
 
        #[allow(dead_code)]
        // Messages of up to 64KB should never end up more than half full with addresses, as that would
-       // be absurd. We ensure this by checking that at least 500 (our stated public contract on when
+       // be absurd. We ensure this by checking that at least 100 (our stated public contract on when
        // broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB
        // message...
        const HALF_MESSAGE_IS_ADDRS: u32 = ::core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
        #[deny(const_err)]
        #[allow(dead_code)]
        // ...by failing to compile if the number of addresses that would be half of a message is
-       // smaller than 500:
-       const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500;
+       // smaller than 100:
+       const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 100;
 
        /// Regenerates channel_announcements and generates a signed node_announcement from the given
        /// arguments, providing them in corresponding events via
@@ -2888,13 +2959,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        /// tying these addresses together and to this node. If you wish to preserve user privacy,
        /// addresses should likely contain only Tor Onion addresses.
        ///
-       /// Panics if `addresses` is absurdly large (more than 500).
+       /// Panics if `addresses` is absurdly large (more than 100).
        ///
        /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
        pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec<NetAddress>) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
 
-               if addresses.len() > 500 {
+               if addresses.len() > 100 {
                        panic!("More than half the message size was taken up by public addresses!");
                }
 
@@ -3028,8 +3099,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
 
                        for (short_chan_id, mut pending_forwards) in channel_state.forward_htlcs.drain() {
                                if short_chan_id != 0 {
-                                       let forward_chan_id = match channel_state.short_to_id.get(&short_chan_id) {
-                                               Some(chan_id) => chan_id.clone(),
+                                       let forward_chan_id = match channel_state.short_to_chan_info.get(&short_chan_id) {
+                                               Some((_cp_id, chan_id)) => chan_id.clone(),
                                                None => {
                                                        for forward_info in pending_forwards.drain(..) {
                                                                match forward_info {
@@ -3445,7 +3516,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                self.process_background_events();
        }
 
-       fn update_channel_fee(&self, short_to_id: &mut HashMap<u64, [u8; 32]>, pending_msg_events: &mut Vec<events::MessageSendEvent>, chan_id: &[u8; 32], chan: &mut Channel<Signer>, new_feerate: u32) -> (bool, NotifyOption, Result<(), MsgHandleErrInternal>) {
+       fn update_channel_fee(&self, short_to_chan_info: &mut HashMap<u64, (PublicKey, [u8; 32])>, pending_msg_events: &mut Vec<events::MessageSendEvent>, chan_id: &[u8; 32], chan: &mut Channel<Signer>, new_feerate: u32) -> (bool, NotifyOption, Result<(), MsgHandleErrInternal>) {
                if !chan.is_outbound() { return (true, NotifyOption::SkipPersist, Ok(())); }
                // If the feerate has decreased by less than half, don't bother
                if new_feerate <= chan.get_feerate() && new_feerate * 2 > chan.get_feerate() {
@@ -3465,7 +3536,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                let res = match chan.send_update_fee_and_commit(new_feerate, &self.logger) {
                        Ok(res) => Ok(res),
                        Err(e) => {
-                               let (drop, res) = convert_chan_err!(self, e, short_to_id, chan, chan_id);
+                               let (drop, res) = convert_chan_err!(self, e, short_to_chan_info, chan, chan_id);
                                if drop { retain_channel = false; }
                                Err(res)
                        }
@@ -3473,7 +3544,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                let ret_err = match res {
                        Ok(Some((update_fee, commitment_signed, monitor_update))) => {
                                if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) {
-                                       let (res, drop) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, chan_id, COMMITMENT_UPDATE_ONLY);
+                                       let (res, drop) = handle_monitor_err!(self, e, short_to_chan_info, chan, RAACommitmentOrder::CommitmentFirst, chan_id, COMMITMENT_UPDATE_ONLY);
                                        if drop { retain_channel = false; }
                                        res
                                } else {
@@ -3513,9 +3584,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                let mut channel_state_lock = self.channel_state.lock().unwrap();
                                let channel_state = &mut *channel_state_lock;
                                let pending_msg_events = &mut channel_state.pending_msg_events;
-                               let short_to_id = &mut channel_state.short_to_id;
+                               let short_to_chan_info = &mut channel_state.short_to_chan_info;
                                channel_state.by_id.retain(|chan_id, chan| {
-                                       let (retain_channel, chan_needs_persist, err) = self.update_channel_fee(short_to_id, pending_msg_events, chan_id, chan, new_feerate);
+                                       let (retain_channel, chan_needs_persist, err) = self.update_channel_fee(short_to_chan_info, pending_msg_events, chan_id, chan, new_feerate);
                                        if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
                                        if err.is_err() {
                                                handle_errors.push(err);
@@ -3553,10 +3624,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                let mut channel_state_lock = self.channel_state.lock().unwrap();
                                let channel_state = &mut *channel_state_lock;
                                let pending_msg_events = &mut channel_state.pending_msg_events;
-                               let short_to_id = &mut channel_state.short_to_id;
+                               let short_to_chan_info = &mut channel_state.short_to_chan_info;
                                channel_state.by_id.retain(|chan_id, chan| {
                                        let counterparty_node_id = chan.get_counterparty_node_id();
-                                       let (retain_channel, chan_needs_persist, err) = self.update_channel_fee(short_to_id, pending_msg_events, chan_id, chan, new_feerate);
+                                       let (retain_channel, chan_needs_persist, err) = self.update_channel_fee(short_to_chan_info, pending_msg_events, chan_id, chan, new_feerate);
                                        if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
                                        if err.is_err() {
                                                handle_errors.push((err, counterparty_node_id));
@@ -3564,7 +3635,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        if !retain_channel { return false; }
 
                                        if let Err(e) = chan.timer_check_closing_negotiation_progress() {
-                                               let (needs_close, err) = convert_chan_err!(self, e, short_to_id, chan, chan_id);
+                                               let (needs_close, err) = convert_chan_err!(self, e, short_to_chan_info, chan, chan_id);
                                                handle_errors.push((Err(err), chan.get_counterparty_node_id()));
                                                if needs_close { return false; }
                                        }
@@ -3839,22 +3910,40 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                let (network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_utils::process_onion_failure(&self.secp_ctx, &self.logger, &source, err.data.clone());
 #[cfg(not(test))]
                                                let (network_update, short_channel_id, payment_retryable, _, _) = onion_utils::process_onion_failure(&self.secp_ctx, &self.logger, &source, err.data.clone());
-                                               // TODO: If we decided to blame ourselves (or one of our channels) in
-                                               // process_onion_failure we should close that channel as it implies our
-                                               // next-hop is needlessly blaming us!
-                                               events::Event::PaymentPathFailed {
-                                                       payment_id: Some(payment_id),
-                                                       payment_hash: payment_hash.clone(),
-                                                       rejected_by_dest: !payment_retryable,
-                                                       network_update,
-                                                       all_paths_failed,
-                                                       path: path.clone(),
-                                                       short_channel_id,
-                                                       retry,
-#[cfg(test)]
-                                                       error_code: onion_error_code,
-#[cfg(test)]
-                                                       error_data: onion_error_data
+
+                                               if self.payment_is_probe(payment_hash, &payment_id) {
+                                                       if !payment_retryable {
+                                                               events::Event::ProbeSuccessful {
+                                                                       payment_id,
+                                                                       payment_hash: payment_hash.clone(),
+                                                                       path: path.clone(),
+                                                               }
+                                                       } else {
+                                                               events::Event::ProbeFailed {
+                                                                       payment_id: payment_id,
+                                                                       payment_hash: payment_hash.clone(),
+                                                                       path: path.clone(),
+                                                                       short_channel_id,
+                                                               }
+                                                       }
+                                               } else {
+                                                       // TODO: If we decided to blame ourselves (or one of our channels) in
+                                                       // process_onion_failure we should close that channel as it implies our
+                                                       // next-hop is needlessly blaming us!
+                                                       events::Event::PaymentPathFailed {
+                                                               payment_id: Some(payment_id),
+                                                               payment_hash: payment_hash.clone(),
+                                                               rejected_by_dest: !payment_retryable,
+                                                               network_update,
+                                                               all_paths_failed,
+                                                               path: path.clone(),
+                                                               short_channel_id,
+                                                               retry,
+                                                               #[cfg(test)]
+                                                               error_code: onion_error_code,
+                                                               #[cfg(test)]
+                                                               error_data: onion_error_data
+                                                       }
                                                }
                                        },
                                        &HTLCFailReason::Reason {
@@ -3975,7 +4064,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        let mut expected_amt_msat = None;
                        let mut valid_mpp = true;
                        for htlc in sources.iter() {
-                               if let None = channel_state.as_ref().unwrap().short_to_id.get(&htlc.prev_hop.short_channel_id) {
+                               if let None = channel_state.as_ref().unwrap().short_to_chan_info.get(&htlc.prev_hop.short_channel_id) {
                                        valid_mpp = false;
                                        break;
                                }
@@ -4064,8 +4153,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        fn claim_funds_from_hop(&self, channel_state_lock: &mut MutexGuard<ChannelHolder<Signer>>, prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage) -> ClaimFundsFromHop {
                //TODO: Delay the claimed_funds relaying just like we do outbound relay!
                let channel_state = &mut **channel_state_lock;
-               let chan_id = match channel_state.short_to_id.get(&prev_hop.short_channel_id) {
-                       Some(chan_id) => chan_id.clone(),
+               let chan_id = match channel_state.short_to_chan_info.get(&prev_hop.short_channel_id) {
+                       Some((_cp_id, chan_id)) => chan_id.clone(),
                        None => {
                                return ClaimFundsFromHop::PrevHopForceClosed
                        }
@@ -4112,7 +4201,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                        payment_preimage, e);
                                        }
                                        let counterparty_node_id = chan.get().get_counterparty_node_id();
-                                       let (drop, res) = convert_chan_err!(self, e, channel_state.short_to_id, chan.get_mut(), &chan_id);
+                                       let (drop, res) = convert_chan_err!(self, e, channel_state.short_to_chan_info, chan.get_mut(), &chan_id);
                                        if drop {
                                                chan.remove_entry();
                                        }
@@ -4511,12 +4600,23 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                return 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()) {
+                                       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(),
+                                                       funding_msg.channel_id))
+                                       },
+                                       hash_map::Entry::Vacant(i_e) => {
+                                               i_e.insert(chan.get_counterparty_node_id());
+                                       }
+                               }
                                channel_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!(channel_state.short_to_id, channel_state.pending_msg_events, chan, msg);
+                                       send_channel_ready!(channel_state.short_to_chan_info, channel_state.pending_msg_events, chan, msg);
                                }
                                e.insert(chan);
                        }
@@ -4551,7 +4651,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                return res
                                        }
                                        if let Some(msg) = channel_ready {
-                                               send_channel_ready!(channel_state.short_to_id, channel_state.pending_msg_events, chan.get(), msg);
+                                               send_channel_ready!(channel_state.short_to_chan_info, channel_state.pending_msg_events, chan.get(), msg);
                                        }
                                        funding_tx
                                },
@@ -4624,7 +4724,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        if let Some(monitor_update) = monitor_update {
                                                if let Err(e) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
                                                        let (result, is_permanent) =
-                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
+                                                               handle_monitor_err!(self, e, channel_state.short_to_chan_info, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
                                                        if is_permanent {
                                                                remove_channel!(self, channel_state, chan_entry);
                                                                break result;
@@ -4986,8 +5086,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        fn internal_channel_update(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelUpdate) -> Result<NotifyOption, MsgHandleErrInternal> {
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = &mut *channel_state_lock;
-               let chan_id = match channel_state.short_to_id.get(&msg.contents.short_channel_id) {
-                       Some(chan_id) => chan_id.clone(),
+               let chan_id = match channel_state.short_to_chan_info.get(&msg.contents.short_channel_id) {
+                       Some((_cp_id, chan_id)) => chan_id.clone(),
                        None => {
                                // It's not a local channel
                                return Ok(NotifyOption::SkipPersist)
@@ -5156,7 +5256,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_state_lock;
                        let by_id = &mut channel_state.by_id;
-                       let short_to_id = &mut channel_state.short_to_id;
+                       let short_to_chan_info = &mut channel_state.short_to_chan_info;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
 
                        by_id.retain(|channel_id, chan| {
@@ -5172,7 +5272,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                if let Some((commitment_update, monitor_update)) = commitment_opt {
                                                        if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) {
                                                                has_monitor_update = true;
-                                                               let (res, close_channel) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, channel_id, COMMITMENT_UPDATE_ONLY);
+                                                               let (res, close_channel) = handle_monitor_err!(self, e, short_to_chan_info, chan, RAACommitmentOrder::CommitmentFirst, channel_id, COMMITMENT_UPDATE_ONLY);
                                                                handle_errors.push((chan.get_counterparty_node_id(), res));
                                                                if close_channel { return false; }
                                                        } else {
@@ -5185,7 +5285,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                true
                                        },
                                        Err(e) => {
-                                               let (close_channel, res) = convert_chan_err!(self, e, short_to_id, chan, channel_id);
+                                               let (close_channel, res) = convert_chan_err!(self, e, short_to_chan_info, chan, channel_id);
                                                handle_errors.push((chan.get_counterparty_node_id(), Err(res)));
                                                // ChannelClosed event is generated by handle_error for us
                                                !close_channel
@@ -5216,7 +5316,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_state_lock;
                        let by_id = &mut channel_state.by_id;
-                       let short_to_id = &mut channel_state.short_to_id;
+                       let short_to_chan_info = &mut channel_state.short_to_chan_info;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
 
                        by_id.retain(|channel_id, chan| {
@@ -5241,13 +5341,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
 
                                                        log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
                                                        self.tx_broadcaster.broadcast_transaction(&tx);
-                                                       update_maps_on_chan_removal!(self, short_to_id, chan);
+                                                       update_maps_on_chan_removal!(self, short_to_chan_info, chan);
                                                        false
                                                } else { true }
                                        },
                                        Err(e) => {
                                                has_update = true;
-                                               let (close_channel, res) = convert_chan_err!(self, e, short_to_id, chan, channel_id);
+                                               let (close_channel, res) = convert_chan_err!(self, e, short_to_chan_info, chan, channel_id);
                                                handle_errors.push((chan.get_counterparty_node_id(), Err(res)));
                                                !close_channel
                                        }
@@ -5442,7 +5542,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                loop {
                        let scid_candidate = fake_scid::Namespace::Phantom.get_fake_scid(best_block.height(), &self.genesis_hash, &self.fake_scid_rand_bytes, &self.keys_manager);
                        // Ensure the generated scid doesn't conflict with a real channel.
-                       match channel_state.short_to_id.entry(scid_candidate) {
+                       match channel_state.short_to_chan_info.entry(scid_candidate) {
                                hash_map::Entry::Occupied(_) => continue,
                                hash_map::Entry::Vacant(_) => return scid_candidate
                        }
@@ -5677,7 +5777,7 @@ where
 
        fn get_relevant_txids(&self) -> Vec<Txid> {
                let channel_state = self.channel_state.lock().unwrap();
-               let mut res = Vec::with_capacity(channel_state.short_to_id.len());
+               let mut res = Vec::with_capacity(channel_state.short_to_chan_info.len());
                for chan in channel_state.by_id.values() {
                        if let Some(funding_txo) = chan.get_funding_txo() {
                                res.push(funding_txo.txid);
@@ -5720,7 +5820,7 @@ where
                {
                        let mut channel_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_lock;
-                       let short_to_id = &mut channel_state.short_to_id;
+                       let short_to_chan_info = &mut channel_state.short_to_chan_info;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
                        channel_state.by_id.retain(|_, channel| {
                                let res = f(channel);
@@ -5732,7 +5832,7 @@ where
                                                }));
                                        }
                                        if let Some(channel_ready) = channel_ready_opt {
-                                               send_channel_ready!(short_to_id, pending_msg_events, channel, channel_ready);
+                                               send_channel_ready!(short_to_chan_info, pending_msg_events, channel, channel_ready);
                                                if channel.is_usable() {
                                                        log_trace!(self.logger, "Sending channel_ready with private initial channel_update for our counterparty on channel {}", log_bytes!(channel.channel_id()));
                                                        if let Ok(msg) = self.get_channel_update_for_unicast(channel) {
@@ -5765,18 +5865,19 @@ where
                                        if channel.is_our_channel_ready() {
                                                if let Some(real_scid) = channel.get_short_channel_id() {
                                                        // If we sent a 0conf channel_ready, and now have an SCID, we add it
-                                                       // to the short_to_id map here. Note that we check whether we can relay
-                                                       // using the real SCID at relay-time (i.e. enforce option_scid_alias
-                                                       // then), and if the funding tx is ever un-confirmed we force-close the
-                                                       // channel, ensuring short_to_id is always consistent.
-                                                       let scid_insert = short_to_id.insert(real_scid, channel.channel_id());
-                                                       assert!(scid_insert.is_none() || scid_insert.unwrap() == channel.channel_id(),
+                                                       // to the short_to_chan_info map here. Note that we check whether we
+                                                       // can relay using the real SCID at relay-time (i.e.
+                                                       // enforce option_scid_alias then), and if the funding tx is ever
+                                                       // un-confirmed we force-close the channel, ensuring short_to_chan_info
+                                                       // is always consistent.
+                                                       let scid_insert = short_to_chan_info.insert(real_scid, (channel.get_counterparty_node_id(), channel.channel_id()));
+                                                       assert!(scid_insert.is_none() || scid_insert.unwrap() == (channel.get_counterparty_node_id(), channel.channel_id()),
                                                                "SCIDs should never collide - ensure you weren't behind by a full {} blocks when creating channels",
                                                                fake_scid::MAX_SCID_BLOCKS_FROM_NOW);
                                                }
                                        }
                                } else if let Err(reason) = res {
-                                       update_maps_on_chan_removal!(self, short_to_id, channel);
+                                       update_maps_on_chan_removal!(self, short_to_chan_info, channel);
                                        // It looks like our counterparty went on-chain or funding transaction was
                                        // reorged out of the main chain. Close the channel.
                                        failed_channels.push(channel.force_shutdown(true));
@@ -5967,14 +6068,14 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_state_lock;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
-                       let short_to_id = &mut channel_state.short_to_id;
+                       let short_to_chan_info = &mut channel_state.short_to_chan_info;
                        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" });
                        channel_state.by_id.retain(|_, chan| {
                                if chan.get_counterparty_node_id() == *counterparty_node_id {
                                        chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
                                        if chan.is_shutdown() {
-                                               update_maps_on_chan_removal!(self, short_to_id, chan);
+                                               update_maps_on_chan_removal!(self, short_to_chan_info, chan);
                                                self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer);
                                                return false;
                                        } else {
@@ -6198,7 +6299,7 @@ impl_writeable_tlv_based!(ChannelDetails, {
        (18, outbound_capacity_msat, required),
        // Note that by the time we get past the required read above, outbound_capacity_msat will be
        // filled in, so we can safely unwrap it here.
-       (19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap())),
+       (19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap() as u64)),
        (20, inbound_capacity_msat, required),
        (22, confirmations_required, option),
        (24, force_close_spend_delay, option),
@@ -6631,6 +6732,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
                        (5, self.our_network_pubkey, required),
                        (7, self.fake_scid_rand_bytes, required),
                        (9, htlc_purposes, vec_type),
+                       (11, self.probing_cookie_secret, required),
                });
 
                Ok(())
@@ -6774,7 +6876,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                let channel_count: u64 = Readable::read(reader)?;
                let mut funding_txo_set = HashSet::with_capacity(cmp::min(channel_count as usize, 128));
                let mut by_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
-               let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
+               let mut id_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
+               let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
                let mut channel_closures = Vec::new();
                for _ in 0..channel_count {
                        let mut channel: Channel<Signer> = Channel::read(reader, (&args.keys_manager, best_block_height))?;
@@ -6814,7 +6917,10 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                } else {
                                        log_info!(args.logger, "Successfully loaded channel {}", log_bytes!(channel.channel_id()));
                                        if let Some(short_channel_id) = channel.get_short_channel_id() {
-                                               short_to_id.insert(short_channel_id, channel.channel_id());
+                                               short_to_chan_info.insert(short_channel_id, (channel.get_counterparty_node_id(), channel.channel_id()));
+                                       }
+                                       if channel.is_funding_initiated() {
+                                               id_to_peer.insert(channel.channel_id(), channel.get_counterparty_node_id());
                                        }
                                        by_id.insert(channel.channel_id(), channel);
                                }
@@ -6927,6 +7033,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                let mut pending_outbound_payments = None;
                let mut received_network_pubkey: Option<PublicKey> = None;
                let mut fake_scid_rand_bytes: Option<[u8; 32]> = None;
+               let mut probing_cookie_secret: Option<[u8; 32]> = None;
                let mut claimable_htlc_purposes = None;
                read_tlv_fields!(reader, {
                        (1, pending_outbound_payments_no_retry, option),
@@ -6934,11 +7041,16 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                        (5, received_network_pubkey, option),
                        (7, fake_scid_rand_bytes, option),
                        (9, claimable_htlc_purposes, vec_type),
+                       (11, probing_cookie_secret, option),
                });
                if fake_scid_rand_bytes.is_none() {
                        fake_scid_rand_bytes = Some(args.keys_manager.get_secure_random_bytes());
                }
 
+               if probing_cookie_secret.is_none() {
+                       probing_cookie_secret = Some(args.keys_manager.get_secure_random_bytes());
+               }
+
                if pending_outbound_payments.is_none() && pending_outbound_payments_no_retry.is_none() {
                        pending_outbound_payments = Some(pending_outbound_payments_compat);
                } else if pending_outbound_payments.is_none() {
@@ -7073,7 +7185,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                return Err(DecodeError::InvalidValue);
                        }
                        if chan.is_usable() {
-                               if short_to_id.insert(chan.outbound_scid_alias(), *chan_id).is_some() {
+                               if short_to_chan_info.insert(chan.outbound_scid_alias(), (chan.get_counterparty_node_id(), *chan_id)).is_some() {
                                        // Note that in rare cases its possible to hit this while reading an older
                                        // channel if we just happened to pick a colliding outbound alias above.
                                        log_error!(args.logger, "Got duplicate outbound SCID alias; {}", chan.outbound_scid_alias());
@@ -7082,6 +7194,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                        }
                }
 
+               let bounded_fee_estimator = LowerBoundedFeeEstimator::new(args.fee_estimator);
+
                for (_, monitor) in args.channel_monitors.iter() {
                        for (payment_hash, payment_preimage) in monitor.get_stored_preimages() {
                                if let Some((payment_purpose, claimable_htlcs)) = claimable_htlcs.remove(&payment_hash) {
@@ -7110,7 +7224,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                                        channel.claim_htlc_while_disconnected_dropping_mon_update(claimable_htlc.prev_hop.htlc_id, payment_preimage, &args.logger);
                                                }
                                                if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.outpoint) {
-                                                       previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &args.fee_estimator, &args.logger);
+                                                       previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &bounded_fee_estimator, &args.logger);
                                                }
                                        }
                                        pending_events_read.push(events::Event::PaymentClaimed {
@@ -7124,7 +7238,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
 
                let channel_manager = ChannelManager {
                        genesis_hash,
-                       fee_estimator: args.fee_estimator,
+                       fee_estimator: bounded_fee_estimator,
                        chain_monitor: args.chain_monitor,
                        tx_broadcaster: args.tx_broadcaster,
 
@@ -7132,7 +7246,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
 
                        channel_state: Mutex::new(ChannelHolder {
                                by_id,
-                               short_to_id,
+                               short_to_chan_info,
                                forward_htlcs,
                                claimable_htlcs,
                                pending_msg_events: Vec::new(),
@@ -7142,8 +7256,11 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                        pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
 
                        outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
+                       id_to_peer: Mutex::new(id_to_peer),
                        fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(),
 
+                       probing_cookie_secret: probing_cookie_secret.unwrap(),
+
                        our_network_key,
                        our_network_pubkey,
                        secp_ctx,
@@ -7189,7 +7306,7 @@ mod tests {
        use ln::msgs::ChannelMessageHandler;
        use routing::router::{PaymentParameters, RouteParameters, find_route};
        use util::errors::APIError;
-       use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
+       use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
        use util::test_utils;
        use chain::keysinterface::KeysInterface;
 
@@ -7678,6 +7795,119 @@ mod tests {
                // Check that using the original payment hash succeeds.
                assert!(inbound_payment::verify(payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger).is_ok());
        }
+
+       #[test]
+       fn test_id_to_peer_coverage() {
+               // Test that the `ChannelManager:id_to_peer` contains channels which have been assigned
+               // a `channel_id` (i.e. have had the funding tx created), and that they are removed once
+               // the channel is successfully closed.
+               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.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
+               let open_channel = 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(), InitFeatures::known(), &open_channel);
+               let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+
+               let (temporary_channel_id, tx, _funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
+               let channel_id = &tx.txid().into_inner();
+               {
+                       // Ensure that the `id_to_peer` map is empty until either party has received the
+                       // funding transaction, and have the real `channel_id`.
+                       assert_eq!(nodes[0].node.id_to_peer.lock().unwrap().len(), 0);
+                       assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+               }
+
+               nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
+               {
+                       // Assert that `nodes[0]`'s `id_to_peer` map is populated with the channel as soon as
+                       // as it has the funding transaction.
+                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_0_lock.len(), 1);
+                       assert!(nodes_0_lock.contains_key(channel_id));
+
+                       assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+               }
+
+               let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
+
+               nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
+               {
+                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_0_lock.len(), 1);
+                       assert!(nodes_0_lock.contains_key(channel_id));
+
+                       // Assert that `nodes[1]`'s `id_to_peer` map is populated with the channel as soon as
+                       // as it has the funding transaction.
+                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_1_lock.len(), 1);
+                       assert!(nodes_1_lock.contains_key(channel_id));
+               }
+               check_added_monitors!(nodes[1], 1);
+               let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
+               check_added_monitors!(nodes[0], 1);
+               let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
+               let (announcement, nodes_0_update, nodes_1_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
+               update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &nodes_0_update, &nodes_1_update);
+
+               nodes[0].node.close_channel(channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+               nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()));
+               let nodes_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &nodes_1_shutdown);
+
+               let closing_signed_node_0 = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
+               nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &closing_signed_node_0);
+               {
+                       // Assert that the channel is kept in the `id_to_peer` map for both nodes until the
+                       // channel can be fully closed by both parties (i.e. no outstanding htlcs exists, the
+                       // fee for the closing transaction has been negotiated and the parties has the other
+                       // party's signature for the fee negotiated closing transaction.)
+                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_0_lock.len(), 1);
+                       assert!(nodes_0_lock.contains_key(channel_id));
+
+                       // At this stage, `nodes[1]` has proposed a fee for the closing transaction in the
+                       // `handle_closing_signed` call above. As `nodes[1]` has not yet received the signature
+                       // from `nodes[0]` for the closing transaction with the proposed fee, the channel is
+                       // kept in the `nodes[1]`'s `id_to_peer` map.
+                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_1_lock.len(), 1);
+                       assert!(nodes_1_lock.contains_key(channel_id));
+               }
+
+               nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()));
+               {
+                       // `nodes[0]` accepts `nodes[1]`'s proposed fee for the closing transaction, and
+                       // therefore has all it needs to fully close the channel (both signatures for the
+                       // closing transaction).
+                       // Assert that the channel is removed from `nodes[0]`'s `id_to_peer` map as it can be
+                       // fully closed by `nodes[0]`.
+                       assert_eq!(nodes[0].node.id_to_peer.lock().unwrap().len(), 0);
+
+                       // Assert that the channel is still in `nodes[1]`'s  `id_to_peer` map, as `nodes[1]`
+                       // doesn't have `nodes[0]`'s signature for the closing transaction yet.
+                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       assert_eq!(nodes_1_lock.len(), 1);
+                       assert!(nodes_1_lock.contains_key(channel_id));
+               }
+
+               let (_nodes_0_update, closing_signed_node_0) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id());
+
+               nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &closing_signed_node_0.unwrap());
+               {
+                       // Assert that the channel has now been removed from both parties `id_to_peer` map once
+                       // they both have everything required to fully close the channel.
+                       assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+               }
+               let (_nodes_1_update, _none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id());
+
+               check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure);
+               check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure);
+       }
 }
 
 #[cfg(all(any(test, feature = "_test_utils"), feature = "_bench_unstable"))]
index 9ecbee739f1874eaa0b8cbfca4d19ff7658b5e90..e58b541723c203329a01ea9085314a91e1b8625a 100644 (file)
@@ -13,6 +13,7 @@
 
 use chain;
 use chain::{Confirm, Listen, Watch};
+use chain::chaininterface::LowerBoundedFeeEstimator;
 use chain::channelmonitor;
 use chain::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
 use chain::transaction::OutPoint;
@@ -3489,7 +3490,7 @@ fn test_force_close_fail_back() {
        // Now check that if we add the preimage to ChannelMonitor it broadcasts our HTLC-Success..
        {
                get_monitor!(nodes[2], payment_event.commitment_msg.channel_id)
-                       .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &node_cfgs[2].fee_estimator, &node_cfgs[2].logger);
+                       .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), &node_cfgs[2].logger);
        }
        mine_transaction(&nodes[2], &tx);
        let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -7342,7 +7343,7 @@ fn test_user_configurable_csv_delay() {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
-       if let Err(error) = Channel::new_outbound(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+       if let Err(error) = Channel::new_outbound(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
                &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), 1000000, 1000000, 0,
                &low_our_to_self_config, 0, 42)
        {
@@ -7356,7 +7357,7 @@ fn test_user_configurable_csv_delay() {
        nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None).unwrap();
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
-       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+       if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
                &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
                &low_our_to_self_config, 0, &nodes[0].logger, 42)
        {
@@ -7388,7 +7389,7 @@ fn test_user_configurable_csv_delay() {
        nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None).unwrap();
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
-       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+       if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
                &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
                &high_their_to_self_config, 0, &nodes[0].logger, 42)
        {
index 9522e83d18d1cbfa02ddcbe9d0b7ef91ba2d4925..28c86b79598cf70572069ce55561766a522b3130 100644 (file)
@@ -80,15 +80,15 @@ pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;
 /// payment_hash type, use to cross-lock hop
 /// (C-not exported) as we just use [u8; 32] directly
 #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentHash(pub [u8;32]);
+pub struct PaymentHash(pub [u8; 32]);
 /// payment_preimage type, use to route payment between hop
 /// (C-not exported) as we just use [u8; 32] directly
 #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentPreimage(pub [u8;32]);
+pub struct PaymentPreimage(pub [u8; 32]);
 /// payment_secret type, use to authenticate sender to the receiver and tie MPP HTLCs together
 /// (C-not exported) as we just use [u8; 32] directly
 #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentSecret(pub [u8;32]);
+pub struct PaymentSecret(pub [u8; 32]);
 
 use prelude::*;
 use bitcoin::bech32;
index 0e5b2e07e7a4cea649bc44939a67f2c940f71779..3e44cfcf024034a7de39a614e50cc5a974cfc632 100644 (file)
@@ -40,7 +40,7 @@ use io_extras::read_to_end;
 
 use util::events::MessageSendEventsProvider;
 use util::logger;
-use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt};
+use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
 
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 
@@ -442,6 +442,13 @@ pub enum NetAddress {
                /// The port on which the node is listening
                port: u16,
        },
+       /// A hostname/port on which the peer is listening.
+       Hostname {
+               /// The hostname on which the node is listening.
+               hostname: Hostname,
+               /// The port on which the node is listening.
+               port: u16,
+       },
 }
 impl NetAddress {
        /// Gets the ID of this address type. Addresses in node_announcement messages should be sorted
@@ -452,6 +459,7 @@ impl NetAddress {
                        &NetAddress::IPv6 {..} => { 2 },
                        &NetAddress::OnionV2(_) => { 3 },
                        &NetAddress::OnionV3 {..} => { 4 },
+                       &NetAddress::Hostname {..} => { 5 },
                }
        }
 
@@ -462,11 +470,15 @@ impl NetAddress {
                        &NetAddress::IPv6 { .. } => { 18 },
                        &NetAddress::OnionV2(_) => { 12 },
                        &NetAddress::OnionV3 { .. } => { 37 },
+                       // Consists of 1-byte hostname length, hostname bytes, and 2-byte port.
+                       &NetAddress::Hostname { ref hostname, .. } => { u16::from(hostname.len()) + 3 },
                }
        }
 
-       /// The maximum length of any address descriptor, not including the 1-byte type
-       pub(crate) const MAX_LEN: u16 = 37;
+       /// The maximum length of any address descriptor, not including the 1-byte type.
+       /// This maximum length is reached by a hostname address descriptor:
+       /// a hostname with a maximum length of 255, its 1-byte length and a 2-byte port.
+       pub(crate) const MAX_LEN: u16 = 258;
 }
 
 impl Writeable for NetAddress {
@@ -492,7 +504,12 @@ impl Writeable for NetAddress {
                                checksum.write(writer)?;
                                version.write(writer)?;
                                port.write(writer)?;
-                       }
+                       },
+                       &NetAddress::Hostname { ref hostname, ref port } => {
+                               5u8.write(writer)?;
+                               hostname.write(writer)?;
+                               port.write(writer)?;
+                       },
                }
                Ok(())
        }
@@ -523,6 +540,12 @@ impl Readable for Result<NetAddress, u8> {
                                        port: Readable::read(reader)?,
                                }))
                        },
+                       5 => {
+                               Ok(Ok(NetAddress::Hostname {
+                                       hostname: Readable::read(reader)?,
+                                       port: Readable::read(reader)?,
+                               }))
+                       },
                        _ => return Ok(Err(byte)),
                }
        }
@@ -1829,7 +1852,7 @@ mod tests {
        use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
        use ln::msgs;
        use ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
-       use util::ser::{Writeable, Readable};
+       use util::ser::{Writeable, Readable, Hostname};
 
        use bitcoin::hashes::hex::FromHex;
        use bitcoin::util::address::Address;
@@ -1843,6 +1866,7 @@ mod tests {
 
        use io::Cursor;
        use prelude::*;
+       use core::convert::TryFrom;
 
        #[test]
        fn encoding_channel_reestablish_no_secret() {
@@ -1971,7 +1995,7 @@ mod tests {
                do_encoding_channel_announcement(true, true);
        }
 
-       fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, excess_address_data: bool, excess_data: bool) {
+       fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, hostname: bool, excess_address_data: bool, excess_data: bool) {
                let secp_ctx = Secp256k1::new();
                let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
@@ -2007,6 +2031,12 @@ mod tests {
                                port: 9735
                        });
                }
+               if hostname {
+                       addresses.push(msgs::NetAddress::Hostname {
+                               hostname: Hostname::try_from(String::from("host")).unwrap(),
+                               port: 9735,
+                       });
+               }
                let mut addr_len = 0;
                for addr in &addresses {
                        addr_len += addr.len() + 1;
@@ -2047,6 +2077,9 @@ mod tests {
                if onionv3 {
                        target_value.append(&mut hex::decode("04fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e00020102607").unwrap());
                }
+               if hostname {
+                       target_value.append(&mut hex::decode("0504686f73742607").unwrap());
+               }
                if excess_address_data {
                        target_value.append(&mut hex::decode("216c280b5395a2546e7e4b2663e04f811622f15a4f92e83aa2e92ba2a573c139142c54ae63072a1ec1ee7dc0c04bde5c847806172aa05c92c22ae8e308d1d269").unwrap());
                }
@@ -2058,15 +2091,16 @@ mod tests {
 
        #[test]
        fn encoding_node_announcement() {
-               do_encoding_node_announcement(true, true, true, true, true, true, true);
-               do_encoding_node_announcement(false, false, false, false, false, false, false);
-               do_encoding_node_announcement(false, true, false, false, false, false, false);
-               do_encoding_node_announcement(false, false, true, false, false, false, false);
-               do_encoding_node_announcement(false, false, false, true, false, false, false);
-               do_encoding_node_announcement(false, false, false, false, true, false, false);
-               do_encoding_node_announcement(false, false, false, false, false, true, false);
-               do_encoding_node_announcement(false, true, false, true, false, true, false);
-               do_encoding_node_announcement(false, false, true, false, true, false, false);
+               do_encoding_node_announcement(true, true, true, true, true, true, true, true);
+               do_encoding_node_announcement(false, false, false, false, false, false, false, false);
+               do_encoding_node_announcement(false, true, false, false, false, false, false, false);
+               do_encoding_node_announcement(false, false, true, false, false, false, false, false);
+               do_encoding_node_announcement(false, false, false, true, false, false, false, false);
+               do_encoding_node_announcement(false, false, false, false, true, false, false, false);
+               do_encoding_node_announcement(false, false, false, false, false, true, false, false);
+               do_encoding_node_announcement(false, false, false, false, false, false, true, false);
+               do_encoding_node_announcement(false, true, false, true, false, false, true, false);
+               do_encoding_node_announcement(false, false, true, false, true, false, false, false);
        }
 
        fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {
index 7f725a42141013b778ece0e0b2e5a478c71a5d3c..99c8682738da55467b5866f0c8c751047ff2c001 100644 (file)
@@ -845,3 +845,132 @@ fn get_ldk_payment_preimage() {
        pass_along_path(&nodes[0], &[&nodes[1]], amt_msat, payment_hash, Some(payment_secret), events.pop().unwrap(), true, Some(payment_preimage));
        claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage);
 }
+
+#[test]
+fn sent_probe_is_probe_of_sending_node() {
+       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, None]);
+       let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+
+       // First check we refuse to build a single-hop probe
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000);
+       assert!(nodes[0].node.send_probe(route.paths[0].clone()).is_err());
+
+       // Then build an actual two-hop probing path
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], 100_000);
+
+       match nodes[0].node.send_probe(route.paths[0].clone()) {
+               Ok((payment_hash, payment_id)) => {
+                       assert!(nodes[0].node.payment_is_probe(&payment_hash, &payment_id));
+                       assert!(!nodes[1].node.payment_is_probe(&payment_hash, &payment_id));
+                       assert!(!nodes[2].node.payment_is_probe(&payment_hash, &payment_id));
+               },
+               _ => panic!(),
+       }
+
+       get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+       check_added_monitors!(nodes[0], 1);
+}
+
+#[test]
+fn successful_probe_yields_event() {
+       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, None]);
+       let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], 100_000);
+
+       let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
+
+       // node[0] -- update_add_htlcs -> node[1]
+       check_added_monitors!(nodes[0], 1);
+       let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+       let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]);
+       check_added_monitors!(nodes[1], 0);
+       commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false);
+       expect_pending_htlcs_forwardable!(nodes[1]);
+
+       // node[1] -- update_add_htlcs -> node[2]
+       check_added_monitors!(nodes[1], 1);
+       let updates = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id());
+       let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
+       nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &probe_event.msgs[0]);
+       check_added_monitors!(nodes[2], 0);
+       commitment_signed_dance!(nodes[2], nodes[1], probe_event.commitment_msg, true, true);
+
+       // node[1] <- update_fail_htlcs -- node[2]
+       let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
+       nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+       check_added_monitors!(nodes[1], 0);
+       commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, true);
+
+       // node[0] <- update_fail_htlcs -- node[1]
+       let 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(), &updates.update_fail_htlcs[0]);
+       check_added_monitors!(nodes[0], 0);
+       commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
+
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events.drain(..).next().unwrap() {
+               crate::util::events::Event::ProbeSuccessful { payment_id: ev_pid, payment_hash: ev_ph, .. } => {
+                       assert_eq!(payment_id, ev_pid);
+                       assert_eq!(payment_hash, ev_ph);
+               },
+               _ => panic!(),
+       };
+}
+
+#[test]
+fn failed_probe_yields_event() {
+       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, None]);
+       let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 90000000, InitFeatures::known(), InitFeatures::known());
+
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id());
+
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 9_999_000, 42);
+
+       let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
+
+       // node[0] -- update_add_htlcs -> node[1]
+       check_added_monitors!(nodes[0], 1);
+       let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+       let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]);
+       check_added_monitors!(nodes[1], 0);
+       commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false);
+       expect_pending_htlcs_forwardable!(nodes[1]);
+
+       // node[0] <- update_fail_htlcs -- node[1]
+       check_added_monitors!(nodes[1], 1);
+       let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       // Skip the PendingHTLCsForwardable event
+       let _events = nodes[1].node.get_and_clear_pending_events();
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+       check_added_monitors!(nodes[0], 0);
+       commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
+
+       let mut events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events.drain(..).next().unwrap() {
+               crate::util::events::Event::ProbeFailed { payment_id: ev_pid, payment_hash: ev_ph, .. } => {
+                       assert_eq!(payment_id, ev_pid);
+                       assert_eq!(payment_hash, ev_ph);
+               },
+               _ => panic!(),
+       };
+}
index a7090e4e7355508fb0a7fe10f1106a3a37e7ee78..29349392f761438b311cca2eb98f49ba14bd338f 100644 (file)
@@ -273,7 +273,7 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
 
        let channel_state = nodes[0].node.channel_state.lock().unwrap();
        assert_eq!(channel_state.by_id.len(), 1);
-       assert_eq!(channel_state.short_to_id.len(), 2);
+       assert_eq!(channel_state.short_to_chan_info.len(), 2);
        mem::drop(channel_state);
 
        if !reorg_after_reload {
@@ -293,7 +293,7 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                {
                        let channel_state = nodes[0].node.channel_state.lock().unwrap();
                        assert_eq!(channel_state.by_id.len(), 0);
-                       assert_eq!(channel_state.short_to_id.len(), 0);
+                       assert_eq!(channel_state.short_to_chan_info.len(), 0);
                }
        }
 
@@ -361,7 +361,7 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                {
                        let channel_state = nodes[0].node.channel_state.lock().unwrap();
                        assert_eq!(channel_state.by_id.len(), 0);
-                       assert_eq!(channel_state.short_to_id.len(), 0);
+                       assert_eq!(channel_state.short_to_chan_info.len(), 0);
                }
        }
        // With expect_channel_force_closed set the TestChainMonitor will enforce that the next update
index 420a473ff53a6228a6da7a0781df9b272ec5a1c6..289221601c5c82e92cd2db457dbfff69a5eef460 100644 (file)
@@ -176,10 +176,10 @@ impl_writeable_tlv_based!(RouteParameters, {
 /// Maximum total CTLV difference we allow for a full payment path.
 pub const DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA: u32 = 1008;
 
-/// Maximum number of paths we allow an MPP payment to have.
+/// Maximum number of paths we allow an (MPP) payment to have.
 // The default limit is currently set rather arbitrary - there aren't any real fundamental path-count
 // limits, but for now more than 10 paths likely carries too much one-path failure.
-pub const DEFAULT_MAX_MPP_PATH_COUNT: u8 = 10;
+pub const DEFAULT_MAX_PATH_COUNT: u8 = 10;
 
 // The median hop CLTV expiry delta currently seen in the network.
 const MEDIAN_HOP_CLTV_EXPIRY_DELTA: u32 = 40;
@@ -222,16 +222,16 @@ pub struct PaymentParameters {
        /// Defaults to [`DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA`].
        pub max_total_cltv_expiry_delta: u32,
 
-       /// The maximum number of paths that may be used by MPP payments.
-       /// Defaults to [`DEFAULT_MAX_MPP_PATH_COUNT`].
-       pub max_mpp_path_count: u8,
+       /// The maximum number of paths that may be used by (MPP) payments.
+       /// Defaults to [`DEFAULT_MAX_PATH_COUNT`].
+       pub max_path_count: u8,
 }
 
 impl_writeable_tlv_based!(PaymentParameters, {
        (0, payee_pubkey, required),
        (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)),
        (2, features, option),
-       (3, max_mpp_path_count, (default_value, DEFAULT_MAX_MPP_PATH_COUNT)),
+       (3, max_path_count, (default_value, DEFAULT_MAX_PATH_COUNT)),
        (4, route_hints, vec_type),
        (6, expiry_time, option),
 });
@@ -245,7 +245,7 @@ impl PaymentParameters {
                        route_hints: vec![],
                        expiry_time: None,
                        max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
-                       max_mpp_path_count: DEFAULT_MAX_MPP_PATH_COUNT,
+                       max_path_count: DEFAULT_MAX_PATH_COUNT,
                }
        }
 
@@ -282,11 +282,11 @@ impl PaymentParameters {
                Self { max_total_cltv_expiry_delta, ..self }
        }
 
-       /// Includes a limit for the maximum number of payment paths that may be used by MPP.
+       /// Includes a limit for the maximum number of payment paths that may be used.
        ///
        /// (C-not exported) since bindings don't support move semantics
-       pub fn with_max_mpp_path_count(self, max_mpp_path_count: u8) -> Self {
-               Self { max_mpp_path_count, ..self }
+       pub fn with_max_path_count(self, max_path_count: u8) -> Self {
+               Self { max_path_count, ..self }
        }
 }
 
@@ -800,10 +800,16 @@ where L::Target: Logger {
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
 
+       if payment_params.max_path_count == 0 {
+               return Err(LightningError{err: "Can't find a route with no paths allowed.".to_owned(), action: ErrorAction::IgnoreError});
+       }
+
        // Allow MPP only if we have a features set from somewhere that indicates the payee supports
        // it. If the payee supports it they're supposed to include it in the invoice, so that should
        // work reliably.
-       let allow_mpp = if let Some(features) = &payment_params.features {
+       let allow_mpp = if payment_params.max_path_count == 1 {
+               false
+       } else if let Some(features) = &payment_params.features {
                features.supports_basic_mpp()
        } else if let Some(node) = network_nodes.get(&payee_node_id) {
                if let Some(node_info) = node.announcement_info.as_ref() {
@@ -811,10 +817,6 @@ where L::Target: Logger {
                } else { false }
        } else { false };
 
-       if allow_mpp && payment_params.max_mpp_path_count == 0 {
-               return Err(LightningError{err: "Can't find an MPP route with no paths allowed.".to_owned(), action: ErrorAction::IgnoreError});
-       }
-
        log_trace!(logger, "Searching for a route from payer {} to payee {} {} MPP and {} first hops {}overriding the network graph", our_node_pubkey,
                payment_params.payee_pubkey, if allow_mpp { "with" } else { "without" },
                first_hops.map(|hops| hops.len()).unwrap_or(0), if first_hops.is_some() { "" } else { "not " });
@@ -872,10 +874,10 @@ where L::Target: Logger {
        // Taking too many smaller paths also increases the chance of payment failure.
        // Thus to avoid this effect, we require from our collected links to provide
        // at least a minimal contribution to the recommended value yet-to-be-fulfilled.
-       // This requirement is currently set to be 1/max_mpp_path_count of the payment
+       // This requirement is currently set to be 1/max_path_count of the payment
        // value to ensure we only ever return routes that do not violate this limit.
        let minimal_value_contribution_msat: u64 = if allow_mpp {
-               (final_value_msat + (payment_params.max_mpp_path_count as u64 - 1)) / payment_params.max_mpp_path_count as u64
+               (final_value_msat + (payment_params.max_path_count as u64 - 1)) / payment_params.max_path_count as u64
        } else {
                final_value_msat
        };
@@ -1694,7 +1696,7 @@ where L::Target: Logger {
                selected_paths.push(path);
        }
        // Make sure we would never create a route with more paths than we allow.
-       debug_assert!(selected_paths.len() <= payment_params.max_mpp_path_count.into());
+       debug_assert!(selected_paths.len() <= payment_params.max_path_count.into());
 
        if let Some(features) = &payment_params.features {
                for path in selected_paths.iter_mut() {
@@ -1849,6 +1851,10 @@ fn build_route_from_hops_internal<L: Deref>(
                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]) {}
        }
 
        impl<'a> Writeable for HopScorer {
@@ -1876,7 +1882,7 @@ fn build_route_from_hops_internal<L: Deref>(
 
 #[cfg(test)]
 mod tests {
-       use routing::gossip::{NetworkGraph, P2PGossipSync, NodeId};
+       use routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
        use 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};
@@ -4119,20 +4125,20 @@ mod tests {
                }
 
                {
-                       // Attempt to route while setting max_mpp_path_count to 0 results in a failure.
-                       let zero_payment_params = payment_params.clone().with_max_mpp_path_count(0);
+                       // Attempt to route while setting max_path_count to 0 results in a failure.
+                       let zero_payment_params = payment_params.clone().with_max_path_count(0);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
                                &our_id, &zero_payment_params, &network_graph.read_only(), None, 100, 42,
                                Arc::clone(&logger), &scorer, &random_seed_bytes) {
-                                       assert_eq!(err, "Can't find an MPP route with no paths allowed.");
+                                       assert_eq!(err, "Can't find a route with no paths allowed.");
                        } else { panic!(); }
                }
 
                {
-                       // Attempt to route while setting max_mpp_path_count to 3 results in a failure.
+                       // Attempt to route while setting max_path_count to 3 results in a failure.
                        // This is the case because the minimal_value_contribution_msat would require each path
                        // to account for 1/3 of the total value, which is violated by 2 out of 3 paths.
-                       let fail_payment_params = payment_params.clone().with_max_mpp_path_count(3);
+                       let fail_payment_params = payment_params.clone().with_max_path_count(3);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
                                &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000, 42,
                                Arc::clone(&logger), &scorer, &random_seed_bytes) {
@@ -5314,6 +5320,8 @@ mod tests {
 
                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 BadNodeScorer {
@@ -5332,6 +5340,8 @@ mod tests {
 
                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]) {}
        }
 
        #[test]
@@ -5717,7 +5727,7 @@ mod tests {
        }
 
        #[test]
-       fn avoids_banned_nodes() {
+       fn honors_manual_penalties() {
                let (secp_ctx, network_graph, _, _, logger) = build_line_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
 
@@ -5727,7 +5737,17 @@ mod tests {
                let scorer_params = ProbabilisticScoringParameters::default();
                let mut scorer = ProbabilisticScorer::new(scorer_params, Arc::clone(&network_graph), Arc::clone(&logger));
 
-               // First check we can get a route.
+               // First check set manual penalties are returned by the scorer.
+               let usage = ChannelUsage {
+                       amount_msat: 0,
+                       inflight_htlc_msat: 0,
+                       effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: Some(1_000) },
+               };
+               scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
+               scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
+               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 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());
index 524f0ed3158b40dabae37d9516009a2588b6cd08..4922fad78476f56d62e6c5ebe859ce36323c93bf 100644 (file)
@@ -102,6 +102,12 @@ pub trait Score $(: $supertrait)* {
 
        /// Handles updating channel penalties after successfully routing along a path.
        fn payment_path_successful(&mut self, path: &[&RouteHop]);
+
+       /// Handles updating channel penalties after a probe over the given path failed.
+       fn probe_failed(&mut self, path: &[&RouteHop], short_channel_id: u64);
+
+       /// Handles updating channel penalties after a probe over the given path succeeded.
+       fn probe_successful(&mut self, path: &[&RouteHop]);
 }
 
 impl<S: Score, T: DerefMut<Target=S> $(+ $supertrait)*> Score for T {
@@ -118,6 +124,14 @@ impl<S: Score, T: DerefMut<Target=S> $(+ $supertrait)*> Score for T {
        fn payment_path_successful(&mut self, path: &[&RouteHop]) {
                self.deref_mut().payment_path_successful(path)
        }
+
+       fn probe_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
+               self.deref_mut().probe_failed(path, short_channel_id)
+       }
+
+       fn probe_successful(&mut self, path: &[&RouteHop]) {
+               self.deref_mut().probe_successful(path)
+       }
 }
 } }
 
@@ -241,6 +255,10 @@ impl Score for FixedPenaltyScorer {
        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]) {}
 }
 
 impl Writeable for FixedPenaltyScorer {
@@ -362,10 +380,12 @@ pub struct ProbabilisticScoringParameters {
        /// Default value: 256 msat
        pub amount_penalty_multiplier_msat: u64,
 
-       /// A list of nodes that won't be considered during path finding.
+       /// Manual penalties used for the given nodes. Allows to set a particular penalty for a given
+       /// node. Note that a manual penalty of `u64::max_value()` means the node would not ever be
+       /// considered during path finding.
        ///
        /// (C-not exported)
-       pub banned_nodes: HashSet<NodeId>,
+       pub manual_node_penalties: HashMap<NodeId, u64>,
 
        /// This penalty is applied when `htlc_maximum_msat` is equal to or larger than half of the
        /// channel's capacity, which makes us prefer nodes with a smaller `htlc_maximum_msat`. We
@@ -468,17 +488,27 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
        /// Marks the node with the given `node_id` as banned, i.e.,
        /// it will be avoided during path finding.
        pub fn add_banned(&mut self, node_id: &NodeId) {
-               self.params.banned_nodes.insert(*node_id);
+               self.params.manual_node_penalties.insert(*node_id, u64::max_value());
        }
 
        /// Removes the node with the given `node_id` from the list of nodes to avoid.
        pub fn remove_banned(&mut self, node_id: &NodeId) {
-               self.params.banned_nodes.remove(node_id);
+               self.params.manual_node_penalties.remove(node_id);
        }
 
-       /// Clears the list of nodes that are avoided during path finding.
-       pub fn clear_banned(&mut self) {
-               self.params.banned_nodes = HashSet::new();
+       /// Sets a manual penalty for the given node.
+       pub fn set_manual_penalty(&mut self, node_id: &NodeId, penalty: u64) {
+               self.params.manual_node_penalties.insert(*node_id, penalty);
+       }
+
+       /// Removes the node with the given `node_id` from the list of manual penalties.
+       pub fn remove_manual_penalty(&mut self, node_id: &NodeId) {
+               self.params.manual_node_penalties.remove(node_id);
+       }
+
+       /// Clears the list of manual penalties that are applied during path finding.
+       pub fn clear_manual_penalties(&mut self) {
+               self.params.manual_node_penalties = HashMap::new();
        }
 }
 
@@ -490,7 +520,7 @@ impl ProbabilisticScoringParameters {
                        liquidity_penalty_multiplier_msat: 0,
                        liquidity_offset_half_life: Duration::from_secs(3600),
                        amount_penalty_multiplier_msat: 0,
-                       banned_nodes: HashSet::new(),
+                       manual_node_penalties: HashMap::new(),
                        anti_probing_penalty_msat: 0,
                }
        }
@@ -499,7 +529,7 @@ impl ProbabilisticScoringParameters {
        /// they will be avoided during path finding.
        pub fn add_banned_from_list(&mut self, node_ids: Vec<NodeId>) {
                for id in node_ids {
-                       self.banned_nodes.insert(id);
+                       self.manual_node_penalties.insert(id, u64::max_value());
                }
        }
 }
@@ -511,7 +541,7 @@ impl Default for ProbabilisticScoringParameters {
                        liquidity_penalty_multiplier_msat: 40_000,
                        liquidity_offset_half_life: Duration::from_secs(3600),
                        amount_penalty_multiplier_msat: 256,
-                       banned_nodes: HashSet::new(),
+                       manual_node_penalties: HashMap::new(),
                        anti_probing_penalty_msat: 250,
                }
        }
@@ -713,8 +743,8 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
        fn channel_penalty_msat(
                &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage
        ) -> u64 {
-               if self.params.banned_nodes.contains(source) || self.params.banned_nodes.contains(target) {
-                       return u64::max_value();
+               if let Some(penalty) = self.params.manual_node_penalties.get(target) {
+                       return *penalty;
                }
 
                let mut anti_probing_penalty_msat = 0;
@@ -811,6 +841,14 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
                        }
                }
        }
+
+       fn probe_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
+               self.payment_path_failed(path, short_channel_id)
+       }
+
+       fn probe_successful(&mut self, path: &[&RouteHop]) {
+               self.payment_path_failed(path, u64::max_value())
+       }
 }
 
 mod approx {
@@ -1177,10 +1215,22 @@ impl<T: Time> Readable for ChannelLiquidity<T> {
                        (2, max_liquidity_offset_msat, required),
                        (4, duration_since_epoch, required),
                });
+               // On rust prior to 1.60 `Instant::duration_since` will panic if time goes backwards.
+               // We write `last_updated` as wallclock time even though its ultimately an `Instant` (which
+               // is a time from a monotonic clock usually represented as an offset against boot time).
+               // Thus, we have to construct an `Instant` by subtracting the difference in wallclock time
+               // from the one that was written. However, because `Instant` can panic if we construct one
+               // in the future, we must handle wallclock time jumping backwards, which we do by simply
+               // using `Instant::now()` in that case.
+               let wall_clock_now = T::duration_since_epoch();
+               let now = T::now();
+               let last_updated = if wall_clock_now > duration_since_epoch {
+                       now - (wall_clock_now - duration_since_epoch)
+               } else { now };
                Ok(Self {
                        min_liquidity_offset_msat,
                        max_liquidity_offset_msat,
-                       last_updated: T::now() - (T::duration_since_epoch() - duration_since_epoch),
+                       last_updated,
                })
        }
 }
index be7accc18dacfc837d89bddcec937e0e9eb4b349..2f65e958f8b60d0f0a0f72d3cd3b7ca1b009085a 100644 (file)
@@ -407,9 +407,9 @@ impl ::util::ser::Readable for LegacyChannelConfig {
                let mut forwarding_fee_base_msat = 0;
                read_tlv_fields!(reader, {
                        (0, forwarding_fee_proportional_millionths, required),
-                       (1, max_dust_htlc_exposure_msat, (default_value, 5_000_000)),
+                       (1, max_dust_htlc_exposure_msat, (default_value, 5_000_000u64)),
                        (2, cltv_expiry_delta, required),
-                       (3, force_close_avoidance_max_fee_satoshis, (default_value, 1000)),
+                       (3, force_close_avoidance_max_fee_satoshis, (default_value, 1000u64)),
                        (4, announced_channel, required),
                        (6, commit_upfront_shutdown_pubkey, required),
                        (8, forwarding_fee_base_msat, required),
index caba7753f3fbb9bbf9b5364f6ab2488f8e6a6503..2282ea55ab36211576b4726645af7579179001f8 100644 (file)
@@ -382,6 +382,38 @@ pub enum Event {
 #[cfg(test)]
                error_data: Option<Vec<u8>>,
        },
+       /// Indicates that a probe payment we sent returned successful, i.e., only failed at the destination.
+       ProbeSuccessful {
+               /// The id returned by [`ChannelManager::send_probe`].
+               ///
+               /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
+               payment_id: PaymentId,
+               /// The hash generated by [`ChannelManager::send_probe`].
+               ///
+               /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
+               payment_hash: PaymentHash,
+               /// The payment path that was successful.
+               path: Vec<RouteHop>,
+       },
+       /// Indicates that a probe payment we sent failed at an intermediary node on the path.
+       ProbeFailed {
+               /// The id returned by [`ChannelManager::send_probe`].
+               ///
+               /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
+               payment_id: PaymentId,
+               /// The hash generated by [`ChannelManager::send_probe`].
+               ///
+               /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
+               payment_hash: PaymentHash,
+               /// The payment path that failed.
+               path: Vec<RouteHop>,
+               /// The channel responsible for the failed probe.
+               ///
+               /// Note that for route hints or for the first hop in a path this may be an SCID alias and
+               /// may not refer to a channel in the public network graph. These aliases may also collide
+               /// with channels in the public network graph.
+               short_channel_id: Option<u64>,
+       },
        /// Used to indicate that [`ChannelManager::process_pending_htlc_forwards`] should be called at
        /// a time in the future.
        ///
@@ -635,6 +667,23 @@ impl Writeable for Event {
                                        (4, amount_msat, required),
                                });
                        },
+                       &Event::ProbeSuccessful { ref payment_id, ref payment_hash, ref path } => {
+                               21u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_id, required),
+                                       (2, payment_hash, required),
+                                       (4, path, vec_type)
+                               })
+                       },
+                       &Event::ProbeFailed { ref payment_id, ref payment_hash, ref path, ref short_channel_id } => {
+                               23u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_id, required),
+                                       (2, payment_hash, required),
+                                       (4, path, vec_type),
+                                       (6, short_channel_id, option),
+                               })
+                       },
                        // Note that, going forward, all new events must only write data inside of
                        // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
                        // data via `write_tlv_fields`.
@@ -854,6 +903,45 @@ impl MaybeReadable for Event {
                                };
                                f()
                        },
+                       21u8 => {
+                               let f = || {
+                                       let mut payment_id = PaymentId([0; 32]);
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_id, required),
+                                               (2, payment_hash, required),
+                                               (4, path, vec_type),
+                                       });
+                                       Ok(Some(Event::ProbeSuccessful {
+                                               payment_id,
+                                               payment_hash,
+                                               path: path.unwrap(),
+                                       }))
+                               };
+                               f()
+                       },
+                       23u8 => {
+                               let f = || {
+                                       let mut payment_id = PaymentId([0; 32]);
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+                                       let mut short_channel_id = None;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_id, required),
+                                               (2, payment_hash, required),
+                                               (4, path, vec_type),
+                                               (6, short_channel_id, option),
+                                       });
+                                       Ok(Some(Event::ProbeFailed{
+                                               payment_id,
+                                               payment_hash,
+                                               path: path.unwrap(),
+                                               short_channel_id,
+                                       }))
+                               };
+                               f()
+                       },
                        // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
                        // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
                        // reads.
index a45806eef54a1434eada0da1d3f1d179d48f9285..5b1a86a6a95f27a276f1dc221bd705f57fbf8ed4 100644 (file)
@@ -16,6 +16,8 @@ use io_extras::{copy, sink};
 use core::hash::Hash;
 use sync::Mutex;
 use core::cmp;
+use core::convert::TryFrom;
+use core::ops::Deref;
 
 use bitcoin::secp256k1::{PublicKey, SecretKey};
 use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE};
@@ -266,6 +268,12 @@ impl<T: Readable> Readable for OptionDeserWrapper<T> {
                Ok(Self(Some(Readable::read(reader)?)))
        }
 }
+/// When handling default_values, we want to map the default-value T directly
+/// to a OptionDeserWrapper<T> in a way that works for `field: T = t;` as
+/// well. Thus, we assume `Into<T> for T` does nothing and use that.
+impl<T: Readable> From<T> for OptionDeserWrapper<T> {
+       fn from(t: T) -> OptionDeserWrapper<T> { OptionDeserWrapper(Some(t)) }
+}
 
 /// Wrapper to write each element of a Vec with no length prefix
 pub(crate) struct VecWriteWrapper<'a, T: Writeable>(pub &'a Vec<T>);
@@ -935,6 +943,75 @@ impl Readable for String {
        }
 }
 
+/// Represents a hostname for serialization purposes.
+/// Only the character set and length will be validated.
+/// The character set consists of ASCII alphanumeric characters, hyphens, and periods.
+/// Its length is guaranteed to be representable by a single byte.
+/// This serialization is used by BOLT 7 hostnames.
+#[derive(Clone, Debug, PartialEq)]
+pub struct Hostname(String);
+impl Hostname {
+       /// Returns the length of the hostname.
+       pub fn len(&self) -> u8 {
+               (&self.0).len() as u8
+       }
+}
+impl Deref for Hostname {
+       type Target = String;
+
+       fn deref(&self) -> &Self::Target {
+               &self.0
+       }
+}
+impl From<Hostname> for String {
+       fn from(hostname: Hostname) -> Self {
+               hostname.0
+       }
+}
+impl TryFrom<Vec<u8>> for Hostname {
+       type Error = ();
+
+       fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
+               if let Ok(s) = String::from_utf8(bytes) {
+                       Hostname::try_from(s)
+               } else {
+                       Err(())
+               }
+       }
+}
+impl TryFrom<String> for Hostname {
+       type Error = ();
+
+       fn try_from(s: String) -> Result<Self, Self::Error> {
+               if s.len() <= 255 && s.chars().all(|c|
+                       c.is_ascii_alphanumeric() ||
+                       c == '.' ||
+                       c == '-'
+               ) {
+                       Ok(Hostname(s))
+               } else {
+                       Err(())
+               }
+       }
+}
+impl Writeable for Hostname {
+       #[inline]
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.len().write(w)?;
+               w.write_all(self.as_bytes())
+       }
+}
+impl Readable for Hostname {
+       #[inline]
+       fn read<R: Read>(r: &mut R) -> Result<Hostname, DecodeError> {
+               let len: u8 = Readable::read(r)?;
+               let mut vec = Vec::with_capacity(len.into());
+               vec.resize(len.into(), 0);
+               r.read_exact(&mut vec)?;
+               Hostname::try_from(vec).map_err(|_| DecodeError::InvalidValue)
+       }
+}
+
 impl Writeable for Duration {
        #[inline]
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -950,3 +1027,29 @@ impl Readable for Duration {
                Ok(Duration::new(secs, nanos))
        }
 }
+
+#[cfg(test)]
+mod tests {
+       use core::convert::TryFrom;
+       use util::ser::{Readable, Hostname, Writeable};
+
+       #[test]
+       fn hostname_conversion() {
+               assert_eq!(Hostname::try_from(String::from("a-test.com")).unwrap().as_str(), "a-test.com");
+
+               assert!(Hostname::try_from(String::from("\"")).is_err());
+               assert!(Hostname::try_from(String::from("$")).is_err());
+               assert!(Hostname::try_from(String::from("⚡")).is_err());
+               let mut large_vec = Vec::with_capacity(256);
+               large_vec.resize(256, b'A');
+               assert!(Hostname::try_from(String::from_utf8(large_vec).unwrap()).is_err());
+       }
+
+       #[test]
+       fn hostname_serialization() {
+               let hostname = Hostname::try_from(String::from("test")).unwrap();
+               let mut buf: Vec<u8> = Vec::new();
+               hostname.write(&mut buf).unwrap();
+               assert_eq!(Hostname::read(&mut buf.as_slice()).unwrap().as_str(), "test");
+       }
+}
index 816426b1133cb21a1e703129e6aecfa884f2c00c..351c2a1f5e25e4d21ad0c999e2f064bf366a6f35 100644 (file)
@@ -99,7 +99,7 @@ macro_rules! check_tlv_order {
                #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always true
                let invalid_order = ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type;
                if invalid_order {
-                       $field = $default;
+                       $field = $default.into();
                }
        }};
        ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required) => {{
@@ -128,7 +128,7 @@ macro_rules! check_missing_tlv {
                #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always true
                let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type;
                if missing_req_type {
-                       $field = $default;
+                       $field = $default.into();
                }
        }};
        ($last_seen_type: expr, $type: expr, $field: ident, required) => {{
@@ -349,7 +349,7 @@ macro_rules! read_tlv_fields {
 
 macro_rules! init_tlv_based_struct_field {
        ($field: ident, (default_value, $default: expr)) => {
-               $field
+               $field.0.unwrap()
        };
        ($field: ident, option) => {
                $field
@@ -364,7 +364,7 @@ macro_rules! init_tlv_based_struct_field {
 
 macro_rules! init_tlv_field_var {
        ($field: ident, (default_value, $default: expr)) => {
-               let mut $field = $default;
+               let mut $field = ::util::ser::OptionDeserWrapper(None);
        };
        ($field: ident, required) => {
                let mut $field = ::util::ser::OptionDeserWrapper(None);