]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Merge pull request #3086 from alecchendev/2024-05-holder-commitment
authorvalentinewallace <valentinewallace@users.noreply.github.com>
Mon, 10 Jun 2024 22:30:09 +0000 (18:30 -0400)
committerGitHub <noreply@github.com>
Mon, 10 Jun 2024 22:30:09 +0000 (18:30 -0400)
Add `HolderCommitmentPoint` struct to track commitment points

232 files changed:
.github/workflows/build.yml
ci/check-cfg-flags.py
ci/check-compiles.sh
ci/rustfmt.sh
fuzz/Cargo.toml
fuzz/ci-fuzz.sh
fuzz/src/base32.rs
fuzz/src/bin/base32_target.rs
fuzz/src/bin/bech32_parse_target.rs
fuzz/src/bin/bolt11_deser_target.rs
fuzz/src/bin/chanmon_consistency_target.rs
fuzz/src/bin/chanmon_deser_target.rs
fuzz/src/bin/fromstr_to_netaddress_target.rs
fuzz/src/bin/full_stack_target.rs
fuzz/src/bin/indexedmap_target.rs
fuzz/src/bin/invoice_deser_target.rs
fuzz/src/bin/invoice_request_deser_target.rs
fuzz/src/bin/msg_accept_channel_target.rs
fuzz/src/bin/msg_accept_channel_v2_target.rs
fuzz/src/bin/msg_announcement_signatures_target.rs
fuzz/src/bin/msg_channel_announcement_target.rs
fuzz/src/bin/msg_channel_details_target.rs
fuzz/src/bin/msg_channel_ready_target.rs
fuzz/src/bin/msg_channel_reestablish_target.rs
fuzz/src/bin/msg_channel_update_target.rs
fuzz/src/bin/msg_closing_signed_target.rs
fuzz/src/bin/msg_commitment_signed_target.rs
fuzz/src/bin/msg_decoded_onion_error_packet_target.rs
fuzz/src/bin/msg_error_message_target.rs
fuzz/src/bin/msg_funding_created_target.rs
fuzz/src/bin/msg_funding_signed_target.rs
fuzz/src/bin/msg_gossip_timestamp_filter_target.rs
fuzz/src/bin/msg_init_target.rs
fuzz/src/bin/msg_node_announcement_target.rs
fuzz/src/bin/msg_open_channel_target.rs
fuzz/src/bin/msg_open_channel_v2_target.rs
fuzz/src/bin/msg_ping_target.rs
fuzz/src/bin/msg_pong_target.rs
fuzz/src/bin/msg_query_channel_range_target.rs
fuzz/src/bin/msg_query_short_channel_ids_target.rs
fuzz/src/bin/msg_reply_channel_range_target.rs
fuzz/src/bin/msg_reply_short_channel_ids_end_target.rs
fuzz/src/bin/msg_revoke_and_ack_target.rs
fuzz/src/bin/msg_shutdown_target.rs
fuzz/src/bin/msg_splice_ack_target.rs
fuzz/src/bin/msg_splice_locked_target.rs
fuzz/src/bin/msg_splice_target.rs
fuzz/src/bin/msg_stfu_target.rs
fuzz/src/bin/msg_tx_abort_target.rs
fuzz/src/bin/msg_tx_ack_rbf_target.rs
fuzz/src/bin/msg_tx_add_input_target.rs
fuzz/src/bin/msg_tx_add_output_target.rs
fuzz/src/bin/msg_tx_complete_target.rs
fuzz/src/bin/msg_tx_init_rbf_target.rs
fuzz/src/bin/msg_tx_remove_input_target.rs
fuzz/src/bin/msg_tx_remove_output_target.rs
fuzz/src/bin/msg_tx_signatures_target.rs
fuzz/src/bin/msg_update_add_htlc_target.rs
fuzz/src/bin/msg_update_fail_htlc_target.rs
fuzz/src/bin/msg_update_fail_malformed_htlc_target.rs
fuzz/src/bin/msg_update_fee_target.rs
fuzz/src/bin/msg_update_fulfill_htlc_target.rs
fuzz/src/bin/offer_deser_target.rs
fuzz/src/bin/onion_hop_data_target.rs
fuzz/src/bin/onion_message_target.rs
fuzz/src/bin/peer_crypt_target.rs
fuzz/src/bin/process_network_graph_target.rs
fuzz/src/bin/refund_deser_target.rs
fuzz/src/bin/router_target.rs
fuzz/src/bin/target_template.txt
fuzz/src/bin/zbase32_target.rs
fuzz/src/bolt11_deser.rs
fuzz/src/chanmon_consistency.rs
fuzz/src/chanmon_deser.rs
fuzz/src/fromstr_to_netaddress.rs
fuzz/src/full_stack.rs
fuzz/src/indexedmap.rs
fuzz/src/invoice_request_deser.rs
fuzz/src/lib.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_accept_channel_v2.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
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_open_channel.rs
fuzz/src/msg_targets/msg_open_channel_v2.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_splice.rs
fuzz/src/msg_targets/msg_splice_ack.rs
fuzz/src/msg_targets/msg_splice_locked.rs
fuzz/src/msg_targets/msg_stfu.rs
fuzz/src/msg_targets/msg_target_template.txt
fuzz/src/msg_targets/msg_tx_abort.rs
fuzz/src/msg_targets/msg_tx_ack_rbf.rs
fuzz/src/msg_targets/msg_tx_add_input.rs
fuzz/src/msg_targets/msg_tx_add_output.rs
fuzz/src/msg_targets/msg_tx_complete.rs
fuzz/src/msg_targets/msg_tx_init_rbf.rs
fuzz/src/msg_targets/msg_tx_remove_input.rs
fuzz/src/msg_targets/msg_tx_remove_output.rs
fuzz/src/msg_targets/msg_tx_signatures.rs
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/msg_targets/utils.rs
fuzz/src/offer_deser.rs
fuzz/src/onion_hop_data.rs
fuzz/src/onion_message.rs
fuzz/src/peer_crypt.rs
fuzz/src/process_network_graph.rs
fuzz/src/refund_deser.rs
fuzz/src/router.rs
fuzz/src/utils/test_logger.rs
fuzz/src/utils/test_persister.rs
lightning-background-processor/Cargo.toml
lightning-background-processor/src/lib.rs
lightning-block-sync/Cargo.toml
lightning-block-sync/src/convert.rs
lightning-block-sync/src/init.rs
lightning-block-sync/src/lib.rs
lightning-block-sync/src/poll.rs
lightning-block-sync/src/test_utils.rs
lightning-block-sync/src/utils.rs
lightning-custom-message/Cargo.toml
lightning-custom-message/src/lib.rs
lightning-invoice/Cargo.toml
lightning-invoice/src/de.rs
lightning-invoice/src/lib.rs
lightning-invoice/src/ser.rs
lightning-invoice/src/utils.rs
lightning-invoice/tests/ser_de.rs
lightning-net-tokio/Cargo.toml
lightning-persister/Cargo.toml
lightning-persister/src/fs_store.rs
lightning-persister/src/test_utils.rs
lightning-rapid-gossip-sync/Cargo.toml
lightning-transaction-sync/Cargo.toml
lightning-transaction-sync/src/common.rs
lightning-transaction-sync/src/electrum.rs
lightning-transaction-sync/src/error.rs
lightning-transaction-sync/src/esplora.rs
lightning-transaction-sync/src/lib.rs
lightning-transaction-sync/tests/integration_tests.rs
lightning/Cargo.toml
lightning/src/blinded_path/payment.rs
lightning/src/chain/chainmonitor.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/mod.rs
lightning/src/chain/onchaintx.rs
lightning/src/chain/package.rs
lightning/src/chain/transaction.rs
lightning/src/events/bump_transaction.rs
lightning/src/events/mod.rs
lightning/src/ln/async_signer_tests.rs
lightning/src/ln/blinded_payment_tests.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channel.rs
lightning/src/ln/channel_state.rs [new file with mode: 0644]
lightning/src/ln/channelmanager.rs
lightning/src/ln/features.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/interactivetxs.rs
lightning/src/ln/max_payment_path_len_tests.rs
lightning/src/ln/mod.rs
lightning/src/ln/monitor_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/offers_tests.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/outbound_payment.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/peer_handler.rs
lightning/src/ln/priv_short_conf_tests.rs
lightning/src/ln/reload_tests.rs
lightning/src/ln/reorg_tests.rs
lightning/src/ln/script.rs
lightning/src/ln/shutdown_tests.rs
lightning/src/ln/types.rs
lightning/src/offers/invoice.rs
lightning/src/offers/invoice_request.rs
lightning/src/offers/merkle.rs
lightning/src/offers/offer.rs
lightning/src/offers/parse.rs
lightning/src/offers/refund.rs
lightning/src/offers/signer.rs
lightning/src/offers/test_utils.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/routing/gossip.rs
lightning/src/routing/router.rs
lightning/src/routing/scoring.rs
lightning/src/routing/test_utils.rs
lightning/src/routing/utxo.rs
lightning/src/sign/mod.rs
lightning/src/util/async_poll.rs [new file with mode: 0644]
lightning/src/util/fuzz_wrappers.rs
lightning/src/util/invoice.rs
lightning/src/util/message_signing.rs
lightning/src/util/mod.rs
lightning/src/util/persist.rs
lightning/src/util/scid_utils.rs
lightning/src/util/ser.rs
lightning/src/util/test_channel_signer.rs
lightning/src/util/test_utils.rs
lightning/src/util/transaction_utils.rs
rustfmt_excluded_files

index eb930f6fcfface6e777eea82b1efcca3dad8edc9..37443c288168bd746f3863ece6a80b99e6d20043 100644 (file)
@@ -192,7 +192,7 @@ jobs:
         run: |
           cd fuzz && cargo update -p regex --precise "1.9.6" --verbose && cd ..
       - name: Sanity check fuzz targets on Rust ${{ env.TOOLCHAIN }}
-        run: cd fuzz && RUSTFLAGS="--cfg=fuzzing" cargo test --verbose --color always
+        run: cd fuzz && RUSTFLAGS="--cfg=fuzzing --cfg=secp256k1_fuzz --cfg=hashes_fuzz" cargo test --verbose --color always
       - name: Run fuzzers
         run: cd fuzz && ./ci-fuzz.sh && cd ..
 
index fd514da657bfd8a12801eea16a9cf8fedd13aac6..c33e8aa3a15015fb7e7c470def921d633cb2ceb9 100755 (executable)
@@ -82,6 +82,10 @@ def check_target_os(os):
 def check_cfg_tag(cfg):
     if cfg == "fuzzing":
         pass
+    elif cfg == "secp256k1_fuzz":
+        pass
+    elif cfg == "hashes_fuzz":
+        pass
     elif cfg == "test":
         pass
     elif cfg == "debug_assertions":
index af88bceee01127667377c294c69429ae0c2e4630..2fe62be787ed60e95fe45af20651d3fc63843a42 100755 (executable)
@@ -5,6 +5,6 @@ echo Testing $(git log -1 --oneline)
 cargo check
 cargo doc
 cargo doc --document-private-items
-cd fuzz && RUSTFLAGS="--cfg=fuzzing" cargo check --features=stdin_fuzz
+cd fuzz && RUSTFLAGS="--cfg=fuzzing --cfg=secp256k1_fuzz --cfg=hashes_fuzz" cargo check --features=stdin_fuzz
 cd ../lightning && cargo check --no-default-features --features=no-std
 cd .. && RUSTC_BOOTSTRAP=1 RUSTFLAGS="--cfg=c_bindings" cargo check -Z avoid-dev-deps
index a1fdf6bd7f3282ff669944335e9d029d2a21989f..1039429bc6ae5e6cf7a377ad6a679eee143609a5 100755 (executable)
@@ -15,5 +15,5 @@ TMP_FILE=$(mktemp)
 find . -name '*.rs' -type f |sort >$TMP_FILE
 for file in $(comm -23 $TMP_FILE rustfmt_excluded_files); do
        echo "Checking formatting of $file"
-       rustfmt $VERS --check $file
+       rustfmt $VERS --edition 2021 --check $file
 done
index c14fce790ff53c4c8245460fc61f314a211bd3d8..4d9f7e0dea33697c8ec85cad904c737a2ffde4b0 100644 (file)
@@ -21,7 +21,8 @@ stdin_fuzz = []
 lightning = { path = "../lightning", features = ["regex", "hashbrown", "_test_utils"] }
 lightning-invoice = { path = "../lightning-invoice" }
 lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
-bitcoin = { version = "0.30.2", features = ["secp-lowmemory"] }
+bech32 = "0.9.1"
+bitcoin = { version = "0.31.2", features = ["secp-lowmemory"] }
 hex = { package = "hex-conservative", version = "0.1.1", default-features = false }
 
 afl = { version = "0.12", optional = true }
index 969505ca88d1bf1e227fd1eeee73c26c13dea741..5a5a8f7f803f8b73c9d96135a3ba1d2a5a5380e9 100755 (executable)
@@ -15,7 +15,11 @@ popd
 
 cargo install --color always --force honggfuzz --no-default-features
 sed -i 's/lto = true//' Cargo.toml
-HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" cargo --color always hfuzz build
+
+export RUSTFLAGS="--cfg=secp256k1_fuzz --cfg=hashes_fuzz"
+export HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz"
+
+cargo --color always hfuzz build
 for TARGET in src/bin/*.rs; do
        FILENAME=$(basename $TARGET)
        FILE="${FILENAME%.*}"
@@ -28,7 +32,7 @@ for TARGET in src/bin/*.rs; do
                HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -N1000000"
        fi
        export HFUZZ_RUN_ARGS
-       HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" cargo --color always hfuzz run $FILE
+       cargo --color always hfuzz run $FILE
        if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then
                cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT
                for CASE in hfuzz_workspace/$FILE/SIG*; do
index 8171f19f637a00fc9fc18144d12ab4ebff699e54..c0d71dd7b3300edbc4638520ad71471a3ecdd90a 100644 (file)
@@ -16,9 +16,11 @@ pub fn do_test(data: &[u8]) {
        if let Ok(s) = std::str::from_utf8(data) {
                let first_decoding = base32::Alphabet::RFC4648 { padding: true }.decode(s);
                if let Ok(first_decoding) = first_decoding {
-                       let encoding_response = base32::Alphabet::RFC4648 { padding: true }.encode(&first_decoding);
+                       let encoding_response =
+                               base32::Alphabet::RFC4648 { padding: true }.encode(&first_decoding);
                        assert_eq!(encoding_response, s.to_ascii_uppercase());
-                       let second_decoding = base32::Alphabet::RFC4648 { padding: true }.decode(&encoding_response).unwrap();
+                       let second_decoding =
+                               base32::Alphabet::RFC4648 { padding: true }.decode(&encoding_response).unwrap();
                        assert_eq!(first_decoding, second_decoding);
                }
        }
@@ -26,19 +28,23 @@ pub fn do_test(data: &[u8]) {
        if let Ok(s) = std::str::from_utf8(data) {
                let first_decoding = base32::Alphabet::RFC4648 { padding: false }.decode(s);
                if let Ok(first_decoding) = first_decoding {
-                       let encoding_response = base32::Alphabet::RFC4648 { padding: false }.encode(&first_decoding);
+                       let encoding_response =
+                               base32::Alphabet::RFC4648 { padding: false }.encode(&first_decoding);
                        assert_eq!(encoding_response, s.to_ascii_uppercase());
-                       let second_decoding = base32::Alphabet::RFC4648 { padding: false }.decode(&encoding_response).unwrap();
+                       let second_decoding =
+                               base32::Alphabet::RFC4648 { padding: false }.decode(&encoding_response).unwrap();
                        assert_eq!(first_decoding, second_decoding);
                }
        }
-       
+
        let encode_response = base32::Alphabet::RFC4648 { padding: false }.encode(&data);
-       let decode_response = base32::Alphabet::RFC4648 { padding: false }.decode(&encode_response).unwrap();
+       let decode_response =
+               base32::Alphabet::RFC4648 { padding: false }.decode(&encode_response).unwrap();
        assert_eq!(data, decode_response);
 
        let encode_response = base32::Alphabet::RFC4648 { padding: true }.encode(&data);
-       let decode_response = base32::Alphabet::RFC4648 { padding: true }.decode(&encode_response).unwrap();
+       let decode_response =
+               base32::Alphabet::RFC4648 { padding: true }.decode(&encode_response).unwrap();
        assert_eq!(data, decode_response);
 }
 
index a7951c77004ca1dda65532264b04150b681df298..7937f30855c707ec7173e0f6e5a2a79bb55227b5 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::base32::*;
 
index 629112f9fef0cd21617a4e2af86004ce8dc8e9fc..62f588d31692ddefc3704b07000684f0ad54b365 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::bech32_parse::*;
 
index 626a4651071ded9a041c320c6b8bfade01fc1bcd..f79140ae5eb5c8d22c8e7fff16d6c4ebb70735c7 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::bolt11_deser::*;
 
index 25fe23b58caeb4e1fd5c29fd8894833ec70255ef..c4788b0c1b27302509f61c6c11ad17f56f0bf619 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::chanmon_consistency::*;
 
index 9e9b17626768388ed6d4fefa369a40c09c2b3769..e58b803021728f5470313fdee730b861e810966f 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::chanmon_deser::*;
 
index 29c984e60160a9c29a6979b0aac92efdb157ee3a..d86d521c76273ab236070e7f46b83e90cb3eb2e1 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::fromstr_to_netaddress::*;
 
index bebb7fdcd81ebdd2f558154b661a4a7c95a77f35..33bac418f38baf2649e0ca91f519a8865ac18148 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::full_stack::*;
 
index 238566d546553ee48da7c731b8e247808a94b392..3830e6a24a6fa33912ef4ad8aecbea325880c8c4 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::indexedmap::*;
 
index 06dbbe3078cac7faa347ce234fbfa00d78d1fa18..ed79d246a584ce37fc2d789f9ae91371f88af9d6 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::invoice_deser::*;
 
index 97741ff3ade27b7f30a09ea42b1da5464d2c09db..47fd3361fcc0e3f56174912269e0157f552faa8e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::invoice_request_deser::*;
 
index 0018d09abd3986af33219eb422b52768cacd15a3..0b5fa27bcc75b0feb20f8c268b2e497cb90b1528 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_accept_channel::*;
 
index 354a5a8c4b84b45769bf593d4d8352c08e59fcd8..efb02c7acf44d037fc4b4785871c191d9eb1b4fa 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_accept_channel_v2::*;
 
index 593908f41751904d7dd8e36c299be5a9ae5507db..684f1361f38190fd8d0b23edb85159ef1c47428d 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_announcement_signatures::*;
 
index f9946314254b7c5d9faa9c06d15464ee52d16bbf..8f326790e0a6c69d21356b0c0ea78aa28af2d65e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_channel_announcement::*;
 
index cb5021aedfa5e70e18c1d8133c28e3a5889bdf71..34f51a30bde2bd33b845a354306a06d3a9f49657 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_channel_details::*;
 
index d11068b7342a9679f4935cfb4ce7c7d34bf3b517..76733dbecfe91e321f7c60cbd0863b7d69def665 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_channel_ready::*;
 
index ba1a76d9941eab3e1b596afc619d1395f1d3b83e..cdb4f1048e34a881d8708abda0ff39236e6f2dc2 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_channel_reestablish::*;
 
index 0198ddc0092e4fe60962c58b484b48186c7adb47..0b567c18b813dcdc7f5550204dee6f418f80c5df 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_channel_update::*;
 
index abd69fc95029f3e3b689a815b4035a18e7ea1924..1634b109da967bad9da738749c7cedf2fce24492 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_closing_signed::*;
 
index 0324301fea79b554e4d50d8e3c7e32ae26c2b8b0..0c00a4ceb5a1caf16b5996584bd9d031d539681a 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_commitment_signed::*;
 
index 1f99bab2bbb82675937001e5cbb192752c9d66b8..93f3c66b207b9d1a09f0d0690c8bad1aa035c124 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_decoded_onion_error_packet::*;
 
index 8609bf65ada5f783660b3807e455625d92d28d9b..4840e2bdfe91a4073ed4470e2560afee059317a2 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_error_message::*;
 
index 51ac425d7e5899756f6aa2ae28bea8ae3f812c70..f888411671027cb91ed9081a7530cd71e15f6609 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_funding_created::*;
 
index bfee1f5aee934cfe4dd2084231d4ea9beda37cb8..42d0316dc9a5525382b21eb65c32d7b41dc805ac 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_funding_signed::*;
 
index aa94f2001cfaab1bd5782c4d75fb6977a2a51b8f..0a47f7731144ba8b51fd1004ee603da126197591 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_gossip_timestamp_filter::*;
 
index 342ceaf3f796b5c4378c3637b226f10c14800157..db0c8a8894f84a79720c3732deaf4ac2ac52c552 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_init::*;
 
index 32012633747ed1ce9d6bd3f9d16697a0d20a3580..1c20a999aaabd85b2a97ae37b325daaedb64773d 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_node_announcement::*;
 
index cee4c0d07efedd4c4342adf9fe9a4ebb98482f44..fc6df814dd1b86b6b68c177b29d0f02c799db76d 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_open_channel::*;
 
index c7949bf9d8d94ddcb5a29a090e2943c4d3e70e2c..732daed18c3e5b6508cae33add5ced2fbd9dd079 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_open_channel_v2::*;
 
index 19e8abe24f9a7bdd19d2f2be50beca13a2f9c0fb..bb1a59b9badf106d546f6e5f669cb5ef19773c69 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_ping::*;
 
index 429550bd1864df484f24e6e0e7376be3328dc66b..7a97d93e7857ac2af0be437a326f7804381d849c 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_pong::*;
 
index c2ce1fd5f52195130806f998d765ea08e8a70d7e..4fd3260db0a3448ce9c2ea95737f5acfb1a18d87 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_query_channel_range::*;
 
index af3d37065e5655f58ac45337ecc0a6476ca318b6..63f8c48fb3bd6d0dbfb18ede9f1bb6b94d9c467d 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_query_short_channel_ids::*;
 
index 0cddbcaf83de9a796f5c7bd680e5258252c754a0..8e5ce619fa402e6062121cc135ed26c1d96e2203 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_reply_channel_range::*;
 
index d802299b28102e6ca62620857d0e642916d878cd..9b9b528abe56f7169ca7cc3eeea50f763108b1a1 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_reply_short_channel_ids_end::*;
 
index d72d63cc32723eab28d05dcc86a98bc3fa9eb312..1f401dae7732cb0f48e989aeffcdae99d85a5f8b 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_revoke_and_ack::*;
 
index 1959a8cfa858c9fff0558779fef9710b23ee74eb..c29bb93bb0b9a669e688062de0eb6450bb120fa8 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_shutdown::*;
 
index cff5675e1914fa292727522af1744c33731dac15..9957a85552f431583f701c124c5392f0fe421884 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_splice_ack::*;
 
index ea5a49bc16dd0428126d3a31a819b44e65032e2b..d9dfcf956bea0f32ef9edc05e5cc12ed1e18cd66 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_splice_locked::*;
 
index bff4dffbbc21e3f7fc64587dcb899530e81c1612..a88b189b43b7d990efa5e6af31f325c24854f09c 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_splice::*;
 
index 1cabf8ded487b03dc7da0ae5159d9f9ac1350399..bdef12d4c32813a66f9aefb664b4faf7c227f911 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_stfu::*;
 
index 66783563ae2148b489d1a344e15ccab17ea9fdbc..76f098b1e2c064da924fd846a55027a13294789e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_abort::*;
 
index 2e6aaedc21e17167d7c66ac8e13c544813208be5..1f549a5703f19b7099f47ecf6bd7b0ad1ea088c1 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_ack_rbf::*;
 
index 1da8bbd935918fddc690e56b15500b38848ff1db..9b7e1cfe7e68866894d26025c7aa8a62c7b9d2ce 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_add_input::*;
 
index a06d51aad6fd069ad6012ed8d8fca73bbbb9d633..b8ad29581bc693435c7b28b62dd5c97d7692946c 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_add_output::*;
 
index 5bb2f855aff87fe2d5b127232c069fe0a3e457e0..28b295b0d2518b89272795a2223b6bf3e8640bdc 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_complete::*;
 
index 74556abb123754d1c57200ceff91516f8002e01e..24fa793315d43547fe893d0ba437d100b6505777 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_init_rbf::*;
 
index d6b9cff281518de34e42e982d5af6e034902f90b..abe4190a3545ec02910a9076a3ac1af38595dbc1 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_remove_input::*;
 
index 2c6b17d8178e439b4879e8715be8be946d3c5c61..3d084e0048d42c20b91aa99a3393ea838765d1d7 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_remove_output::*;
 
index ee650ec2b38aef9bdf6a11e306a9e6acbdd81a18..fa3b966b478882950c4c916499c35f0de019c350 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_tx_signatures::*;
 
index 47faa7b1bbb989b1cb379fbddface77d5bdd4bdd..f3c25a37524f3be486c7e0bf0225ee7c8ccad21f 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_update_add_htlc::*;
 
index 0c47190f72ced5ff645d8c2592190bfaf5c22d47..9698ae92cfe02d4a945b3707fd49ff661235eb67 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_update_fail_htlc::*;
 
index 917fad9ce600d4f315d2cf968b99fdc7349f7238..b7f511c5ff53cb6a042fd73f001acf13711d769e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_update_fail_malformed_htlc::*;
 
index f7baec58a170141d9b0d7c7ed5d986fd65c10b6c..b021107f15044a5e8b7eb2f7c0bf08ef486daa27 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_update_fee::*;
 
index 23197b38eec8704e4faee85eb04e988131e4d8fa..d87cd5bd490dab65e872600e46e2ac6be09a0197 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::msg_targets::msg_update_fulfill_htlc::*;
 
index 49563b1029180235ae0e6a34fd37b22e4f8b0af1..51cdb09adec120792c3017a98bdfd3fa193b9a2a 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::offer_deser::*;
 
index b8a357229bf2907f343b541378921f40c0fa745f..50d98043d05d8a26fcd7fc3cc80a9bda52d3861d 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::onion_hop_data::*;
 
index e9bcf590da142ac8c5d562406d6c8b2be6e6f6d1..7bb09477ec57723ccfbb2f8f1837b28ec7de8d3e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::onion_message::*;
 
index c7cbe8c2c2f30389e34265176cca430d0e2ef19c..0ba0252c9635316ae60f34e7b2466d4067bf6b77 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::peer_crypt::*;
 
index 380efdff447913ad8bdd2570436a619b17380fa9..4ce10e6d4dfd2ff834e4f0d7eaea9f1fd2c4a6f2 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::process_network_graph::*;
 
index c9857783467457d0d951375cb51bc383d684b0fa..fea8a9c4c6de916a44690a86282bb0b2ded7a960 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::refund_deser::*;
 
index 2082f115ae0572f39b9662f6cf64b762d4e9078d..0ebec5494554b0ce9d03d76ce8829fa9f088294e 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::router::*;
 
index 7b0ec0eebce154ee3454201b688024f50e2885d3..e828aa998b12801c46602f84d948d20b1ce44aa2 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::TARGET_MOD::*;
 
index 1553d6d2b66d60cab4cc899e0f7494abfccf6e5b..35aa53d1fff8bc2bd05822c47a50bead7cba72ba 100644 (file)
 // To modify it, modify target_template.txt and run gen_target.sh instead.
 
 #![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+#![cfg_attr(rustfmt, rustfmt_skip)]
 
 #[cfg(not(fuzzing))]
 compile_error!("Fuzz targets need cfg=fuzzing");
 
+#[cfg(not(hashes_fuzz))]
+compile_error!("Fuzz targets need cfg=hashes_fuzz");
+
+#[cfg(not(secp256k1_fuzz))]
+compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
+
 extern crate lightning_fuzz;
 use lightning_fuzz::zbase32::*;
 
index d2c0ab590036faba9f81c5b85ab9c768da5302bf..63d869c8178495613f15cb08ebd1205f7e23d3fc 100644 (file)
@@ -8,7 +8,7 @@
 // licenses.
 
 use crate::utils::test_logger;
-use bitcoin::bech32::{u5, FromBase32, ToBase32};
+use bech32::{u5, FromBase32, ToBase32};
 use bitcoin::secp256k1::{Secp256k1, SecretKey};
 use lightning_invoice::{
        Bolt11Invoice, RawBolt11Invoice, RawDataPart, RawHrp, RawTaggedField, TaggedField,
index 5004580231e3aacbab43504300b59af15d43b923..1cdf617fa078ba60c87efa971888b98201e1142d 100644 (file)
 //! send-side handling is correct, other peers. We consider it a failure if any action results in a
 //! channel being force-closed.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::{Builder, ScriptBuf};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::locktime::absolute::LockTime;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
+use bitcoin::transaction::Version;
 
+use bitcoin::WPubkeyHash;
 use bitcoin::hashes::Hash as TraitImport;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
-use bitcoin::hash_types::{BlockHash, WPubkeyHash};
+use bitcoin::hash_types::BlockHash;
 
 use lightning::blinded_path::BlindedPath;
-use lightning::blinded_path::message::ForwardNode;
 use lightning::blinded_path::payment::ReceiveTlvs;
 use lightning::chain;
 use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, chainmonitor, channelmonitor, Confirm, Watch};
@@ -42,7 +44,8 @@ use lightning::sign::{KeyMaterial, InMemorySigner, Recipient, EntropySource, Nod
 use lightning::events;
 use lightning::events::MessageSendEventsProvider;
 use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId, RecipientOnionFields};
+use lightning::ln::channel_state::ChannelDetails;
+use lightning::ln::channelmanager::{ChainParameters,ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId, RecipientOnionFields};
 use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
 use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
 use lightning::ln::script::ShutdownScript;
@@ -71,7 +74,7 @@ use std::cmp::{self, Ordering};
 use std::sync::{Arc,Mutex};
 use std::sync::atomic;
 use std::io::Cursor;
-use bitcoin::bech32::u5;
+use bech32::u5;
 
 const MAX_FEE: u32 = 10_000;
 struct FuzzEstimator {
@@ -120,7 +123,7 @@ impl MessageRouter for FuzzRouter {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
@@ -245,7 +248,7 @@ impl NodeSigner for KeyProvider {
        }
 
        fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
-               let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
+               let msg_hash = Message::from_digest(Sha256dHash::hash(&msg.encode()[..]).to_byte_array());
                let secp_ctx = Secp256k1::signing_only();
                Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
        }
@@ -589,8 +592,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
                                let events = $source.get_and_clear_pending_events();
                                assert_eq!(events.len(), 1);
                                if let events::Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, .. } = events[0] {
-                                       let tx = Transaction { version: $chan_id, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                                               value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                                       let tx = Transaction { version: Version($chan_id), lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                                               value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(),
                                        }]};
                                        funding_output = OutPoint { txid: tx.txid(), index: 0 };
                                        $source.funding_transaction_generated(&temporary_channel_id, &$dest.get_our_node_id(), tx.clone()).unwrap();
index 8d425357c96844b2b9766de612879750f4dceddc..b9c0121377245cb73b62a23ca24cea4f97c729d8 100644 (file)
@@ -4,8 +4,8 @@
 use bitcoin::hash_types::BlockHash;
 
 use lightning::chain::channelmonitor;
+use lightning::util::ser::{ReadableArgs, Writeable, Writer};
 use lightning::util::test_channel_signer::TestChannelSigner;
-use lightning::util::ser::{ReadableArgs, Writer, Writeable};
 use lightning::util::test_utils::OnlyReadsKeysInterface;
 
 use crate::utils::test_logger;
@@ -22,10 +22,19 @@ impl Writer for VecWriter {
 
 #[inline]
 pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       if let Ok((latest_block_hash, monitor)) = <(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(&mut Cursor::new(data), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})) {
+       if let Ok((latest_block_hash, monitor)) =
+               <(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(
+                       &mut Cursor::new(data),
+                       (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {}),
+               ) {
                let mut w = VecWriter(Vec::new());
                monitor.write(&mut w).unwrap();
-               let deserialized_copy = <(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(&mut Cursor::new(&w.0), (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {})).unwrap();
+               let deserialized_copy =
+                       <(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(
+                               &mut Cursor::new(&w.0),
+                               (&OnlyReadsKeysInterface {}, &OnlyReadsKeysInterface {}),
+                       )
+                       .unwrap();
                assert!(latest_block_hash == deserialized_copy.0);
                assert!(monitor == deserialized_copy.1);
        }
@@ -37,5 +46,5 @@ pub fn chanmon_deser_test<Out: test_logger::Output>(data: &[u8], out: Out) {
 
 #[no_mangle]
 pub extern "C" fn chanmon_deser_run(data: *const u8, datalen: usize) {
-       do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull{});
+       do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull {});
 }
index dba2d44451e3b5755115e41157d4a102fde9c9b5..384ea56a8ef5392c65e3970caad8cfe7aa6ba150 100644 (file)
@@ -7,8 +7,8 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use lightning::ln::msgs::SocketAddress;
 use core::str::FromStr;
+use lightning::ln::msgs::SocketAddress;
 
 use crate::utils::test_logger;
 
@@ -17,7 +17,6 @@ pub fn do_test(data: &[u8]) {
        if let Ok(s) = std::str::from_utf8(data) {
                let _ = SocketAddress::from_str(s);
        }
-
 }
 
 pub fn fromstr_to_netaddress_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
@@ -28,4 +27,3 @@ pub fn fromstr_to_netaddress_test<Out: test_logger::Output>(data: &[u8], _out: O
 pub extern "C" fn fromstr_to_netaddress_run(data: *const u8, datalen: usize) {
        do_test(unsafe { std::slice::from_raw_parts(data, datalen) });
 }
-
index adb997ab22c8dd3d0cd32297e79b175fe1e2cead..bdd29be9129f9a66a494ba428771c539edebb6f8 100644 (file)
 //! or payments to send/ways to handle events generated.
 //! This test has been very useful, though due to its complexity good starting inputs are critical.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::{Builder, ScriptBuf};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::consensus::encode::deserialize;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
+use bitcoin::transaction::Version;
 
+use bitcoin::WPubkeyHash;
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::hashes::Hash as _;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
-use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
+use bitcoin::hash_types::{Txid, BlockHash};
 
 use lightning::blinded_path::BlindedPath;
-use lightning::blinded_path::message::ForwardNode;
 use lightning::blinded_path::payment::ReceiveTlvs;
 use lightning::chain;
 use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen};
@@ -38,7 +40,8 @@ use lightning::chain::transaction::OutPoint;
 use lightning::sign::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
 use lightning::events::Event;
 use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId};
+use lightning::ln::channel_state::ChannelDetails;
+use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId};
 use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler};
 use lightning::ln::msgs::{self, DecodeError};
 use lightning::ln::script::ShutdownScript;
@@ -69,7 +72,7 @@ use std::convert::TryInto;
 use std::cmp;
 use std::sync::{Arc, Mutex};
 use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering};
-use bitcoin::bech32::u5;
+use bech32::u5;
 
 #[inline]
 pub fn slice_to_be16(v: &[u8]) -> u16 {
@@ -158,7 +161,7 @@ impl MessageRouter for FuzzRouter {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
@@ -217,6 +220,7 @@ struct MoneyLossDetector<'a> {
        height: usize,
        max_height: usize,
        blocks_connected: u32,
+       error_message: String,
 }
 impl<'a> MoneyLossDetector<'a> {
        pub fn new(peers: &'a RefCell<[bool; 256]>,
@@ -235,6 +239,7 @@ impl<'a> MoneyLossDetector<'a> {
                        height: 0,
                        max_height: 0,
                        blocks_connected: 0,
+                       error_message: "Channel force-closed".to_string(),
                }
        }
 
@@ -289,7 +294,7 @@ impl<'a> Drop for MoneyLossDetector<'a> {
                        }
 
                        // Force all channels onto the chain (and time out claim txn)
-                       self.manager.force_close_all_channels_broadcasting_latest_txn();
+                       self.manager.force_close_all_channels_broadcasting_latest_txn(self.error_message.to_string());
                }
        }
 }
@@ -350,7 +355,7 @@ impl NodeSigner for KeyProvider {
        }
 
        fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
-               let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
+               let msg_hash = Message::from_digest(Sha256dHash::hash(&msg.encode()[..]).to_byte_array());
                let secp_ctx = Secp256k1::signing_only();
                Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
        }
@@ -651,11 +656,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                }
                        },
                        10 => {
-                               let mut tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                               let mut tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                                let mut channels = Vec::new();
                                for funding_generation in pending_funding_generation.drain(..) {
                                        let txout = TxOut {
-                                               value: funding_generation.2, script_pubkey: funding_generation.3,
+                                               value: Amount::from_sat(funding_generation.2), script_pubkey: funding_generation.3,
                                        };
                                        if !tx.output.contains(&txout) {
                                                tx.output.push(txout);
@@ -665,7 +670,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                // Once we switch to V2 channel opens we should be able to drop this entirely as
                                // channel_ids no longer change when we set the funding tx.
                                'search_loop: loop {
-                                       if tx.version > 0xff {
+                                       if tx.version.0 > 0xff {
                                                break;
                                        }
                                        let funding_txid = tx.txid();
@@ -673,15 +678,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                                let outpoint = OutPoint { txid: funding_txid, index: 0 };
                                                for chan in channelmanager.list_channels() {
                                                        if chan.channel_id == ChannelId::v1_from_funding_outpoint(outpoint) {
-                                                               tx.version += 1;
+                                                               tx.version = Version(tx.version.0 + 1);
                                                                continue 'search_loop;
                                                        }
                                                }
                                                break;
                                        }
-                                       tx.version += 1;
+                                       tx.version = Version(tx.version.0 + 1);
                                }
-                               if tx.version <= 0xff && !channels.is_empty() {
+                               if tx.version.0 <= 0xff && !channels.is_empty() {
                                        let chans = channels.iter().map(|(a, b)| (a, b)).collect::<Vec<_>>();
                                        if let Err(e) = channelmanager.batch_funding_transaction_generated(&chans, tx.clone()) {
                                                // It's possible the channel has been closed in the mean time, but any other
@@ -714,11 +719,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                } else {
                                        let txres: Result<Transaction, _> = deserialize(get_slice!(txlen));
                                        if let Ok(tx) = txres {
-                                               let mut output_val = 0;
+                                               let mut output_val = Amount::ZERO;
                                                for out in tx.output.iter() {
-                                                       if out.value > 21_000_000_0000_0000 { return; }
+                                                       if out.value > Amount::MAX_MONEY { return; }
                                                        output_val += out.value;
-                                                       if output_val > 21_000_000_0000_0000 { return; }
+                                                       if output_val > Amount::MAX_MONEY { return; }
                                                }
                                                loss_detector.connect_block(&[tx]);
                                        } else {
@@ -732,9 +737,10 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                        14 => {
                                let mut channels = channelmanager.list_channels();
                                let channel_id = get_slice!(1)[0] as usize;
+                               let error_message = "Channel force-closed";
                                if channel_id >= channels.len() { return; }
                                channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
-                               channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id).unwrap();
+                               channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id, error_message.to_string()).unwrap();
                        },
                        // 15, 16, 17, 18 is above
                        19 => {
index 58775d024673568bc38eb8d0fd6f8309b4c41ad5..ee21f04619fa3051540c495e06c4b265d80e0952 100644 (file)
@@ -7,23 +7,31 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use lightning::util::indexed_map::{IndexedMap, self};
-use std::collections::{BTreeMap, btree_map};
 use lightning::util::hash_tables::*;
+use lightning::util::indexed_map::{self, IndexedMap};
+use std::collections::{btree_map, BTreeMap};
 
 use crate::utils::test_logger;
 
-use std::ops::{RangeBounds, Bound};
+use std::ops::{Bound, RangeBounds};
 
 struct ExclLowerInclUpper(u8, u8);
 impl RangeBounds<u8> for ExclLowerInclUpper {
-       fn start_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.0) }
-       fn end_bound(&self) -> Bound<&u8> { Bound::Included(&self.1) }
+       fn start_bound(&self) -> Bound<&u8> {
+               Bound::Excluded(&self.0)
+       }
+       fn end_bound(&self) -> Bound<&u8> {
+               Bound::Included(&self.1)
+       }
 }
 struct ExclLowerExclUpper(u8, u8);
 impl RangeBounds<u8> for ExclLowerExclUpper {
-       fn start_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.0) }
-       fn end_bound(&self) -> Bound<&u8> { Bound::Excluded(&self.1) }
+       fn start_bound(&self) -> Bound<&u8> {
+               Bound::Excluded(&self.0)
+       }
+       fn end_bound(&self) -> Bound<&u8> {
+               Bound::Excluded(&self.1)
+       }
 }
 
 fn check_eq(btree: &BTreeMap<u8, u8>, mut indexed: IndexedMap<u8, u8>) {
@@ -46,36 +54,44 @@ fn check_eq(btree: &BTreeMap<u8, u8>, mut indexed: IndexedMap<u8, u8>) {
                                if let indexed_map::Entry::Occupied(mut io) = indexed_entry {
                                        assert_eq!(bo.get(), io.get());
                                        assert_eq!(bo.get_mut(), io.get_mut());
-                               } else { panic!(); }
+                               } else {
+                                       panic!();
+                               }
                        },
                        btree_map::Entry::Vacant(_) => {
                                if let indexed_map::Entry::Vacant(_) = indexed_entry {
-                               } else { panic!(); }
-                       }
+                               } else {
+                                       panic!();
+                               }
+                       },
                }
        }
 
        const STRIDE: u8 = 16;
        for range_type in 0..4 {
-               for k in 0..=255/STRIDE {
+               for k in 0..=255 / STRIDE {
                        let lower_bound = k * STRIDE;
                        let upper_bound = lower_bound + (STRIDE - 1);
-                       macro_rules! range { ($map: expr) => {
-                               match range_type {
-                                       0 => $map.range(lower_bound..upper_bound),
-                                       1 => $map.range(lower_bound..=upper_bound),
-                                       2 => $map.range(ExclLowerInclUpper(lower_bound, upper_bound)),
-                                       3 => $map.range(ExclLowerExclUpper(lower_bound, upper_bound)),
-                                       _ => unreachable!(),
-                               }
-                       } }
+                       macro_rules! range {
+                               ($map: expr) => {
+                                       match range_type {
+                                               0 => $map.range(lower_bound..upper_bound),
+                                               1 => $map.range(lower_bound..=upper_bound),
+                                               2 => $map.range(ExclLowerInclUpper(lower_bound, upper_bound)),
+                                               3 => $map.range(ExclLowerExclUpper(lower_bound, upper_bound)),
+                                               _ => unreachable!(),
+                                       }
+                               };
+                       }
                        let mut btree_iter = range!(btree);
                        let mut indexed_iter = range!(indexed);
                        loop {
                                let b_v = btree_iter.next();
                                let i_v = indexed_iter.next();
                                assert_eq!(b_v, i_v);
-                               if b_v.is_none() { break; }
+                               if b_v.is_none() {
+                                       break;
+                               }
                        }
                }
        }
@@ -104,7 +120,9 @@ fn check_eq(btree: &BTreeMap<u8, u8>, mut indexed: IndexedMap<u8, u8>) {
 
 #[inline]
 pub fn do_test(data: &[u8]) {
-       if data.len() % 2 != 0 { return; }
+       if data.len() % 2 != 0 {
+               return;
+       }
        let mut btree = BTreeMap::new();
        let mut indexed = IndexedMap::new();
 
@@ -138,13 +156,17 @@ pub fn do_test(data: &[u8]) {
                                        } else {
                                                assert_eq!(bo.remove_entry(), io.remove_entry());
                                        }
-                               } else { panic!(); }
+                               } else {
+                                       panic!();
+                               }
                        },
                        btree_map::Entry::Vacant(bv) => {
                                if let indexed_map::Entry::Vacant(iv) = indexed.entry(k) {
                                        bv.insert(k);
                                        iv.insert(k);
-                               } else { panic!(); }
+                               } else {
+                                       panic!();
+                               }
                        },
                }
        }
index 1aad5bfd897b77f9eab9363611354e56e1f88def..642da58236f6bc5fd51ad8cbc266ff2f3aa9676c 100644 (file)
@@ -7,17 +7,17 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use bitcoin::secp256k1::{KeyPair, Parity, PublicKey, Secp256k1, SecretKey, self};
 use crate::utils::test_logger;
+use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey};
 use core::convert::TryFrom;
-use lightning::blinded_path::BlindedPath;
 use lightning::blinded_path::message::ForwardNode;
-use lightning::sign::EntropySource;
-use lightning::ln::PaymentHash;
+use lightning::blinded_path::BlindedPath;
 use lightning::ln::features::BlindedHopFeatures;
+use lightning::ln::PaymentHash;
 use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
 use lightning::offers::invoice_request::InvoiceRequest;
 use lightning::offers::parse::Bolt12SemanticError;
+use lightning::sign::EntropySource;
 use lightning::util::ser::Writeable;
 
 #[inline]
@@ -28,7 +28,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
                assert_eq!(data, bytes);
 
                let secp_ctx = Secp256k1::new();
-               let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let mut buffer = Vec::new();
 
                if let Ok(unsigned_invoice) = build_response(&invoice_request, &secp_ctx) {
@@ -38,17 +38,17 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
                        let even_pubkey = x_only_pubkey.public_key(Parity::Even);
                        if signing_pubkey == odd_pubkey || signing_pubkey == even_pubkey {
                                unsigned_invoice
-                                       .sign(|message: &UnsignedBolt12Invoice|
+                                       .sign(|message: &UnsignedBolt12Invoice| {
                                                Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
-                                       )
+                                       })
                                        .unwrap()
                                        .write(&mut buffer)
                                        .unwrap();
                        } else {
                                unsigned_invoice
-                                       .sign(|message: &UnsignedBolt12Invoice|
+                                       .sign(|message: &UnsignedBolt12Invoice| {
                                                Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
-                                       )
+                                       })
                                        .unwrap_err();
                        }
                }
@@ -58,7 +58,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
 struct Randomness;
 
 impl EntropySource for Randomness {
-       fn get_secure_random_bytes(&self) -> [u8; 32] { [42; 32] }
+       fn get_secure_random_bytes(&self) -> [u8; 32] {
+               [42; 32]
+       }
 }
 
 fn pubkey(byte: u8) -> PublicKey {
@@ -71,7 +73,7 @@ fn privkey(byte: u8) -> SecretKey {
 }
 
 fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
-       invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>
+       invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>,
 ) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
        let entropy_source = Randomness {};
        let intermediate_nodes = [
@@ -85,8 +87,10 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                ],
        ];
        let paths = vec![
-               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx).unwrap(),
-               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx).unwrap(),
+               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
+                       .unwrap(),
+               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
+                       .unwrap(),
        ];
 
        let payinfo = vec![
index 6efdd94dfcb433650c5480b92e4ceabb81909f4b..2e132edce423ecbd23a015af80b6ea8105a1f976 100644 (file)
@@ -8,29 +8,29 @@
 // licenses.
 
 extern crate bitcoin;
+extern crate hex;
 extern crate lightning;
 extern crate lightning_rapid_gossip_sync;
-extern crate hex;
 
 pub mod utils;
 
+pub mod base32;
 pub mod bech32_parse;
-pub mod chanmon_deser;
+pub mod bolt11_deser;
 pub mod chanmon_consistency;
+pub mod chanmon_deser;
+pub mod fromstr_to_netaddress;
 pub mod full_stack;
 pub mod indexedmap;
 pub mod invoice_deser;
 pub mod invoice_request_deser;
 pub mod offer_deser;
-pub mod bolt11_deser;
+pub mod onion_hop_data;
 pub mod onion_message;
 pub mod peer_crypt;
 pub mod process_network_graph;
 pub mod refund_deser;
 pub mod router;
 pub mod zbase32;
-pub mod onion_hop_data;
-pub mod base32;
-pub mod fromstr_to_netaddress;
 
 pub mod msg_targets;
index cb24aa919db8c258163525afcb5d247d5e1a320f..05997c07573f8c4fcc57a6f7f38e32c4f87eb10c 100755 (executable)
@@ -7,7 +7,10 @@ GEN_TEST() {
        echo "pub mod $tn;" >> mod.rs
 }
 
-echo "mod utils;" > mod.rs
+{
+       echo "#![cfg_attr(rustfmt, rustfmt_skip)]"
+       echo "mod utils;"
+} > mod.rs
 
 # Note when adding new targets here you should add a similar line in src/bin/gen_target.sh
 
@@ -45,7 +48,7 @@ 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 ""
+GEN_TEST lightning::ln::channel_state::ChannelDetails test_msg_simple ""
 
 GEN_TEST lightning::ln::msgs::OpenChannelV2 test_msg_simple ""
 GEN_TEST lightning::ln::msgs::AcceptChannelV2 test_msg_simple ""
index 837bee65dec110c4d7f78d5576923e1e5a466c43..15750a9a5b140a3402f5a8ee7b1c412be5c51428 100644 (file)
@@ -1,3 +1,4 @@
+#![cfg_attr(rustfmt, rustfmt_skip)]
 mod utils;
 pub mod msg_accept_channel;
 pub mod msg_announcement_signatures;
index d4e7acf1da76b34fe965f0c839a9650a85d0e101..216fe7c59bd156a3773e9573e441e4076200c9fc 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 36b646644ea45eddca8af367ca1cac2c172d1a07..c1d7fb55c9bf9abc390b8259c80cdcd27c6cadd0 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index cf0ca2e2d85dc1284c80267da30aa582fe76f37b..6010e6001b62e89d5488fb624e8a31a4511bb296 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 0c67ca16edf657dcc982c4b08de2437fc96c521c..d4084c618937e8aa6b49415fe70bbe140c88b694 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 54fc289479fc3c492b2345879a9cf547962e8c08..eb9f8beee47eee822ffeed37b99101a12baa2a77 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::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);
+       test_msg_simple!(lightning::ln::channel_state::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);
+       test_msg_simple!(lightning::ln::channel_state::ChannelDetails, data);
 }
index 5b13486f56cce9039d577be32e69d3bf32a50b54..3180928905de3807fd073a733bc2441c4b490d76 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index fdc2d1fa62b217049218ed0ff0fcf69b70a87fcf..f766892a2e2086916e6da7881a25a2e5b93749bf 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 27dadaed562f15412102907f5eee12fd73ba6c99..358305b9dae2eff6629ded0a345b6f102e5fa8ee 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 0497b1fcc65c81b958b55c81be50636bda418dda..74e04d6675abc8fa79ca4fd677bb490b32145cd5 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 8726efc586bed577c10ac0fb803ab4840fd85cd2..7ece314353d3e4cc3746af8bc8466ee2824d4f09 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 3f5243d4e26b7f967489b681479d8628626c697c..9d245e2f2d211b329d8da24585d4fa5a9b10b717 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 6d9d8e27e316794dad5f5c6c63f38acad883ba12..ae16e1686dcd2122e4a8958aad7c7bd3ae127e86 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index c03975da7b91767bc83ab55ca3fb41247a832954..a6c5ba148c24d401f38a95d043b86c63aea5bd0f 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 8788d34bc8f95ebd44a60014c92264e713afe449..34f0fddaad300d38bb10b906a09b69f2c89068a5 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 884449b06d5b5b82b453b28f4583f76a93ecdffb..8e0fb7c53808a2880e85451505338fce4bb5a708 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 1f21f4b3d5d4d77cd1d60dd42762eb99a53b2316..5f11441ddf5cda69fdf6ccdc83155ae7bd060bdf 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index ab2ba755092f1f9675fa3ea948ece123e5c8abed..ce9bb30d3ddfb8da106b2c35bed9c7569a89ed09 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index cacb5d767d6169b0aaddff1700d2f22e8305b5d1..9c924e501db6e2669b329263d728cb286d7bb4f3 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 4f6457a3ebbd5772bc955b866e2b6a9b9b2e730a..a43d58ee9e65f1560e7ddcc6ad758624c5cd8f55 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 2509fef7e892c52ff6cc1d7e0b085ea52ce60e5d..2ff54816474447207cf341f07b80286dc6f0521b 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 1c90eefdb32a9f1949ff80cfaa33a1cdd54904a8..52b9ee084866662f10da99d7a346b2eeb7004e85 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index fe2fb40514384c0d1d12a1badc61404e037dac95..6b59636780b1679478995318b1480f68109973bb 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index bd8fa59d157f3bb2d1c937dca45b9151c63ec525..c15915fd1a8229b41877c235ecdf380bc60c394c 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 43a3e0f3ddce834f518a8e06919b470db77db719..3cb94af6c2345cdcbc0b19252cdd083da016eed9 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index dc765c76b19d5017983a0ae3ab8670a3fe61f5be..a53459997f94d7d195b01c234b8cdc404a02f1cb 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 9190c98e8822815947b7815f9123476b5e8d3f26..26f2d7524cdf4100630ca946ed71bfb3f19b3429 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 26133f7d1dbf4202b0c6f554456aa0b97c19edd4..77c4cfdaae3aea36bdda0e8f098b3707a4bdf597 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index e6a18d2561ca87108727333ba99ef40de6010d44..f203da0562cb33816ce2572a2d9d0d91e2b60d84 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index cc77c198bb71ab6926f0f18065067c05810fd7aa..65949d273da7ec69639520aa91820174391a24c5 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 39e340fd40b35c03802aa9f5ddc8772a2ec06a26..02e762ade70d0545237f6c11272f219664beab44 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index be2029194a71ef7215b27f721ab6259c6970c1f1..87845cf28aaf26ed81cf8aa8c438a5641557ab3c 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index c6064388dcabc4fbcf8280a23826da6c6aa02af7..f5ed99b64d0dcf4bc33c91d509f0e740694575ef 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index c361b654675c4978c98d294e25f607d79dce20d8..c80df485040c6121b7b9aa301eb0ea4b6b11c7ee 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 9931bfcfb72d7eb58f68debcc39c6dcf9c4b53d4..41fd1ed9c2751d36107157fd97a6bec9a48a62f6 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index f212b59cd6a722ecae6c09726648a6a87770a571..8ae0c61034a44e1d7e8679b79913d0dd272e4149 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 49b23218fa1880b02b6c65e2b6b877f0b412ef71..04511ed599f44212a402ebdb19094747998101dc 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index c4227b15235f671fd41bf7e4c73f3122e03923e7..4cd1a271284cb0210668fe171673416ee1dc6c96 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index ea021dc60ac49032b5de564136faf1a71e74bb59..eab0a747ea87023ff3218a4ae34d18ef0dd3662e 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index fe69ad41b8d1d9178d5c0bc584479bda285e2671..1f934eac27440e746de186f4d61e85c841082407 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 6c09d4d9f41deb111856157f1d40b64dedf45875..a9e0e8b2ef1e0e68d42d22a24beaab7ca72a12a2 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 54392d48cda7297f6f3310b6b010b3048e55da8e..17dc063adc222dc9737f9f1d715b61bcba335c59 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index e8edf4f4dd5eaf2eae43b4758a07110059d9c5cd..45a2616243a272726bc1a1a452375895968bfa2d 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index b93cc60b505ec3f77ac95474e929c66c7cb8524c..e338beeee2f162bc102faba070bf3fa062a8e183 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 24718d54adefe0e1a1996c86f88452c04b0ff77a..6c1914f03ca9e58d759eb487bc7570ac13081ba6 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 92661537bf765d1b93ddf18c39912a672d32128e..991dde925f8964f48cac525b4a246b8285b76ed6 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 7f9463e2731c7911196247dc6cfb07b6be3e4006..61e3f30b95c67f908b44348407129543769a4b57 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index a5bcf4111f6dbabe8ae4f14c3eb137ebafdc4b8b..0e1a456667746f383dce42fcfe6300f4148b343c 100644 (file)
@@ -10,6 +10,8 @@
 // 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.
 
+#![cfg_attr(rustfmt, rustfmt_skip)]
+
 use crate::msg_targets::utils::VecWriter;
 use crate::utils::test_logger;
 
index 6325f3bf10d07bab3469b018ab106c7c732ec1d7..5fa474cbf02f291c9b66194133111c224228fcab 100644 (file)
@@ -29,81 +29,73 @@ impl Writer for VecWriter {
 // entirely
 #[macro_export]
 macro_rules! test_msg {
-       ($MsgType: path, $data: ident) => {
-               {
-                       use lightning::util::ser::{Writeable, Readable};
-                       let mut r = ::std::io::Cursor::new($data);
-                       if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
-                               let p = r.position() as usize;
-                               let mut w = VecWriter(Vec::new());
-                               msg.write(&mut w).unwrap();
+       ($MsgType: path, $data: ident) => {{
+               use lightning::util::ser::{Readable, Writeable};
+               let mut r = ::std::io::Cursor::new($data);
+               if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
+                       let p = r.position() as usize;
+                       let mut w = VecWriter(Vec::new());
+                       msg.write(&mut w).unwrap();
 
-                               assert_eq!(w.0.len(), p);
-                               assert_eq!(msg.serialized_length(), p);
-                               assert_eq!(&r.into_inner()[..p], &w.0[..p]);
-                       }
+                       assert_eq!(w.0.len(), p);
+                       assert_eq!(msg.serialized_length(), p);
+                       assert_eq!(&r.into_inner()[..p], &w.0[..p]);
                }
-       }
+       }};
 }
 
 // Tests a message that may lose data on roundtrip, but shoulnd't lose data compared to our
 // re-serialization.
 #[macro_export]
 macro_rules! test_msg_simple {
-       ($MsgType: path, $data: ident) => {
-               {
-                       use lightning::util::ser::{Writeable, Readable};
-                       let mut r = ::std::io::Cursor::new($data);
-                       if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
-                               let mut w = VecWriter(Vec::new());
-                               msg.write(&mut w).unwrap();
-                               assert_eq!(msg.serialized_length(), w.0.len());
+       ($MsgType: path, $data: ident) => {{
+               use lightning::util::ser::{Readable, Writeable};
+               let mut r = ::std::io::Cursor::new($data);
+               if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
+                       let mut w = VecWriter(Vec::new());
+                       msg.write(&mut w).unwrap();
+                       assert_eq!(msg.serialized_length(), w.0.len());
 
-                               let msg = <$MsgType as Readable>::read(&mut ::std::io::Cursor::new(&w.0)).unwrap();
-                               let mut w_two = VecWriter(Vec::new());
-                               msg.write(&mut w_two).unwrap();
-                               assert_eq!(&w.0[..], &w_two.0[..]);
-                       }
+                       let msg = <$MsgType as Readable>::read(&mut ::std::io::Cursor::new(&w.0)).unwrap();
+                       let mut w_two = VecWriter(Vec::new());
+                       msg.write(&mut w_two).unwrap();
+                       assert_eq!(&w.0[..], &w_two.0[..]);
                }
-       }
+       }};
 }
 
 // Tests a message that must survive roundtrip exactly, and must exactly empty the read buffer and
 // split it back out on re-serialization.
 #[macro_export]
 macro_rules! test_msg_exact {
-       ($MsgType: path, $data: ident) => {
-               {
-                       use lightning::util::ser::{Writeable, Readable};
-                       let mut r = ::std::io::Cursor::new($data);
-                       if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
-                               let mut w = VecWriter(Vec::new());
-                               msg.write(&mut w).unwrap();
-                               assert_eq!(&r.into_inner()[..], &w.0[..]);
-                               assert_eq!(msg.serialized_length(), w.0.len());
-                       }
+       ($MsgType: path, $data: ident) => {{
+               use lightning::util::ser::{Readable, Writeable};
+               let mut r = ::std::io::Cursor::new($data);
+               if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
+                       let mut w = VecWriter(Vec::new());
+                       msg.write(&mut w).unwrap();
+                       assert_eq!(&r.into_inner()[..], &w.0[..]);
+                       assert_eq!(msg.serialized_length(), w.0.len());
                }
-       }
+       }};
 }
 
 // Tests a message that must survive roundtrip exactly, modulo one "hole" which may be set to
 // any value on re-serialization.
 #[macro_export]
 macro_rules! test_msg_hole {
-       ($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => {
-               {
-                       use lightning::util::ser::{Writeable, Readable};
-                       let mut r = ::std::io::Cursor::new($data);
-                       if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
-                               let mut w = VecWriter(Vec::new());
-                               msg.write(&mut w).unwrap();
-                               let p = w.0.len() as usize;
-                               assert_eq!(msg.serialized_length(), p);
+       ($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => {{
+               use lightning::util::ser::{Readable, Writeable};
+               let mut r = ::std::io::Cursor::new($data);
+               if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
+                       let mut w = VecWriter(Vec::new());
+                       msg.write(&mut w).unwrap();
+                       let p = w.0.len() as usize;
+                       assert_eq!(msg.serialized_length(), p);
 
-                               assert_eq!(w.0.len(), p);
-                               assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]);
-                               assert_eq!(&r.get_ref()[$hole+$hole_len..p], &w.0[$hole+$hole_len..]);
-                       }
+                       assert_eq!(w.0.len(), p);
+                       assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]);
+                       assert_eq!(&r.get_ref()[$hole + $hole_len..p], &w.0[$hole + $hole_len..]);
                }
-       }
+       }};
 }
index 5aad4642e461f6477a55591cf2239507882cd86a..84b69d3fcd31f5dc82bbf1bdf60faa4036283f25 100644 (file)
@@ -7,8 +7,8 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
 use crate::utils::test_logger;
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 use core::convert::TryFrom;
 use lightning::offers::invoice_request::UnsignedInvoiceRequest;
 use lightning::offers::offer::{Amount, Offer, Quantity};
@@ -23,15 +23,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
                assert_eq!(data, bytes);
 
                let secp_ctx = Secp256k1::new();
-               let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let pubkey = PublicKey::from(keys);
                let mut buffer = Vec::new();
 
                if let Ok(invoice_request) = build_response(&offer, pubkey) {
                        invoice_request
-                               .sign(|message: &UnsignedInvoiceRequest|
+                               .sign(|message: &UnsignedInvoiceRequest| {
                                        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
-                               )
+                               })
                                .unwrap()
                                .write(&mut buffer)
                                .unwrap();
@@ -40,7 +40,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
 }
 
 fn build_response(
-       offer: &Offer, pubkey: PublicKey
+       offer: &Offer, pubkey: PublicKey,
 ) -> Result<UnsignedInvoiceRequest, Bolt12SemanticError> {
        let mut builder = offer.request_invoice(vec![42; 64], pubkey)?;
 
index e7f51b9916775244cb73a87b3b2de57fbe585efa..36aebb4e194e6181cff4b6310e1c481f51148dbd 100644 (file)
@@ -15,19 +15,25 @@ use lightning::util::test_utils;
 
 #[inline]
 pub fn onion_hop_data_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       use lightning::util::ser::ReadableArgs;
        use bitcoin::secp256k1::PublicKey;
+       use lightning::util::ser::ReadableArgs;
        let mut r = ::std::io::Cursor::new(data);
        let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42));
-       let _ =  <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<(Option<PublicKey>, &&test_utils::TestNodeSigner)>>::read(&mut r, (None, &&node_signer));
+       let _ = <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<(
+               Option<PublicKey>,
+               &&test_utils::TestNodeSigner,
+       )>>::read(&mut r, (None, &&node_signer));
 }
 
 #[no_mangle]
 pub extern "C" fn onion_hop_data_run(data: *const u8, datalen: usize) {
-       use lightning::util::ser::ReadableArgs;
        use bitcoin::secp256k1::PublicKey;
+       use lightning::util::ser::ReadableArgs;
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
        let mut r = ::std::io::Cursor::new(data);
        let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42));
-       let _ =  <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<(Option<PublicKey>, &&test_utils::TestNodeSigner)>>::read(&mut r, (None, &&node_signer));
+       let _ = <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<(
+               Option<PublicKey>,
+               &&test_utils::TestNodeSigner,
+       )>>::read(&mut r, (None, &&node_signer));
 }
index 4e563e28a46b80fe9d701b47fb918b285bccf966..a8a290fefb3379a176ff781e8b80c8df1036804f 100644 (file)
@@ -1,25 +1,27 @@
 // Imports that need to be added manually
-use bitcoin::bech32::u5;
+use bech32::u5;
 use bitcoin::blockdata::script::ScriptBuf;
-use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self};
 use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1::ecdsa::RecoverableSignature;
 use bitcoin::secp256k1::schnorr;
+use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
 
 use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-use lightning::blinded_path::message::ForwardNode;
 use lightning::ln::features::InitFeatures;
 use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
 use lightning::ln::script::ShutdownScript;
 use lightning::offers::invoice::UnsignedBolt12Invoice;
 use lightning::offers::invoice_request::UnsignedInvoiceRequest;
-use lightning::sign::{Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
-use lightning::util::test_channel_signer::TestChannelSigner;
-use lightning::util::logger::Logger;
-use lightning::util::ser::{Readable, Writeable, Writer};
-use lightning::onion_message::messenger::{CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction};
+use lightning::onion_message::messenger::{
+       CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
+       PendingOnionMessage, Responder, ResponseInstruction,
+};
 use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler};
 use lightning::onion_message::packet::OnionMessageContents;
+use lightning::sign::{EntropySource, KeyMaterial, NodeSigner, Recipient, SignerProvider};
+use lightning::util::logger::Logger;
+use lightning::util::ser::{Readable, Writeable, Writer};
+use lightning::util::test_channel_signer::TestChannelSigner;
 
 use crate::utils::test_logger;
 
@@ -33,17 +35,19 @@ pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
                let mut secret_bytes = [1; 32];
                secret_bytes[31] = 2;
                let secret = SecretKey::from_slice(&secret_bytes).unwrap();
-               let keys_manager = KeyProvider {
-                       node_secret: secret,
-                       counter: AtomicU64::new(0),
-               };
+               let keys_manager = KeyProvider { node_secret: secret, counter: AtomicU64::new(0) };
                let node_id_lookup = EmptyNodeIdLookUp {};
                let message_router = TestMessageRouter {};
                let offers_msg_handler = TestOffersMessageHandler {};
                let custom_msg_handler = TestCustomMessageHandler {};
                let onion_messenger = OnionMessenger::new(
-                       &keys_manager, &keys_manager, logger, &node_id_lookup, &message_router,
-                       &offers_msg_handler, &custom_msg_handler
+                       &keys_manager,
+                       &keys_manager,
+                       logger,
+                       &node_id_lookup,
+                       &message_router,
+                       &offers_msg_handler,
+                       &custom_msg_handler,
                );
 
                let peer_node_id = {
@@ -79,17 +83,13 @@ struct TestMessageRouter {}
 
 impl MessageRouter for TestMessageRouter {
        fn find_path(
-               &self, _sender: PublicKey, _peers: Vec<PublicKey>, destination: Destination
+               &self, _sender: PublicKey, _peers: Vec<PublicKey>, destination: Destination,
        ) -> Result<OnionMessagePath, ()> {
-               Ok(OnionMessagePath {
-                       intermediate_nodes: vec![],
-                       destination,
-                       first_node_addresses: None,
-               })
+               Ok(OnionMessagePath { intermediate_nodes: vec![], destination, first_node_addresses: None })
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
@@ -98,7 +98,9 @@ impl MessageRouter for TestMessageRouter {
 struct TestOffersMessageHandler {}
 
 impl OffersMessageHandler for TestOffersMessageHandler {
-       fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
+       fn handle_message(
+               &self, _message: OffersMessage, _responder: Option<Responder>,
+       ) -> ResponseInstruction<OffersMessage> {
                ResponseInstruction::NoResponse
        }
 }
@@ -128,16 +130,20 @@ struct TestCustomMessageHandler {}
 
 impl CustomOnionMessageHandler for TestCustomMessageHandler {
        type CustomMessage = TestCustomMessage;
-       fn handle_custom_message(&self, message: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
+       fn handle_custom_message(
+               &self, message: Self::CustomMessage, responder: Option<Responder>,
+       ) -> ResponseInstruction<Self::CustomMessage> {
                match responder {
                        Some(responder) => responder.respond(message),
-                       None => ResponseInstruction::NoResponse
+                       None => ResponseInstruction::NoResponse,
                }
        }
-       fn read_custom_message<R: io::Read>(&self, _message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError> {
+       fn read_custom_message<R: io::Read>(
+               &self, _message_type: u64, buffer: &mut R,
+       ) -> Result<Option<Self::CustomMessage>, msgs::DecodeError> {
                let mut buf = Vec::new();
                buffer.read_to_end(&mut buf)?;
-               return Ok(Some(TestCustomMessage {}))
+               return Ok(Some(TestCustomMessage {}));
        }
        fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>> {
                vec![]
@@ -159,8 +165,11 @@ struct KeyProvider {
 impl EntropySource for KeyProvider {
        fn get_secure_random_bytes(&self) -> [u8; 32] {
                let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
-               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                       (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
+               #[rustfmt::skip]
+               let random_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8,
+                       (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8];
+               random_bytes
        }
 }
 
@@ -168,15 +177,17 @@ impl NodeSigner for KeyProvider {
        fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
                let node_secret = match recipient {
                        Recipient::Node => Ok(&self.node_secret),
-                       Recipient::PhantomNode => Err(())
+                       Recipient::PhantomNode => Err(()),
                }?;
                Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret))
        }
 
-       fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
+       fn ecdh(
+               &self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>,
+       ) -> Result<SharedSecret, ()> {
                let mut node_secret = match recipient {
                        Recipient::Node => Ok(self.node_secret.clone()),
-                       Recipient::PhantomNode => Err(())
+                       Recipient::PhantomNode => Err(()),
                }?;
                if let Some(tweak) = tweak {
                        node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
@@ -184,14 +195,18 @@ impl NodeSigner for KeyProvider {
                Ok(SharedSecret::new(other_key, &node_secret))
        }
 
-       fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!() }
+       fn get_inbound_payment_key_material(&self) -> KeyMaterial {
+               unreachable!()
+       }
 
-       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
+       fn sign_invoice(
+               &self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient,
+       ) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
 
        fn sign_bolt12_invoice_request(
-               &self, _invoice_request: &UnsignedInvoiceRequest
+               &self, _invoice_request: &UnsignedInvoiceRequest,
        ) -> Result<schnorr::Signature, ()> {
                unreachable!()
        }
@@ -202,7 +217,9 @@ impl NodeSigner for KeyProvider {
                unreachable!()
        }
 
-       fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
+       fn sign_gossip_message(
+               &self, _msg: lightning::ln::msgs::UnsignedGossipMessage,
+       ) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
                unreachable!()
        }
 }
@@ -212,17 +229,29 @@ impl SignerProvider for KeyProvider {
        #[cfg(taproot)]
        type TaprootSigner = TestChannelSigner;
 
-       fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!() }
+       fn generate_channel_keys_id(
+               &self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128,
+       ) -> [u8; 32] {
+               unreachable!()
+       }
 
-       fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner {
+       fn derive_channel_signer(
+               &self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32],
+       ) -> Self::EcdsaSigner {
                unreachable!()
        }
 
-       fn read_chan_signer(&self, _data: &[u8]) -> Result<TestChannelSigner, DecodeError> { unreachable!() }
+       fn read_chan_signer(&self, _data: &[u8]) -> Result<TestChannelSigner, DecodeError> {
+               unreachable!()
+       }
 
-       fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()> { unreachable!() }
+       fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()> {
+               unreachable!()
+       }
 
-       fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> { unreachable!() }
+       fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> {
+               unreachable!()
+       }
 }
 
 #[cfg(test)]
@@ -238,8 +267,17 @@ mod tests {
        }
        impl Logger for TrackingLogger {
                fn log(&self, record: Record) {
-                       *self.lines.lock().unwrap().entry((record.module_path.to_string(), format!("{}", record.args))).or_insert(0) += 1;
-                       println!("{:<5} [{} : {}, {}] {}", record.level.to_string(), record.module_path, record.file, record.line, record.args);
+                       let mut lines_lock = self.lines.lock().unwrap();
+                       let key = (record.module_path.to_string(), format!("{}", record.args));
+                       *lines_lock.entry(key).or_insert(0) += 1;
+                       println!(
+                               "{:<5} [{} : {}, {}] {}",
+                               record.level.to_string(),
+                               record.module_path,
+                               record.file,
+                               record.line,
+                               record.args
+                       );
                }
        }
 
index 41d8c0936060868a97df54711f725e397ea3a35d..b01aa02400b6c65a135aa5d5a454323e664eabbe 100644 (file)
@@ -7,33 +7,30 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use lightning::ln::peer_channel_encryptor::{PeerChannelEncryptor, MessageBuf};
+use lightning::ln::peer_channel_encryptor::{MessageBuf, PeerChannelEncryptor};
 use lightning::util::test_utils::TestNodeSigner;
 
-use bitcoin::secp256k1::{Secp256k1, PublicKey, SecretKey};
+use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
 
 use crate::utils::test_logger;
 
 #[inline]
 fn slice_to_be16(v: &[u8]) -> u16 {
-       ((v[0] as u16) << 8*1) |
-       ((v[1] as u16) << 8*0)
+       ((v[0] as u16) << 8 * 1) | ((v[1] as u16) << 8 * 0)
 }
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        let mut read_pos = 0;
        macro_rules! get_slice {
-               ($len: expr) => {
-                       {
-                               let slice_len = $len as usize;
-                               if data.len() < read_pos + slice_len {
-                                       return;
-                               }
-                               read_pos += slice_len;
-                               &data[read_pos - slice_len..read_pos]
+               ($len: expr) => {{
+                       let slice_len = $len as usize;
+                       if data.len() < read_pos + slice_len {
+                               return;
                        }
-               }
+                       read_pos += slice_len;
+                       &data[read_pos - slice_len..read_pos]
+               }};
        }
 
        let secp_ctx = Secp256k1::signing_only();
@@ -63,7 +60,12 @@ pub fn do_test(data: &[u8]) {
                crypter
        } else {
                let mut crypter = PeerChannelEncryptor::new_inbound(&&node_signer);
-               match crypter.process_act_one_with_keys(get_slice!(50), &&node_signer, ephemeral_key, &secp_ctx) {
+               match crypter.process_act_one_with_keys(
+                       get_slice!(50),
+                       &&node_signer,
+                       ephemeral_key,
+                       &secp_ctx,
+               ) {
                        Ok(_) => {},
                        Err(_) => return,
                }
@@ -77,9 +79,11 @@ pub fn do_test(data: &[u8]) {
        let mut buf = [0; 65536 + 16];
        loop {
                if get_slice!(1)[0] == 0 {
-                       crypter.encrypt_buffer(MessageBuf::from_encoded(&get_slice!(slice_to_be16(get_slice!(2)))));
+                       crypter.encrypt_buffer(MessageBuf::from_encoded(&get_slice!(slice_to_be16(
+                               get_slice!(2)
+                       ))));
                } else {
-                       let len = match crypter.decrypt_length_header(get_slice!(16+2)) {
+                       let len = match crypter.decrypt_length_header(get_slice!(16 + 2)) {
                                Ok(len) => len,
                                Err(_) => return,
                        };
index b4c6a29e8a99f47744fdb9fd0caf2468c7604e57..980c147e96a024f45ae44ad7e33fae9ea390154e 100644 (file)
@@ -6,7 +6,8 @@ use crate::utils::test_logger;
 /// Actual fuzz test, method signature and name are fixed
 fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
        let logger = test_logger::TestLogger::new("".to_owned(), out);
-       let network_graph = lightning::routing::gossip::NetworkGraph::new(bitcoin::Network::Bitcoin, &logger);
+       let network_graph =
+               lightning::routing::gossip::NetworkGraph::new(bitcoin::Network::Bitcoin, &logger);
        let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
        let _ = rapid_sync.update_network_graph(data);
 }
index 660ad5e2c1dae2b6d1b4c0a45b92071be22d0d37..11907b6d6965c121be2c6d612453d9169893b8d8 100644 (file)
@@ -7,17 +7,17 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey, self};
 use crate::utils::test_logger;
+use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
 use core::convert::TryFrom;
-use lightning::blinded_path::BlindedPath;
 use lightning::blinded_path::message::ForwardNode;
-use lightning::sign::EntropySource;
-use lightning::ln::PaymentHash;
+use lightning::blinded_path::BlindedPath;
 use lightning::ln::features::BlindedHopFeatures;
+use lightning::ln::PaymentHash;
 use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
 use lightning::offers::parse::Bolt12SemanticError;
 use lightning::offers::refund::Refund;
+use lightning::sign::EntropySource;
 use lightning::util::ser::Writeable;
 
 #[inline]
@@ -28,15 +28,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
                assert_eq!(data, bytes);
 
                let secp_ctx = Secp256k1::new();
-               let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let pubkey = PublicKey::from(keys);
                let mut buffer = Vec::new();
 
                if let Ok(invoice) = build_response(&refund, pubkey, &secp_ctx) {
                        invoice
-                               .sign(|message: &UnsignedBolt12Invoice|
+                               .sign(|message: &UnsignedBolt12Invoice| {
                                        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
-                               )
+                               })
                                .unwrap()
                                .write(&mut buffer)
                                .unwrap();
@@ -47,7 +47,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
 struct Randomness;
 
 impl EntropySource for Randomness {
-       fn get_secure_random_bytes(&self) -> [u8; 32] { [42; 32] }
+       fn get_secure_random_bytes(&self) -> [u8; 32] {
+               [42; 32]
+       }
 }
 
 fn pubkey(byte: u8) -> PublicKey {
@@ -60,7 +62,7 @@ fn privkey(byte: u8) -> SecretKey {
 }
 
 fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
-       refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>
+       refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>,
 ) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
        let entropy_source = Randomness {};
        let intermediate_nodes = [
@@ -74,8 +76,10 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                ],
        ];
        let paths = vec![
-               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx).unwrap(),
-               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx).unwrap(),
+               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
+                       .unwrap(),
+               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
+                       .unwrap(),
        ];
 
        let payinfo = vec![
index afe028131c1de0a3a79eb30e975a9cc6e72097a9..a4002682111cd4cbd249bb29644fa9705fb8b085 100644 (file)
@@ -7,62 +7,66 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::script::Builder;
 use bitcoin::blockdata::transaction::TxOut;
 
 use lightning::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
 use lightning::chain::transaction::OutPoint;
-use lightning::ln::ChannelId;
-use lightning::ln::channelmanager::{self, ChannelDetails, ChannelCounterparty};
+use lightning::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelShutdownState};
+use lightning::ln::channelmanager;
 use lightning::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
 use lightning::ln::msgs;
+use lightning::ln::ChannelId;
 use lightning::offers::invoice::BlindedPayInfo;
 use lightning::routing::gossip::{NetworkGraph, RoutingFees};
+use lightning::routing::router::{
+       find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters,
+};
+use lightning::routing::scoring::{
+       ProbabilisticScorer, ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters,
+};
 use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult};
-use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
-use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
 use lightning::util::config::UserConfig;
 use lightning::util::hash_tables::*;
 use lightning::util::ser::Readable;
 
 use bitcoin::hashes::Hash;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::PublicKey;
-use bitcoin::network::constants::Network;
 
 use crate::utils::test_logger;
 
 use std::convert::TryInto;
-use std::sync::Arc;
 use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Arc;
 
 #[inline]
 pub fn slice_to_be16(v: &[u8]) -> u16 {
-       ((v[0] as u16) << 8*1) |
-       ((v[1] as u16) << 8*0)
+       ((v[0] as u16) << 8 * 1) | ((v[1] as u16) << 8 * 0)
 }
 
 #[inline]
 pub fn slice_to_be32(v: &[u8]) -> u32 {
-       ((v[0] as u32) << 8*3) |
-       ((v[1] as u32) << 8*2) |
-       ((v[2] as u32) << 8*1) |
-       ((v[3] as u32) << 8*0)
+       ((v[0] as u32) << 8 * 3)
+               | ((v[1] as u32) << 8 * 2)
+               | ((v[2] as u32) << 8 * 1)
+               | ((v[3] as u32) << 8 * 0)
 }
 
 #[inline]
 pub fn slice_to_be64(v: &[u8]) -> u64 {
-       ((v[0] as u64) << 8*7) |
-       ((v[1] as u64) << 8*6) |
-       ((v[2] as u64) << 8*5) |
-       ((v[3] as u64) << 8*4) |
-       ((v[4] as u64) << 8*3) |
-       ((v[5] as u64) << 8*2) |
-       ((v[6] as u64) << 8*1) |
-       ((v[7] as u64) << 8*0)
+       ((v[0] as u64) << 8 * 7)
+               | ((v[1] as u64) << 8 * 6)
+               | ((v[2] as u64) << 8 * 5)
+               | ((v[3] as u64) << 8 * 4)
+               | ((v[4] as u64) << 8 * 3)
+               | ((v[5] as u64) << 8 * 2)
+               | ((v[6] as u64) << 8 * 1)
+               | ((v[7] as u64) << 8 * 0)
 }
 
-
 struct InputData {
        data: Vec<u8>,
        read_pos: AtomicUsize,
@@ -91,11 +95,13 @@ struct FuzzChainSource<'a, 'b, Out: test_logger::Output> {
 impl<Out: test_logger::Output> UtxoLookup for FuzzChainSource<'_, '_, Out> {
        fn get_utxo(&self, _chain_hash: &ChainHash, _short_channel_id: u64) -> UtxoResult {
                let input_slice = self.input.get_slice(2);
-               if input_slice.is_none() { return UtxoResult::Sync(Err(UtxoLookupError::UnknownTx)); }
+               if input_slice.is_none() {
+                       return UtxoResult::Sync(Err(UtxoLookupError::UnknownTx));
+               }
                let input_slice = input_slice.unwrap();
                let txo_res = TxOut {
-                       value: if input_slice[0] % 2 == 0 { 1_000_000 } else { 1_000 },
-                       script_pubkey: Builder::new().push_int(input_slice[1] as i64).into_script().to_v0_p2wsh(),
+                       value: Amount::from_sat(if input_slice[0] % 2 == 0 { 1_000_000 } else { 1_000 }),
+                       script_pubkey: Builder::new().push_int(input_slice[1] as i64).into_script().to_p2wsh(),
                };
                match input_slice {
                        &[0, _] => UtxoResult::Sync(Err(UtxoLookupError::UnknownChain)),
@@ -120,17 +126,14 @@ impl<Out: test_logger::Output> UtxoLookup for FuzzChainSource<'_, '_, Out> {
 
 #[inline]
 pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
-       let input = Arc::new(InputData {
-               data: data.to_vec(),
-               read_pos: AtomicUsize::new(0),
-       });
+       let input = Arc::new(InputData { data: data.to_vec(), read_pos: AtomicUsize::new(0) });
        macro_rules! get_slice_nonadvancing {
                ($len: expr) => {
                        match input.get_slice_nonadvancing($len as usize) {
                                Some(slice) => slice,
                                None => return,
                        }
-               }
+               };
        }
        macro_rules! get_slice {
                ($len: expr) => {
@@ -138,7 +141,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                Some(slice) => slice,
                                None => return,
                        }
-               }
+               };
        }
 
        macro_rules! decode_msg {
@@ -158,18 +161,16 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                        msgs::DecodeError::Io(e) => panic!("{:?}", e),
                                        msgs::DecodeError::UnsupportedCompression => return,
                                        msgs::DecodeError::DangerousValue => return,
-                               }
+                               },
                        }
-               }}
+               }};
        }
 
        macro_rules! decode_msg_with_len16 {
-               ($MsgType: path, $excess: expr) => {
-                       {
-                               let extra_len = slice_to_be16(get_slice_nonadvancing!(2));
-                               decode_msg!($MsgType, 2 + (extra_len as usize) + $excess)
-                       }
-               }
+               ($MsgType: path, $excess: expr) => {{
+                       let extra_len = slice_to_be16(get_slice_nonadvancing!(2));
+                       decode_msg!($MsgType, 2 + (extra_len as usize) + $excess)
+               }};
        }
 
        macro_rules! get_pubkey_from_node_id {
@@ -178,7 +179,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                Ok(pk) => pk,
                                Err(_) => return,
                        }
-               }
+               };
        }
 
        macro_rules! get_pubkey {
@@ -187,17 +188,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                Ok(key) => key,
                                Err(_) => return,
                        }
-               }
+               };
        }
 
        let logger = test_logger::TestLogger::new("".to_owned(), out);
 
        let our_pubkey = get_pubkey!();
        let net_graph = NetworkGraph::new(Network::Bitcoin, &logger);
-       let chain_source = FuzzChainSource {
-               input: Arc::clone(&input),
-               net_graph: &net_graph,
-       };
+       let chain_source = FuzzChainSource { input: Arc::clone(&input), net_graph: &net_graph };
 
        let mut node_pks = new_hash_map();
        let mut scid = 42;
@@ -209,32 +207,41 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                count => {
                                        for _ in 0..count {
                                                scid += 1;
-                                               let (rnid, _) =
-                                                       node_pks.iter().skip(u16::from_be_bytes(get_slice!(2).try_into().unwrap()) as usize % node_pks.len()).next().unwrap();
+                                               let skip = u16::from_be_bytes(get_slice!(2).try_into().unwrap()) as usize
+                                                       % node_pks.len();
+                                               let (rnid, _) = node_pks.iter().skip(skip).next().unwrap();
                                                let capacity = u64::from_be_bytes(get_slice!(8).try_into().unwrap());
                                                $first_hops_vec.push(ChannelDetails {
                                                        channel_id: ChannelId::new_zero(),
                                                        counterparty: ChannelCounterparty {
                                                                node_id: *rnid,
-                                                               features: channelmanager::provided_init_features(&UserConfig::default()),
+                                                               features: channelmanager::provided_init_features(
+                                                                       &UserConfig::default(),
+                                                               ),
                                                                unspendable_punishment_reserve: 0,
                                                                forwarding_info: None,
                                                                outbound_htlc_minimum_msat: None,
                                                                outbound_htlc_maximum_msat: None,
                                                        },
-                                                       funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
+                                                       funding_txo: Some(OutPoint {
+                                                               txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
+                                                               index: 0,
+                                                       }),
                                                        channel_type: None,
                                                        short_channel_id: Some(scid),
                                                        inbound_scid_alias: None,
                                                        outbound_scid_alias: None,
                                                        channel_value_satoshis: capacity,
-                                                       user_channel_id: 0, inbound_capacity_msat: 0,
+                                                       user_channel_id: 0,
+                                                       inbound_capacity_msat: 0,
                                                        unspendable_punishment_reserve: None,
                                                        confirmations_required: None,
                                                        confirmations: None,
                                                        force_close_spend_delay: None,
-                                                       is_outbound: true, is_channel_ready: true,
-                                                       is_usable: true, is_public: true,
+                                                       is_outbound: true,
+                                                       is_channel_ready: true,
+                                                       is_usable: true,
+                                                       is_public: true,
                                                        balance_msat: 0,
                                                        outbound_capacity_msat: capacity.saturating_mul(1000),
                                                        next_outbound_htlc_limit_msat: capacity.saturating_mul(1000),
@@ -243,7 +250,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                        inbound_htlc_maximum_msat: None,
                                                        config: None,
                                                        feerate_sat_per_1000_weight: None,
-                                                       channel_shutdown_state: Some(channelmanager::ChannelShutdownState::NotShuttingDown),
+                                                       channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
                                                        pending_inbound_htlcs: Vec::new(),
                                                        pending_outbound_htlcs: Vec::new(),
                                                });
@@ -251,7 +258,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                        Some(&$first_hops_vec[..])
                                },
                        }
-               }
+               };
        }
 
        macro_rules! last_hops {
@@ -259,8 +266,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                        let count = get_slice!(1)[0];
                        for _ in 0..count {
                                scid += 1;
-                               let (rnid, _) =
-                                       node_pks.iter().skip(slice_to_be16(get_slice!(2)) as usize % node_pks.len()).next().unwrap();
+                               let skip = slice_to_be16(get_slice!(2)) as usize % node_pks.len();
+                               let (rnid, _) = node_pks.iter().skip(skip).next().unwrap();
                                $last_hops.push(RouteHint(vec![RouteHintHop {
                                        src_node_id: *rnid,
                                        short_channel_id: scid,
@@ -273,30 +280,47 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                        htlc_maximum_msat: None,
                                }]));
                        }
-               }
+               };
        }
 
        macro_rules! find_routes {
                ($first_hops: expr, $node_pks: expr, $route_params: expr) => {
-                       let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &net_graph, &logger);
+                       let scorer = ProbabilisticScorer::new(
+                               ProbabilisticScoringDecayParameters::default(),
+                               &net_graph,
+                               &logger,
+                       );
                        let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32];
                        for (target, ()) in $node_pks {
                                let final_value_msat = slice_to_be64(get_slice!(8));
                                let final_cltv_expiry_delta = slice_to_be32(get_slice!(4));
                                let route_params = $route_params(final_value_msat, final_cltv_expiry_delta, target);
-                               let _ = find_route(&our_pubkey, &route_params, &net_graph,
-                                       $first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
-                                       &logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes);
+                               let _ = find_route(
+                                       &our_pubkey,
+                                       &route_params,
+                                       &net_graph,
+                                       $first_hops
+                                               .map(|c| c.iter().collect::<Vec<_>>())
+                                               .as_ref()
+                                               .map(|a| a.as_slice()),
+                                       &logger,
+                                       &scorer,
+                                       &ProbabilisticScoringFeeParameters::default(),
+                                       &random_seed_bytes,
+                               );
                        }
-               }
+               };
        }
 
        loop {
                match get_slice!(1)[0] {
                        0 => {
                                let start_len = slice_to_be16(&get_slice_nonadvancing!(2)[0..2]) as usize;
-                               let addr_len = slice_to_be16(&get_slice_nonadvancing!(start_len+2 + 74)[start_len+2 + 72..start_len+2 + 74]);
-                               if addr_len > (37+1)*4 {
+                               let addr_len = slice_to_be16(
+                                       &get_slice_nonadvancing!(start_len + 2 + 74)
+                                               [start_len + 2 + 72..start_len + 2 + 74],
+                               );
+                               if addr_len > (37 + 1) * 4 {
                                        return;
                                }
                                let msg = decode_msg_with_len16!(msgs::UnsignedNodeAnnouncement, 288);
@@ -304,20 +328,26 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let _ = net_graph.update_node_from_unsigned_announcement(&msg);
                        },
                        1 => {
-                               let msg = decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32+8+33*4);
+                               let msg =
+                                       decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32 + 8 + 33 * 4);
                                node_pks.insert(get_pubkey_from_node_id!(msg.node_id_1), ());
                                node_pks.insert(get_pubkey_from_node_id!(msg.node_id_2), ());
-                               let _ = net_graph.update_channel_from_unsigned_announcement::
-                                       <&FuzzChainSource<'_, '_, Out>>(&msg, &None);
+                               let _ = net_graph
+                                       .update_channel_from_unsigned_announcement::<&FuzzChainSource<'_, '_, Out>>(
+                                               &msg, &None,
+                                       );
                        },
                        2 => {
-                               let msg = decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32+8+33*4);
+                               let msg =
+                                       decode_msg_with_len16!(msgs::UnsignedChannelAnnouncement, 32 + 8 + 33 * 4);
                                node_pks.insert(get_pubkey_from_node_id!(msg.node_id_1), ());
                                node_pks.insert(get_pubkey_from_node_id!(msg.node_id_2), ());
-                               let _ = net_graph.update_channel_from_unsigned_announcement(&msg, &Some(&chain_source));
+                               let _ =
+                                       net_graph.update_channel_from_unsigned_announcement(&msg, &Some(&chain_source));
                        },
                        3 => {
-                               let _ = net_graph.update_channel_unsigned(&decode_msg!(msgs::UnsignedChannelUpdate, 72));
+                               let _ = net_graph
+                                       .update_channel_unsigned(&decode_msg!(msgs::UnsignedChannelUpdate, 72));
                        },
                        4 => {
                                let short_channel_id = slice_to_be64(get_slice!(8));
@@ -331,12 +361,18 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let first_hops = first_hops!(first_hops_vec);
                                let mut last_hops = Vec::new();
                                last_hops!(last_hops);
-                               find_routes!(first_hops, node_pks.iter(), |final_amt, final_delta, target: &PublicKey| {
-                                       RouteParameters::from_payment_params_and_value(
-                                               PaymentParameters::from_node_id(*target, final_delta)
-                                                       .with_route_hints(last_hops.clone()).unwrap(),
-                                               final_amt)
-                               });
+                               find_routes!(
+                                       first_hops,
+                                       node_pks.iter(),
+                                       |final_amt, final_delta, target: &PublicKey| {
+                                               RouteParameters::from_payment_params_and_value(
+                                                       PaymentParameters::from_node_id(*target, final_delta)
+                                                               .with_route_hints(last_hops.clone())
+                                                               .unwrap(),
+                                                       final_amt,
+                                               )
+                                       }
+                               );
                        },
                        x => {
                                let mut first_hops_vec = Vec::new();
@@ -344,38 +380,47 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let mut last_hops_unblinded = Vec::new();
                                last_hops!(last_hops_unblinded);
                                let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
-                               let last_hops: Vec<(BlindedPayInfo, BlindedPath)> = last_hops_unblinded.into_iter().map(|hint| {
-                                       let hop = &hint.0[0];
-                                       let payinfo = BlindedPayInfo {
-                                               fee_base_msat: hop.fees.base_msat,
-                                               fee_proportional_millionths: hop.fees.proportional_millionths,
-                                               htlc_minimum_msat: hop.htlc_minimum_msat.unwrap(),
-                                               htlc_maximum_msat: hop.htlc_minimum_msat.unwrap().saturating_mul(100),
-                                               cltv_expiry_delta: hop.cltv_expiry_delta,
-                                               features: BlindedHopFeatures::empty(),
-                                       };
-                                       let num_blinded_hops = x % 250;
-                                       let mut blinded_hops = Vec::new();
-                                       for _ in 0..num_blinded_hops {
-                                               blinded_hops.push(BlindedHop {
-                                                       blinded_node_id: dummy_pk,
-                                                       encrypted_payload: Vec::new()
-                                               });
-                                       }
-                                       (payinfo, BlindedPath {
-                                               introduction_node: IntroductionNode::NodeId(hop.src_node_id),
-                                               blinding_point: dummy_pk,
-                                               blinded_hops,
+                               let last_hops: Vec<(BlindedPayInfo, BlindedPath)> = last_hops_unblinded
+                                       .into_iter()
+                                       .map(|hint| {
+                                               let hop = &hint.0[0];
+                                               let payinfo = BlindedPayInfo {
+                                                       fee_base_msat: hop.fees.base_msat,
+                                                       fee_proportional_millionths: hop.fees.proportional_millionths,
+                                                       htlc_minimum_msat: hop.htlc_minimum_msat.unwrap(),
+                                                       htlc_maximum_msat: hop.htlc_minimum_msat.unwrap().saturating_mul(100),
+                                                       cltv_expiry_delta: hop.cltv_expiry_delta,
+                                                       features: BlindedHopFeatures::empty(),
+                                               };
+                                               let num_blinded_hops = x % 250;
+                                               let mut blinded_hops = Vec::new();
+                                               for _ in 0..num_blinded_hops {
+                                                       blinded_hops.push(BlindedHop {
+                                                               blinded_node_id: dummy_pk,
+                                                               encrypted_payload: Vec::new(),
+                                                       });
+                                               }
+                                               (
+                                                       payinfo,
+                                                       BlindedPath {
+                                                               introduction_node: IntroductionNode::NodeId(hop.src_node_id),
+                                                               blinding_point: dummy_pk,
+                                                               blinded_hops,
+                                                       },
+                                               )
                                        })
-                               }).collect();
+                                       .collect();
                                let mut features = Bolt12InvoiceFeatures::empty();
                                features.set_basic_mpp_optional();
                                find_routes!(first_hops, [(dummy_pk, ())].iter(), |final_amt, _, _| {
-                                       RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(last_hops.clone())
-                                               .with_bolt12_features(features.clone()).unwrap(),
-                                       final_amt)
+                                       RouteParameters::from_payment_params_and_value(
+                                               PaymentParameters::blinded(last_hops.clone())
+                                                       .with_bolt12_features(features.clone())
+                                                       .unwrap(),
+                                               final_amt,
+                                       )
                                });
-                       }
+                       },
                }
        }
 }
index 5e5817e23f1f92d18f5d83406db2cff23319491d..6d9de02e387b62b4c8577d8c0f3496b6fe1b9067 100644 (file)
@@ -8,10 +8,10 @@
 // licenses.
 
 use lightning::util::logger::{Logger, Record};
-use std::sync::{Arc, Mutex};
 use std::io::Write;
+use std::sync::{Arc, Mutex};
 
-pub trait Output : Clone  + 'static {
+pub trait Output: Clone + 'static {
        fn locked_write(&self, data: &[u8]);
 }
 
@@ -36,7 +36,7 @@ impl StringBuffer {
        }
 }
 
-pub struct TestLogger<Out : Output> {
+pub struct TestLogger<Out: Output> {
        id: String,
        out: Out,
 }
@@ -52,13 +52,22 @@ impl<'a, Out: Output> Write for LockedWriteAdapter<'a, Out> {
                self.0.locked_write(data);
                Ok(data.len())
        }
-       fn flush(&mut self) -> Result<(), std::io::Error> { Ok(()) }
+       fn flush(&mut self) -> Result<(), std::io::Error> {
+               Ok(())
+       }
 }
 
 impl<Out: Output> Logger for TestLogger<Out> {
        fn log(&self, record: Record) {
-               write!(LockedWriteAdapter(&self.out),
-                       "{:<5} {} [{} : {}] {}\n", record.level.to_string(), self.id, record.module_path, record.line, record.args)
-                       .unwrap();
+               write!(
+                       LockedWriteAdapter(&self.out),
+                       "{:<5} {} [{} : {}] {}\n",
+                       record.level.to_string(),
+                       self.id,
+                       record.module_path,
+                       record.line,
+                       record.args
+               )
+               .unwrap();
        }
 }
index a99c397d0b2341c8c4b8b6d76b1f13a345c85540..7de3cc6bebb5252a3feaa25c8983d6060c3560c0 100644 (file)
@@ -1,6 +1,6 @@
 use lightning::chain;
-use lightning::chain::{chainmonitor, channelmonitor};
 use lightning::chain::transaction::OutPoint;
+use lightning::chain::{chainmonitor, channelmonitor};
 use lightning::util::test_channel_signer::TestChannelSigner;
 
 use std::sync::Mutex;
@@ -9,14 +9,18 @@ pub struct TestPersister {
        pub update_ret: Mutex<chain::ChannelMonitorUpdateStatus>,
 }
 impl chainmonitor::Persist<TestChannelSigner> for TestPersister {
-       fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<TestChannelSigner>) -> chain::ChannelMonitorUpdateStatus {
+       fn persist_new_channel(
+               &self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<TestChannelSigner>,
+       ) -> chain::ChannelMonitorUpdateStatus {
                self.update_ret.lock().unwrap().clone()
        }
 
-       fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor<TestChannelSigner>) -> chain::ChannelMonitorUpdateStatus {
+       fn update_persisted_channel(
+               &self, _funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>,
+               _data: &channelmonitor::ChannelMonitor<TestChannelSigner>,
+       ) -> chain::ChannelMonitorUpdateStatus {
                self.update_ret.lock().unwrap().clone()
        }
 
-       fn archive_persisted_channel(&self, _: OutPoint) {
-       }
+       fn archive_persisted_channel(&self, _: OutPoint) {}
 }
index 5148bb81ea48a7021f3541fa647f644bd1b87a3e..e563e2acd9b09a338a6e3ce52e2e1d682726d428 100644 (file)
@@ -21,7 +21,7 @@ no-std = ["bitcoin/no-std", "lightning/no-std", "lightning-rapid-gossip-sync/no-
 default = ["std"]
 
 [dependencies]
-bitcoin = { version = "0.30.2", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false }
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false }
 lightning-rapid-gossip-sync = { version = "0.0.123-beta", path = "../lightning-rapid-gossip-sync", default-features = false }
 
index ad1056ea92222007c49e4ca7a364a7408e16d570..4719d7e5c1aba8a7dd15c1bdf47f1447f872d39a 100644 (file)
@@ -27,11 +27,12 @@ use lightning::chain::chainmonitor::{ChainMonitor, Persist};
 use lightning::events::{Event, PathFailure};
 #[cfg(feature = "std")]
 use lightning::events::EventHandler;
-#[cfg(any(feature = "std", feature = "futures"))]
+#[cfg(feature = "std")]
 use lightning::events::EventsProvider;
 
 use lightning::ln::channelmanager::AChannelManager;
 use lightning::ln::msgs::OnionMessageHandler;
+use lightning::onion_message::messenger::AOnionMessenger;
 use lightning::ln::peer_handler::APeerManager;
 use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
 use lightning::routing::utxo::UtxoLookup;
@@ -55,7 +56,7 @@ use std::thread::{self, JoinHandle};
 use std::time::Instant;
 
 #[cfg(not(feature = "std"))]
-use alloc::vec::Vec;
+use alloc::boxed::Box;
 
 /// `BackgroundProcessor` takes care of tasks that (1) need to happen periodically to keep
 /// Rust-Lightning running properly, and (2) either can or should be run in the background. Its
@@ -281,7 +282,8 @@ macro_rules! define_run_body {
        (
                $persister: ident, $chain_monitor: ident, $process_chain_monitor_events: expr,
                $channel_manager: ident, $process_channel_manager_events: expr,
-               $peer_manager: ident, $process_onion_message_handler_events: expr, $gossip_sync: ident,
+               $onion_messenger: ident, $process_onion_message_handler_events: expr,
+               $peer_manager: ident, $gossip_sync: ident,
                $logger: ident, $scorer: ident, $loop_exit_check: expr, $await: expr, $get_timer: expr,
                $timer_elapsed: expr, $check_slow_await: expr, $time_fetch: expr,
        ) => { {
@@ -347,8 +349,10 @@ macro_rules! define_run_body {
                                last_freshness_call = $get_timer(FRESHNESS_TIMER);
                        }
                        if $timer_elapsed(&mut last_onion_message_handler_call, ONION_MESSAGE_HANDLER_TIMER) {
-                               log_trace!($logger, "Calling OnionMessageHandler's timer_tick_occurred");
-                               $peer_manager.onion_message_handler().timer_tick_occurred();
+                               if let Some(om) = &$onion_messenger {
+                                       log_trace!($logger, "Calling OnionMessageHandler's timer_tick_occurred");
+                                       om.get_om().timer_tick_occurred();
+                               }
                                last_onion_message_handler_call = $get_timer(ONION_MESSAGE_HANDLER_TIMER);
                        }
                        if await_slow {
@@ -564,6 +568,7 @@ use core::task;
 /// # type NetworkGraph = lightning::routing::gossip::NetworkGraph<Arc<Logger>>;
 /// # type P2PGossipSync<UL> = lightning::routing::gossip::P2PGossipSync<Arc<NetworkGraph>, Arc<UL>, Arc<Logger>>;
 /// # type ChannelManager<B, F, FE> = lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor<B, F, FE>, B, FE, Logger>;
+/// # type OnionMessenger<B, F, FE> = lightning::onion_message::messenger::OnionMessenger<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<Logger>, Arc<ChannelManager<B, F, FE>>, Arc<lightning::onion_message::messenger::DefaultMessageRouter<Arc<NetworkGraph>, Arc<Logger>, Arc<lightning::sign::KeysManager>>>, Arc<ChannelManager<B, F, FE>>, lightning::ln::peer_handler::IgnoringMessageHandler>;
 /// # type Scorer = RwLock<lightning::routing::scoring::ProbabilisticScorer<Arc<NetworkGraph>, Arc<Logger>>>;
 /// # type PeerManager<B, F, FE, UL> = lightning::ln::peer_handler::SimpleArcPeerManager<SocketDescriptor, ChainMonitor<B, F, FE>, B, FE, Arc<UL>, Logger>;
 /// #
@@ -576,6 +581,7 @@ use core::task;
 /// #     peer_manager: Arc<PeerManager<B, F, FE, UL>>,
 /// #     event_handler: Arc<EventHandler>,
 /// #     channel_manager: Arc<ChannelManager<B, F, FE>>,
+/// #     onion_messenger: Arc<OnionMessenger<B, F, FE>>,
 /// #     chain_monitor: Arc<ChainMonitor<B, F, FE>>,
 /// #     gossip_sync: Arc<P2PGossipSync<UL>>,
 /// #     persister: Arc<Store>,
@@ -595,6 +601,7 @@ use core::task;
 ///    let background_chan_man = Arc::clone(&node.channel_manager);
 ///    let background_gossip_sync = GossipSync::p2p(Arc::clone(&node.gossip_sync));
 ///    let background_peer_man = Arc::clone(&node.peer_manager);
+///    let background_onion_messenger = Arc::clone(&node.onion_messenger);
 ///    let background_logger = Arc::clone(&node.logger);
 ///    let background_scorer = Arc::clone(&node.scorer);
 ///
@@ -619,6 +626,7 @@ use core::task;
 ///                    |e| background_event_handler.handle_event(e),
 ///                    background_chain_mon,
 ///                    background_chan_man,
+///                    Some(background_onion_messenger),
 ///                    background_gossip_sync,
 ///                    background_peer_man,
 ///                    background_logger,
@@ -651,6 +659,7 @@ pub async fn process_events_async<
        PS: 'static + Deref + Send,
        M: 'static + Deref<Target = ChainMonitor<<CM::Target as AChannelManager>::Signer, CF, T, F, L, P>> + Send + Sync,
        CM: 'static + Deref + Send + Sync,
+       OM: 'static + Deref + Send + Sync,
        PGS: 'static + Deref<Target = P2PGossipSync<G, UL, L>> + Send + Sync,
        RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
        PM: 'static + Deref + Send + Sync,
@@ -661,6 +670,7 @@ pub async fn process_events_async<
        FetchTime: Fn() -> Option<Duration>,
 >(
        persister: PS, event_handler: EventHandler, chain_monitor: M, channel_manager: CM,
+       onion_messenger: Option<OM>,
        gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM, logger: L, scorer: Option<S>,
        sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime,
 ) -> Result<(), lightning::io::Error>
@@ -673,6 +683,7 @@ where
        P::Target: 'static + Persist<<CM::Target as AChannelManager>::Signer>,
        PS::Target: 'static + Persister<'a, CM, L, SC>,
        CM::Target: AChannelManager + Send + Sync,
+       OM::Target: AOnionMessenger + Send + Sync,
        PM::Target: APeerManager + Send + Sync,
 {
        let mut should_break = false;
@@ -683,7 +694,7 @@ where
                let logger = &logger;
                let persister = &persister;
                let fetch_time = &fetch_time;
-               async move {
+               Box::pin(async move { // We should be able to drop the Box once our MSRV is 1.68
                        if let Some(network_graph) = network_graph {
                                handle_network_graph_update(network_graph, &event)
                        }
@@ -698,14 +709,14 @@ where
                                }
                        }
                        event_handler(event).await;
-               }
+               })
        };
        define_run_body!(
                persister, chain_monitor,
                chain_monitor.process_pending_events_async(async_event_handler).await,
                channel_manager, channel_manager.get_cm().process_pending_events_async(async_event_handler).await,
-               peer_manager, process_onion_message_handler_events_async(&peer_manager, async_event_handler).await,
-               gossip_sync, logger, scorer, should_break, {
+               onion_messenger, if let Some(om) = &onion_messenger { om.get_om().process_pending_events_async(async_event_handler).await },
+               peer_manager, gossip_sync, logger, scorer, should_break, {
                        let fut = Selector {
                                a: channel_manager.get_cm().get_event_or_persistence_needed_future(),
                                b: chain_monitor.get_update_future(),
@@ -729,25 +740,6 @@ where
        )
 }
 
-#[cfg(feature = "futures")]
-async fn process_onion_message_handler_events_async<
-       EventHandlerFuture: core::future::Future<Output = ()>,
-       EventHandler: Fn(Event) -> EventHandlerFuture,
-       PM: 'static + Deref + Send + Sync,
->(
-       peer_manager: &PM, handler: EventHandler
-)
-where
-       PM::Target: APeerManager + Send + Sync,
-{
-       let events = core::cell::RefCell::new(Vec::new());
-       peer_manager.onion_message_handler().process_pending_events(&|e| events.borrow_mut().push(e));
-
-       for event in events.into_inner() {
-               handler(event).await
-       }
-}
-
 #[cfg(feature = "std")]
 impl BackgroundProcessor {
        /// Start a background thread that takes care of responsibilities enumerated in the [top-level
@@ -807,6 +799,7 @@ impl BackgroundProcessor {
                PS: 'static + Deref + Send,
                M: 'static + Deref<Target = ChainMonitor<<CM::Target as AChannelManager>::Signer, CF, T, F, L, P>> + Send + Sync,
                CM: 'static + Deref + Send + Sync,
+               OM: 'static + Deref + Send + Sync,
                PGS: 'static + Deref<Target = P2PGossipSync<G, UL, L>> + Send + Sync,
                RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
                PM: 'static + Deref + Send + Sync,
@@ -814,6 +807,7 @@ impl BackgroundProcessor {
                SC: for <'b> WriteableScore<'b>,
        >(
                persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM,
+               onion_messenger: Option<OM>,
                gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM, logger: L, scorer: Option<S>,
        ) -> Self
        where
@@ -825,6 +819,7 @@ impl BackgroundProcessor {
                P::Target: 'static + Persist<<CM::Target as AChannelManager>::Signer>,
                PS::Target: 'static + Persister<'a, CM, L, SC>,
                CM::Target: AChannelManager + Send + Sync,
+               OM::Target: AOnionMessenger + Send + Sync,
                PM::Target: APeerManager + Send + Sync,
        {
                let stop_thread = Arc::new(AtomicBool::new(false));
@@ -851,9 +846,8 @@ impl BackgroundProcessor {
                        define_run_body!(
                                persister, chain_monitor, chain_monitor.process_pending_events(&event_handler),
                                channel_manager, channel_manager.get_cm().process_pending_events(&event_handler),
-                               peer_manager,
-                               peer_manager.onion_message_handler().process_pending_events(&event_handler),
-                               gossip_sync, logger, scorer, stop_thread.load(Ordering::Acquire),
+                               onion_messenger, if let Some(om) = &onion_messenger { om.get_om().process_pending_events(&event_handler) },
+                               peer_manager, gossip_sync, logger, scorer, stop_thread.load(Ordering::Acquire),
                                { Sleeper::from_two_futures(
                                        &channel_manager.get_cm().get_event_or_persistence_needed_future(),
                                        &chain_monitor.get_update_future()
@@ -919,13 +913,14 @@ impl Drop for BackgroundProcessor {
 
 #[cfg(all(feature = "std", test))]
 mod tests {
-       use bitcoin::{ScriptBuf, Txid};
+       use bitcoin::{Amount, ScriptBuf, Txid};
        use bitcoin::blockdata::constants::{genesis_block, ChainHash};
        use bitcoin::blockdata::locktime::absolute::LockTime;
        use bitcoin::blockdata::transaction::{Transaction, TxOut};
        use bitcoin::hashes::Hash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1};
+       use bitcoin::transaction::Version;
        use lightning::chain::{BestBlock, Confirm, chainmonitor, Filter};
        use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
        use lightning::sign::{InMemorySigner, KeysManager, ChangeDestinationSource};
@@ -939,6 +934,7 @@ mod tests {
        use lightning::ln::functional_test_utils::*;
        use lightning::ln::msgs::{ChannelMessageHandler, Init};
        use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler};
+       use lightning::onion_message::messenger::{DefaultMessageRouter, OnionMessenger};
        use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
        use lightning::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp, LockableScore};
        use lightning::routing::router::{DefaultRouter, Path, RouteHop, CandidateRouteHop};
@@ -1000,11 +996,14 @@ mod tests {
        type PGS = Arc<P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>>;
        type RGS = Arc<RapidGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>>>;
 
+       type OM = OnionMessenger<Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestLogger>, Arc<ChannelManager>, Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<KeysManager>>>, IgnoringMessageHandler, IgnoringMessageHandler>;
+
        struct Node {
                node: Arc<ChannelManager>,
+               messenger: Arc<OM>,
                p2p_gossip_sync: PGS,
                rapid_gossip_sync: RGS,
-               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, IgnoringMessageHandler, Arc<test_utils::TestLogger>, IgnoringMessageHandler, Arc<KeysManager>>>,
+               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, Arc<OM>, Arc<test_utils::TestLogger>, IgnoringMessageHandler, Arc<KeysManager>>>,
                chain_monitor: Arc<ChainMonitor>,
                kv_store: Arc<FilesystemStore>,
                tx_broadcaster: Arc<test_utils::TestBroadcaster>,
@@ -1283,6 +1282,7 @@ mod tests {
                        let seed = [i as u8; 32];
                        let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
                        let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), Arc::clone(&keys_manager), scorer.clone(), Default::default()));
+                       let msg_router = Arc::new(DefaultMessageRouter::new(network_graph.clone(), Arc::clone(&keys_manager)));
                        let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Bitcoin));
                        let kv_store = Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into()));
                        let now = Duration::from_secs(genesis_block.header.time as u64);
@@ -1291,6 +1291,7 @@ mod tests {
                        let best_block = BestBlock::from_network(network);
                        let params = ChainParameters { network, best_block };
                        let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), router.clone(), logger.clone(), keys_manager.clone(), keys_manager.clone(), keys_manager.clone(), UserConfig::default(), params, genesis_block.header.time));
+                       let messenger = Arc::new(OnionMessenger::new(keys_manager.clone(), keys_manager.clone(), logger.clone(), manager.clone(), msg_router.clone(), IgnoringMessageHandler {}, IgnoringMessageHandler {}));
                        let wallet = Arc::new(TestWallet {});
                        let sweeper = Arc::new(OutputSweeper::new(best_block, Arc::clone(&tx_broadcaster), Arc::clone(&fee_estimator),
                                None::<Arc<dyn Filter + Sync + Send>>, Arc::clone(&keys_manager), wallet, Arc::clone(&kv_store), Arc::clone(&logger)));
@@ -1299,10 +1300,10 @@ mod tests {
                        let msg_handler = MessageHandler {
                                chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet))),
                                route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()),
-                               onion_message_handler: IgnoringMessageHandler{}, custom_message_handler: IgnoringMessageHandler{}
+                               onion_message_handler: messenger.clone(), custom_message_handler: IgnoringMessageHandler{}
                        };
                        let peer_manager = Arc::new(PeerManager::new(msg_handler, 0, &seed, logger.clone(), keys_manager.clone()));
-                       let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, kv_store, tx_broadcaster, network_graph, logger, best_block, scorer, sweeper };
+                       let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, kv_store, tx_broadcaster, network_graph, logger, best_block, scorer, sweeper, messenger };
                        nodes.push(node);
                }
 
@@ -1350,8 +1351,8 @@ mod tests {
                                        assert_eq!(channel_value_satoshis, $channel_value);
                                        assert_eq!(user_channel_id, 42);
 
-                                       let tx = Transaction { version: 1 as i32, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                                               value: channel_value_satoshis, script_pubkey: output_script.clone(),
+                                       let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                                               value: Amount::from_sat(channel_value_satoshis), script_pubkey: output_script.clone(),
                                        }]};
                                        (temporary_channel_id, tx)
                                },
@@ -1425,7 +1426,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                macro_rules! check_persisted_data {
                        ($node: expr, $filepath: expr) => {
@@ -1460,7 +1461,8 @@ mod tests {
                }
 
                // Force-close the channel.
-               nodes[0].node.force_close_broadcasting_latest_txn(&ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }), &nodes[1].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[0].node.force_close_broadcasting_latest_txn(&ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }), &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
 
                // Check that the force-close updates are persisted.
                check_persisted_data!(nodes[0].node, filepath.clone());
@@ -1492,7 +1494,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
                loop {
                        let log_entries = nodes[0].logger.lines.lock().unwrap();
                        let desired_log_1 = "Calling ChannelManager's timer_tick_occurred".to_string();
@@ -1521,7 +1523,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test"));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
                match bg_processor.join() {
                        Ok(_) => panic!("Expected error persisting manager"),
                        Err(e) => {
@@ -1542,7 +1544,7 @@ mod tests {
                let persister = Arc::new(Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test"));
 
                let bp_future = super::process_events_async(
-                       persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(),
+                       persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()),
                        nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(),
                        Some(nodes[0].scorer.clone()), move |dur: Duration| {
                                Box::pin(async move {
@@ -1567,7 +1569,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir).with_graph_error(std::io::ErrorKind::Other, "test"));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                match bg_processor.stop() {
                        Ok(_) => panic!("Expected error persisting network graph"),
@@ -1585,7 +1587,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir).with_scorer_error(std::io::ErrorKind::Other, "test"));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(),  nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(),  nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                match bg_processor.stop() {
                        Ok(_) => panic!("Expected error persisting scorer"),
@@ -1613,7 +1615,7 @@ mod tests {
                        _ => panic!("Unexpected event: {:?}", event),
                };
 
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                // Open a channel and check that the FundingGenerationReady event was handled.
                begin_open_channel!(nodes[0], nodes[1], channel_value);
@@ -1653,10 +1655,11 @@ mod tests {
                        _ => panic!("Unexpected event: {:?}", event),
                };
                let persister = Arc::new(Persister::new(data_dir));
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                // Force close the channel and check that the SpendableOutputs event was handled.
-               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                let commitment_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().pop().unwrap();
                confirm_transaction_depth(&mut nodes[0], &commitment_tx, BREAKDOWN_TIMEOUT as u32);
 
@@ -1764,7 +1767,7 @@ mod tests {
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir));
                let event_handler = |_: _| {};
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                loop {
                        let log_entries = nodes[0].logger.lines.lock().unwrap();
@@ -1837,7 +1840,7 @@ mod tests {
                let persister = Arc::new(Persister::new(data_dir).with_graph_persistence_notifier(sender));
 
                let event_handler = |_: _| {};
-               let background_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let background_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                do_test_not_pruning_network_graph_until_graph_sync_completion!(nodes,
                        receiver.recv_timeout(Duration::from_secs(super::FIRST_NETWORK_PRUNE_TIMER * 5)),
@@ -1857,7 +1860,7 @@ mod tests {
 
                let (exit_sender, exit_receiver) = tokio::sync::watch::channel(());
                let bp_future = super::process_events_async(
-                       persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(),
+                       persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()),
                        nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(),
                        Some(nodes[0].scorer.clone()), move |dur: Duration| {
                                let mut exit_receiver = exit_receiver.clone();
@@ -1995,7 +1998,7 @@ mod tests {
                let (_, nodes) = create_nodes(1, "test_payment_path_scoring");
                let data_dir = nodes[0].kv_store.get_data_dir();
                let persister = Arc::new(Persister::new(data_dir));
-               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone()));
 
                do_test_payment_path_scoring!(nodes, receiver.recv_timeout(Duration::from_secs(EVENT_DEADLINE)));
 
@@ -2032,7 +2035,7 @@ mod tests {
                let (exit_sender, exit_receiver) = tokio::sync::watch::channel(());
 
                let bp_future = super::process_events_async(
-                       persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(),
+                       persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), Some(nodes[0].messenger.clone()),
                        nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(),
                        Some(nodes[0].scorer.clone()), move |dur: Duration| {
                                let mut exit_receiver = exit_receiver.clone();
index c55281f6ccc4b59e7ab0c1bb9690a4371717fb5c..b232a6ae4abbfd7bd740893ae3dcdbc021634e3e 100644 (file)
@@ -18,7 +18,7 @@ rest-client = [ "serde_json", "chunked_transfer" ]
 rpc-client = [ "serde_json", "chunked_transfer" ]
 
 [dependencies]
-bitcoin = "0.30.2"
+bitcoin = "0.31.2"
 hex = { package = "hex-conservative", version = "0.1.1", default-features = false }
 lightning = { version = "0.0.123-beta", path = "../lightning" }
 tokio = { version = "1.35", features = [ "io-util", "net", "time", "rt" ], optional = true }
index ed811d2cc0c3f629e16a450937c58d8287f35689..e3bf962205043b543a39ea3dab78888659e2622a 100644 (file)
@@ -277,7 +277,7 @@ pub(crate) mod tests {
        use super::*;
        use bitcoin::blockdata::constants::genesis_block;
        use bitcoin::hashes::Hash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use hex::DisplayHex;
        use serde_json::value::Number;
        use serde_json::Value;
index ba93d12f5bcd7ff49d703e530c448b27707bd1a5..38c21f2f9cb8007e550a6febb43fe23fa0d491ce 100644 (file)
@@ -6,7 +6,7 @@ use crate::poll::{ChainPoller, Validate, ValidatedBlockHeader};
 
 use bitcoin::blockdata::block::Header;
 use bitcoin::hash_types::BlockHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 
 use lightning::chain;
 
@@ -38,7 +38,7 @@ BlockSourceResult<ValidatedBlockHeader> where B::Target: BlockSource {
 ///
 /// ```
 /// use bitcoin::hash_types::BlockHash;
-/// use bitcoin::network::constants::Network;
+/// use bitcoin::network::Network;
 ///
 /// use lightning::chain;
 /// use lightning::chain::Watch;
index 4a01d4673b31e91d56c3cb350d995c1b7a3d7403..c54e054454876799cfa2a862f23d2a3be10a0f74 100644 (file)
@@ -439,7 +439,7 @@ mod spv_client_tests {
        use crate::test_utils::{Blockchain, NullChainListener};
        use super::*;
 
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
 
        #[tokio::test]
        async fn poll_from_chain_without_headers() {
@@ -566,7 +566,7 @@ mod chain_notifier_tests {
        use crate::test_utils::{Blockchain, MockChainListener};
        use super::*;
 
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
 
        #[tokio::test]
        async fn sync_from_same_chain() {
index dcc19a4969dd3eab863c1216b17d434b93f54849..7f0f74ce5ce7b57ed66ad9b3dc427da0b41825f6 100644 (file)
@@ -3,7 +3,7 @@
 use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, BlockSourceResult};
 
 use bitcoin::hash_types::BlockHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use lightning::chain::BestBlock;
 
 use std::ops::Deref;
index b6fa6617c846e2d57f5288b0a6ecab975425081a..84c65f244f00e2c2d3fb81ebf976e535c06f8ac7 100644 (file)
@@ -5,8 +5,9 @@ use bitcoin::blockdata::block::{Block, Header, Version};
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::hash_types::{BlockHash, TxMerkleNode};
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::Transaction;
+use bitcoin::transaction;
 
 use lightning::chain;
 
@@ -44,7 +45,7 @@ impl Blockchain {
                        // Note that elsewhere in tests we assume that the merkle root of an empty block is all zeros,
                        // but that's OK because those tests don't trigger the check.
                        let coinbase = Transaction {
-                               version: 0,
+                               version: transaction::Version(0),
                                lock_time: LockTime::ZERO,
                                input: vec![],
                                output: vec![]
index b841f5f9d413d90dfa45ebe8cf18516490a9092e..98a720a2eb2778a48224bf91b963e35b72c2954c 100644 (file)
@@ -1,7 +1,7 @@
-use bitcoin::hashes::hex::FromHex;
+use bitcoin::hashes::hex::{FromHex, HexToArrayError};
 use bitcoin::pow::Work;
 
-pub fn hex_to_work(hex: &str) -> Result<Work, bitcoin::hashes::hex::Error> {
+pub fn hex_to_work(hex: &str) -> Result<Work, HexToArrayError> {
        let bytes = <[u8; 32]>::from_hex(hex)?;
        Ok(Work::from_be_bytes(bytes))
 }
@@ -9,6 +9,7 @@ pub fn hex_to_work(hex: &str) -> Result<Work, bitcoin::hashes::hex::Error> {
 #[cfg(test)]
 mod tests {
        use super::*;
+       use bitcoin::hashes::hex::HexToBytesError;
        use bitcoin::pow::Work;
 
        #[test]
@@ -19,25 +20,25 @@ mod tests {
        #[test]
        fn hex_to_work_too_short_str() {
                let hex = String::from_utf8(vec![b'0'; 32]).unwrap();
-               assert_eq!(hex_to_work(&hex), Err(bitcoin::hashes::hex::Error::InvalidLength(64, 32)));
+               assert_eq!(hex_to_work(&hex), Err(HexToArrayError::InvalidLength(32, 64)));
        }
 
        #[test]
        fn hex_to_work_too_long_str() {
                let hex = String::from_utf8(vec![b'0'; 128]).unwrap();
-               assert_eq!(hex_to_work(&hex), Err(bitcoin::hashes::hex::Error::InvalidLength(64, 128)));
+               assert_eq!(hex_to_work(&hex), Err(HexToArrayError::InvalidLength(128, 64)));
        }
 
        #[test]
        fn hex_to_work_odd_length_str() {
                let hex = String::from_utf8(vec![b'0'; 65]).unwrap();
-               assert_eq!(hex_to_work(&hex), Err(bitcoin::hashes::hex::Error::OddLengthString(65)));
+               assert_eq!(hex_to_work(&hex), Err(HexToArrayError::Conversion(HexToBytesError::OddLengthString(65))));
        }
 
        #[test]
        fn hex_to_work_invalid_char() {
                let hex = String::from_utf8(vec![b'G'; 64]).unwrap();
-               assert_eq!(hex_to_work(&hex), Err(bitcoin::hashes::hex::Error::InvalidChar(b'G')));
+               assert_eq!(hex_to_work(&hex), Err(HexToArrayError::Conversion(HexToBytesError::InvalidChar(b'G'))));
        }
 
        #[test]
index 6b150280b6016e0794896371af993473a7a8a825..ce358159596172f69c3ce06a3ce5035395989de1 100644 (file)
@@ -14,5 +14,5 @@ all-features = true
 rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
-bitcoin = "0.30.2"
+bitcoin = "0.31.2"
 lightning = { version = "0.0.123-beta", path = "../lightning" }
index e2000bc5804c35023c669a94240c4406619f44ef..a0948f23b5fb383d0b82c5156346e5822baa4fdc 100644 (file)
@@ -20,7 +20,7 @@
 //!
 //! # use bitcoin::secp256k1::PublicKey;
 //! # use lightning::io;
-//! # use lightning::ln::msgs::{DecodeError, LightningError};
+//! # use lightning::ln::msgs::{DecodeError, Init, LightningError};
 //! # use lightning::ln::features::{InitFeatures, NodeFeatures};
 //! use lightning::ln::peer_handler::CustomMessageHandler;
 //! use lightning::ln::wire::{CustomMessageReader, self};
 //! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 //! #         unimplemented!()
 //! #     }
+//! #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
+//! #         unimplemented!()
+//! #     }
+//! #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
+//! #         unimplemented!()
+//! #     }
 //! #     fn provided_node_features(&self) -> NodeFeatures {
 //! #         unimplemented!()
 //! #     }
 //! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 //! #         unimplemented!()
 //! #     }
+//! #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
+//! #         unimplemented!()
+//! #     }
+//! #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
+//! #         unimplemented!()
+//! #     }
 //! #     fn provided_node_features(&self) -> NodeFeatures {
 //! #         unimplemented!()
 //! #     }
 //! #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 //! #         unimplemented!()
 //! #     }
+//! #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
+//! #         unimplemented!()
+//! #     }
+//! #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
+//! #         unimplemented!()
+//! #     }
 //! #     fn provided_node_features(&self) -> NodeFeatures {
 //! #         unimplemented!()
 //! #     }
@@ -287,6 +305,22 @@ macro_rules! composite_custom_message_handler {
                                        .collect()
                        }
 
+                       fn peer_disconnected(&self, their_node_id: &$crate::bitcoin::secp256k1::PublicKey) {
+                               $(
+                                       self.$field.peer_disconnected(their_node_id);
+                               )*
+                       }
+
+                       fn peer_connected(&self, their_node_id: &$crate::bitcoin::secp256k1::PublicKey, msg: &$crate::lightning::ln::msgs::Init, inbound: bool) -> Result<(), ()> {
+                               let mut result = Ok(());
+                               $(
+                                       if let Err(e) = self.$field.peer_connected(their_node_id, msg, inbound) {
+                                               result = Err(e);
+                                       }
+                               )*
+                               result
+                       }
+
                        fn provided_node_features(&self) -> $crate::lightning::ln::features::NodeFeatures {
                                $crate::lightning::ln::features::NodeFeatures::empty()
                                        $(
index 1ebf67be1ad43f78776ed6e8e187ee6e2bace16b..22f8616a2f9731ab5be7c3c110870fe1e96cabb6 100644 (file)
@@ -20,11 +20,11 @@ no-std = ["lightning/no-std"]
 std = ["bitcoin/std", "lightning/std", "bech32/std"]
 
 [dependencies]
-bech32 = { version = "0.9.0", default-features = false }
+bech32 = { version = "0.9.1", default-features = false }
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false }
-secp256k1 = { version = "0.27.0", default-features = false, features = ["recovery", "alloc"] }
+secp256k1 = { version = "0.28.0", default-features = false, features = ["recovery", "alloc"] }
 serde = { version = "1.0.118", optional = true }
-bitcoin = { version = "0.30.2", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false }
 
 [dev-dependencies]
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false, features = ["_test_utils"] }
index 381c7b645f9cc5ae765809f84a469e984c850ea4..bd9f4a5f6dedcf2b15502f821a6951a92ec5e99f 100644 (file)
@@ -10,8 +10,7 @@ use core::str::FromStr;
 
 use bech32::{u5, FromBase32};
 
-use bitcoin::{PubkeyHash, ScriptHash};
-use bitcoin::address::WitnessVersion;
+use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256;
 use crate::prelude::*;
@@ -551,10 +550,10 @@ impl FromBase32 for Fallback {
                        return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
                }
 
-               let version = field_data[0];
+               let version = field_data[0].to_u8();
                let bytes = Vec::<u8>::from_base32(&field_data[1..])?;
 
-               match version.to_u8() {
+               match version {
                        0..=16 => {
                                if bytes.len() < 2 || bytes.len() > 40 {
                                        return Err(Bolt11ParseError::InvalidSegWitProgramLength);
@@ -568,14 +567,14 @@ impl FromBase32 for Fallback {
                        17 => {
                                let pkh = match PubkeyHash::from_slice(&bytes) {
                                        Ok(pkh) => pkh,
-                                       Err(bitcoin::hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidPubKeyHashLength),
+                                       Err(_) => return Err(Bolt11ParseError::InvalidPubKeyHashLength),
                                };
                                Ok(Fallback::PubKeyHash(pkh))
                        }
                        18 => {
                                let sh = match ScriptHash::from_slice(&bytes) {
                                        Ok(sh) => sh,
-                                       Err(bitcoin::hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidScriptHashLength),
+                                       Err(_) => return Err(Bolt11ParseError::InvalidScriptHashLength),
                                };
                                Ok(Fallback::ScriptHash(sh))
                        }
@@ -862,8 +861,7 @@ mod test {
        fn test_parse_fallback() {
                use crate::Fallback;
                use bech32::FromBase32;
-               use bitcoin::{PubkeyHash, ScriptHash};
-               use bitcoin::address::WitnessVersion;
+               use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
                use bitcoin::hashes::Hash;
 
                let cases = vec![
index fb34240bee1b32ee397f9acce1de769db65bf9a7..e427bf3ccb99965a4ba50d8609c3dad186cf3658 100644 (file)
@@ -42,8 +42,8 @@ extern crate serde;
 use std::time::SystemTime;
 
 use bech32::u5;
-use bitcoin::{Address, Network, PubkeyHash, ScriptHash};
-use bitcoin::address::{Payload, WitnessProgram, WitnessVersion};
+use bitcoin::{Address, Network, PubkeyHash, ScriptHash, WitnessProgram, WitnessVersion};
+use bitcoin::address::Payload;
 use bitcoin::hashes::{Hash, sha256};
 use lightning::ln::features::Bolt11InvoiceFeatures;
 use lightning::util::invoice::construct_invoice_preimage;
@@ -878,8 +878,7 @@ impl SignedRawBolt11Invoice {
 
        /// Recovers the public key used for signing the invoice from the recoverable signature.
        pub fn recover_payee_pub_key(&self) -> Result<PayeePubKey, secp256k1::Error> {
-               let hash = Message::from_slice(&self.hash[..])
-                       .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
+               let hash = Message::from_digest(self.hash);
 
                Ok(PayeePubKey(Secp256k1::new().recover_ecdsa(
                        &hash,
@@ -904,8 +903,7 @@ impl SignedRawBolt11Invoice {
                let pub_key = included_pub_key.or(recovered_pub_key.as_ref())
                        .expect("One is always present");
 
-               let hash = Message::from_slice(&self.hash[..])
-                       .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
+               let hash = Message::from_digest(self.hash);
 
                let secp_context = Secp256k1::new();
                let verification_result = secp_context.verify_ecdsa(
@@ -999,8 +997,7 @@ impl RawBolt11Invoice {
                where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
        {
                let raw_hash = self.signable_hash();
-               let hash = Message::from_slice(&raw_hash[..])
-                       .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
+               let hash = Message::from_digest(raw_hash);
                let signature = sign_method(&hash)?;
 
                Ok(SignedRawBolt11Invoice {
index dc63783bfa388fc35f7394d8cc243471683df99e..b4f7c778d8af19294499ea4d93cc46fa07daf909 100644 (file)
@@ -329,7 +329,7 @@ impl ToBase32 for Fallback {
        fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
                match *self {
                        Fallback::SegWitProgram {version: v, program: ref p} => {
-                               writer.write_u5(Into::<u5>::into(v))?;
+                               writer.write_u5(u5::try_from_u8(v.to_num()).expect("witness version <= 16"))?;
                                p.write_base32(writer)
                        },
                        Fallback::PubKeyHash(ref hash) => {
index 22e493ae1c570705da884a22b3c42a4e1ec02c0d..00b49c371eacabd7b65b5cb6a34e0e74979b8379 100644 (file)
@@ -9,7 +9,8 @@ use lightning::chain;
 use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
 use lightning::sign::{Recipient, NodeSigner, SignerProvider, EntropySource};
 use lightning::ln::types::{PaymentHash, PaymentSecret};
-use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, MIN_FINAL_CLTV_EXPIRY_DELTA};
+use lightning::ln::channel_state::ChannelDetails;
+use lightning::ln::channelmanager::{ChannelManager, MIN_FINAL_CLTV_EXPIRY_DELTA};
 use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
 use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
 use lightning::routing::gossip::RoutingFees;
@@ -1397,7 +1398,9 @@ mod test {
                let payment_preimage_opt = if user_generated_pmt_hash { None } else { Some(payment_preimage) };
                assert_eq!(other_events.borrow().len(), 1);
                check_payment_claimable(&other_events.borrow()[0], payment_hash, payment_secret, payment_amt, payment_preimage_opt, invoice.recover_payee_pub_key());
-               do_claim_payment_along_route(&nodes[0], &[&vec!(&nodes[fwd_idx])[..]], false, payment_preimage);
+               do_claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[fwd_idx]]], payment_preimage)
+               );
                expect_payment_sent(&nodes[0], payment_preimage, None, true, true);
        }
 
index e5e311fe669277b955ccf23e372478fd8386560b..6b5e99476b02427e254b931260f9b5ee9e9b9cd8 100644 (file)
@@ -4,8 +4,7 @@ extern crate lightning_invoice;
 extern crate secp256k1;
 extern crate hex;
 
-use bitcoin::address::WitnessVersion;
-use bitcoin::{PubkeyHash, ScriptHash};
+use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::hashes::{sha256, Hash};
 use lightning_invoice::*;
index 0ab9f82f527e4b79327576c173c4e8f6b6ab8c2c..c340fc8564054d168b41b769abeefb94eec2d96d 100644 (file)
@@ -15,7 +15,7 @@ all-features = true
 rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
-bitcoin = "0.30.2"
+bitcoin = "0.31.2"
 lightning = { version = "0.0.123-beta", path = "../lightning" }
 tokio = { version = "1.35", features = [ "rt", "sync", "net", "time" ] }
 
index 9f7aca47a785ebf8c4ceaeea4fc816342d4d175b..49f63614e83bf4242b67b6fd19b84b322829b021 100644 (file)
@@ -14,7 +14,7 @@ all-features = true
 rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
-bitcoin = "0.30.2"
+bitcoin = "0.31.2"
 lightning = { version = "0.0.123-beta", path = "../lightning" }
 
 [target.'cfg(windows)'.dependencies]
@@ -25,4 +25,4 @@ criterion = { version = "0.4", optional = true, default-features = false }
 
 [dev-dependencies]
 lightning = { version = "0.0.123-beta", path = "../lightning", features = ["_test_utils"] }
-bitcoin = { version = "0.30.2", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false }
index 8a144f6196b814104665572366f17c2b7ba02d72..093ab1ece07a619c3ba82386d253bb7fa41e4ac7 100644 (file)
@@ -445,7 +445,8 @@ mod tests {
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
 
@@ -482,7 +483,8 @@ mod tests {
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
                let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap();
index 360fa3492bff7196682e447f94ae52745e1e0678..42569c7a07959314b8c0a064e69d16da7e33ef01 100644 (file)
@@ -104,7 +104,8 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
 
        // Force close because cooperative close doesn't result in any persisted
        // updates.
-       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
        check_closed_broadcast!(nodes[0], true);
        check_added_monitors!(nodes[0], 1);
index 02ff3da57b5cc68d95cdf62cdbbd2b433b3754de..ad25e2f30849de487bf3ad6d8cfce27f68256bb5 100644 (file)
@@ -16,7 +16,7 @@ std = ["lightning/std"]
 
 [dependencies]
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false }
-bitcoin = { version = "0.30.2", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false }
 
 [target.'cfg(ldk_bench)'.dependencies]
 criterion = { version = "0.4", optional = true, default-features = false }
index 8bb4958f9fa22183276be848fecc1262812c32e4..23ead252a81ae5b1f8b58b90aed4c43a1a925674 100644 (file)
@@ -24,18 +24,18 @@ async-interface = []
 
 [dependencies]
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false, features = ["std"] }
-bitcoin = { version = "0.30.2", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false }
 bdk-macros = "0.6"
 futures = { version = "0.3", optional = true }
-esplora-client = { version = "0.6", default-features = false, optional = true }
-electrum-client = { version = "0.18.0", optional = true }
+esplora-client = { version = "0.7", default-features = false, optional = true }
+electrum-client = { version = "0.19.0", optional = true }
 
 [dev-dependencies]
 lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false, features = ["std", "_test_utils"] }
 tokio = { version = "1.35.0", features = ["full"] }
 
 [target.'cfg(all(not(target_os = "windows"), not(no_download)))'.dev-dependencies]
-electrsd = { version = "0.26.0", default-features = false, features = ["legacy", "esplora_a33e97e1", "bitcoind_25_0"] }
+electrsd = { version = "0.27.3", default-features = false, features = ["legacy", "esplora_a33e97e1", "bitcoind_25_0"] }
 
 [target.'cfg(all(not(target_os = "windows"), no_download))'.dev-dependencies]
-electrsd = { version = "0.26.0", default-features = false, features = ["legacy"] }
+electrsd = { version = "0.27.3", default-features = false, features = ["legacy"] }
index c635f7385c6ecbd47bb6b4e90f5abb335feca8f5..420d7d8a9575f8672ce3111a52d000270c141a4e 100644 (file)
@@ -1,10 +1,10 @@
-use lightning::chain::{Confirm, WatchedOutput};
-use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
-use bitcoin::{Txid, BlockHash, Transaction, OutPoint};
 use bitcoin::block::Header;
+use bitcoin::{BlockHash, OutPoint, Transaction, Txid};
+use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
+use lightning::chain::{Confirm, WatchedOutput};
 
-use std::collections::{HashSet, HashMap};
-
+use std::collections::{HashMap, HashSet};
+use std::ops::Deref;
 
 // Represents the current state.
 pub(crate) struct SyncState {
@@ -33,10 +33,11 @@ impl SyncState {
                        pending_sync: false,
                }
        }
-       pub fn sync_unconfirmed_transactions(
-               &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
-               unconfirmed_txs: Vec<Txid>,
-       ) {
+       pub fn sync_unconfirmed_transactions<C: Deref>(
+               &mut self, confirmables: &Vec<C>, unconfirmed_txs: Vec<Txid>,
+       ) where
+               C::Target: Confirm,
+       {
                for txid in unconfirmed_txs {
                        for c in confirmables {
                                c.transaction_unconfirmed(&txid);
@@ -46,21 +47,24 @@ impl SyncState {
 
                        // If a previously-confirmed output spend is unconfirmed, re-add the watched output to
                        // the tracking map.
-                       self.outputs_spends_pending_threshold_conf.retain(|(conf_txid, _, prev_outpoint, output)| {
-                               if txid == *conf_txid {
-                                       self.watched_outputs.insert(*prev_outpoint, output.clone());
-                                       false
-                               } else {
-                                       true
-                               }
-                       })
+                       self.outputs_spends_pending_threshold_conf.retain(
+                               |(conf_txid, _, prev_outpoint, output)| {
+                                       if txid == *conf_txid {
+                                               self.watched_outputs.insert(*prev_outpoint, output.clone());
+                                               false
+                                       } else {
+                                               true
+                                       }
+                               },
+                       )
                }
        }
 
-       pub fn sync_confirmed_transactions(
-               &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
-               confirmed_txs: Vec<ConfirmedTx>
-       ) {
+       pub fn sync_confirmed_transactions<C: Deref>(
+               &mut self, confirmables: &Vec<C>, confirmed_txs: Vec<ConfirmedTx>,
+       ) where
+               C::Target: Confirm,
+       {
                for ctx in confirmed_txs {
                        for c in confirmables {
                                c.transactions_confirmed(
@@ -74,20 +78,19 @@ impl SyncState {
 
                        for input in &ctx.tx.input {
                                if let Some(output) = self.watched_outputs.remove(&input.previous_output) {
-                                       self.outputs_spends_pending_threshold_conf.push((ctx.tx.txid(), ctx.block_height, input.previous_output, output));
+                                       let spent = (ctx.tx.txid(), ctx.block_height, input.previous_output, output);
+                                       self.outputs_spends_pending_threshold_conf.push(spent);
                                }
                        }
                }
        }
 
        pub fn prune_output_spends(&mut self, cur_height: u32) {
-               self.outputs_spends_pending_threshold_conf.retain(|(_, conf_height, _, _)| {
-                       cur_height < conf_height + ANTI_REORG_DELAY - 1
-               });
+               self.outputs_spends_pending_threshold_conf
+                       .retain(|(_, conf_height, _, _)| cur_height < conf_height + ANTI_REORG_DELAY - 1);
        }
 }
 
-
 // A queue that is to be filled by `Filter` and drained during the next syncing round.
 pub(crate) struct FilterQueue {
        // Transactions that were registered via the `Filter` interface and have to be processed.
@@ -98,10 +101,7 @@ pub(crate) struct FilterQueue {
 
 impl FilterQueue {
        pub fn new() -> Self {
-               Self {
-                       transactions: HashSet::new(),
-                       outputs: HashMap::new(),
-               }
+               Self { transactions: HashSet::new(), outputs: HashMap::new() }
        }
 
        // Processes the transaction and output queues and adds them to the given [`SyncState`].
index 046f698d4a259e3b0eace68790e59cfe1d406eb7..8ba250f8460b8de635ab3773aabcc31570459004 100644 (file)
@@ -1,24 +1,24 @@
-use crate::common::{ConfirmedTx, SyncState, FilterQueue};
-use crate::error::{TxSyncError, InternalError};
+use crate::common::{ConfirmedTx, FilterQueue, SyncState};
+use crate::error::{InternalError, TxSyncError};
 
 use electrum_client::Client as ElectrumClient;
 use electrum_client::ElectrumApi;
 use electrum_client::GetMerkleRes;
 
-use lightning::util::logger::Logger;
-use lightning::{log_error, log_debug, log_trace};
 use lightning::chain::WatchedOutput;
 use lightning::chain::{Confirm, Filter};
+use lightning::util::logger::Logger;
+use lightning::{log_debug, log_error, log_trace};
 
-use bitcoin::{BlockHash, Script, Transaction, Txid};
 use bitcoin::block::Header;
 use bitcoin::hash_types::TxMerkleNode;
-use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256d::Hash as Sha256d;
+use bitcoin::hashes::Hash;
+use bitcoin::{BlockHash, Script, Transaction, Txid};
 
+use std::collections::HashSet;
 use std::ops::Deref;
 use std::sync::Mutex;
-use std::collections::HashSet;
 use std::time::Instant;
 
 /// Synchronizes LDK with a given Electrum server.
@@ -58,16 +58,13 @@ where
        }
 
        /// Returns a new [`ElectrumSyncClient`] object using the given Electrum client.
+       ///
+       /// This is not exported to bindings users as the underlying client from BDK is not exported.
        pub fn from_client(client: ElectrumClient, logger: L) -> Result<Self, TxSyncError> {
                let sync_state = Mutex::new(SyncState::new());
                let queue = Mutex::new(FilterQueue::new());
 
-               Ok(Self {
-                       sync_state,
-                       queue,
-                       client,
-                       logger,
-               })
+               Ok(Self { sync_state, queue, client, logger })
        }
 
        /// Synchronizes the given `confirmables` via their [`Confirm`] interface implementations. This
@@ -81,7 +78,10 @@ where
        /// [`ChainMonitor`]: lightning::chain::chainmonitor::ChainMonitor
        /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
        /// [`Filter`]: lightning::chain::Filter
-       pub fn sync(&self, confirmables: Vec<&(dyn Confirm + Sync + Send)>) -> Result<(), TxSyncError> {
+       pub fn sync<C: Deref>(&self, confirmables: Vec<C>) -> Result<(), TxSyncError>
+       where
+               C::Target: Confirm,
+       {
                // This lock makes sure we're syncing once at a time.
                let mut sync_state = self.sync_state.lock().unwrap();
 
@@ -120,15 +120,15 @@ where
                                                                        num_unconfirmed += unconfirmed_txs.len();
                                                                        sync_state.sync_unconfirmed_transactions(
                                                                                &confirmables,
-                                                                               unconfirmed_txs
+                                                                               unconfirmed_txs,
                                                                        );
-                                                               }
+                                                               },
                                                                Ok(true) => {
                                                                        log_debug!(self.logger,
                                                                                "Encountered inconsistency during transaction sync, restarting.");
                                                                        sync_state.pending_sync = true;
                                                                        continue;
-                                                               }
+                                                               },
                                                                Err(err) => {
                                                                        // (Semi-)permanent failure, retry later.
                                                                        log_error!(self.logger,
@@ -138,7 +138,7 @@ where
                                                                        );
                                                                        sync_state.pending_sync = true;
                                                                        return Err(TxSyncError::from(err));
-                                                               }
+                                                               },
                                                        }
                                                },
                                                Err(err) => {
@@ -150,7 +150,7 @@ where
                                                        );
                                                        sync_state.pending_sync = true;
                                                        return Err(TxSyncError::from(err));
-                                               }
+                                               },
                                        }
 
                                        // Update the best block.
@@ -169,17 +169,15 @@ where
                                                match self.check_update_tip(&mut tip_header, &mut tip_height) {
                                                        Ok(false) => {
                                                                num_confirmed += confirmed_txs.len();
-                                                               sync_state.sync_confirmed_transactions(
-                                                                       &confirmables,
-                                                                       confirmed_txs
-                                                               );
-                                                       }
+                                                               sync_state
+                                                                       .sync_confirmed_transactions(&confirmables, confirmed_txs);
+                                                       },
                                                        Ok(true) => {
                                                                log_debug!(self.logger,
                                                                        "Encountered inconsistency during transaction sync, restarting.");
                                                                sync_state.pending_sync = true;
                                                                continue;
-                                                       }
+                                                       },
                                                        Err(err) => {
                                                                // (Semi-)permanent failure, retry later.
                                                                log_error!(self.logger,
@@ -189,16 +187,18 @@ where
                                                                );
                                                                sync_state.pending_sync = true;
                                                                return Err(TxSyncError::from(err));
-                                                       }
+                                                       },
                                                }
-                                       }
+                                       },
                                        Err(InternalError::Inconsistency) => {
                                                // Immediately restart syncing when we encounter any inconsistencies.
-                                               log_debug!(self.logger,
-                                                       "Encountered inconsistency during transaction sync, restarting.");
+                                               log_debug!(
+                                                       self.logger,
+                                                       "Encountered inconsistency during transaction sync, restarting."
+                                               );
                                                sync_state.pending_sync = true;
                                                continue;
-                                       }
+                                       },
                                        Err(err) => {
                                                // (Semi-)permanent failure, retry later.
                                                log_error!(self.logger,
@@ -208,27 +208,35 @@ where
                                                );
                                                sync_state.pending_sync = true;
                                                return Err(TxSyncError::from(err));
-                                       }
+                                       },
                                }
                                sync_state.last_sync_hash = Some(tip_header.block_hash());
                                sync_state.pending_sync = false;
                        }
                }
                #[cfg(feature = "time")]
-               log_debug!(self.logger,
+               log_debug!(
+                       self.logger,
                        "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.",
-                       tip_header.block_hash(), start_time.elapsed().as_millis(), num_confirmed,
-                       num_unconfirmed);
+                       tip_header.block_hash(),
+                       start_time.elapsed().as_millis(),
+                       num_confirmed,
+                       num_unconfirmed
+               );
                #[cfg(not(feature = "time"))]
-               log_debug!(self.logger,
+               log_debug!(
+                       self.logger,
                        "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.",
-                       tip_header.block_hash(), num_confirmed, num_unconfirmed);
+                       tip_header.block_hash(),
+                       num_confirmed,
+                       num_unconfirmed
+               );
                Ok(())
        }
 
-       fn check_update_tip(&self, cur_tip_header: &mut Header, cur_tip_height: &mut u32)
-               -> Result<bool, InternalError>
-       {
+       fn check_update_tip(
+               &self, cur_tip_header: &mut Header, cur_tip_height: &mut u32,
+       ) -> Result<bool, InternalError> {
                let check_notification = self.client.block_headers_subscribe()?;
                let check_tip_hash = check_notification.header.block_hash();
 
@@ -254,12 +262,12 @@ where
        fn get_confirmed_transactions(
                &self, sync_state: &SyncState,
        ) -> Result<Vec<ConfirmedTx>, InternalError> {
-
                // First, check the confirmation status of registered transactions as well as the
                // status of dependent transactions of registered outputs.
                let mut confirmed_txs: Vec<ConfirmedTx> = Vec::new();
                let mut watched_script_pubkeys = Vec::with_capacity(
-                       sync_state.watched_transactions.len() + sync_state.watched_outputs.len());
+                       sync_state.watched_transactions.len() + sync_state.watched_outputs.len(),
+               );
                let mut watched_txs = Vec::with_capacity(sync_state.watched_transactions.len());
 
                for txid in &sync_state.watched_transactions {
@@ -276,14 +284,14 @@ where
                                                log_error!(self.logger, "Failed due to retrieving invalid tx data.");
                                                return Err(InternalError::Failed);
                                        }
-                               }
+                               },
                                Err(electrum_client::Error::Protocol(_)) => {
                                        // We couldn't find the tx, do nothing.
-                               }
+                               },
                                Err(e) => {
                                        log_error!(self.logger, "Failed to look up transaction {}: {}.", txid, e);
                                        return Err(InternalError::Failed);
-                               }
+                               },
                        }
                }
 
@@ -308,9 +316,9 @@ where
                                        if confirmed_txs.iter().any(|ctx| ctx.txid == **txid) {
                                                continue;
                                        }
-                                       let mut filtered_history = script_history.iter().filter(|h| h.tx_hash == **txid);
-                                       if let Some(history) = filtered_history.next()
-                                       {
+                                       let mut filtered_history =
+                                               script_history.iter().filter(|h| h.tx_hash == **txid);
+                                       if let Some(history) = filtered_history.next() {
                                                let prob_conf_height = history.height as u32;
                                                let confirmed_tx = self.get_confirmed_tx(tx, prob_conf_height)?;
                                                confirmed_txs.push(confirmed_tx);
@@ -318,8 +326,8 @@ where
                                        debug_assert!(filtered_history.next().is_none());
                                }
 
-                               for (watched_output, script_history) in sync_state.watched_outputs.values()
-                                       .zip(output_results)
+                               for (watched_output, script_history) in
+                                       sync_state.watched_outputs.values().zip(output_results)
                                {
                                        for possible_output_spend in script_history {
                                                if possible_output_spend.height <= 0 {
@@ -335,8 +343,8 @@ where
                                                        Ok(tx) => {
                                                                let mut is_spend = false;
                                                                for txin in &tx.input {
-                                                                       let watched_outpoint = watched_output.outpoint
-                                                                               .into_bitcoin_outpoint();
+                                                                       let watched_outpoint =
+                                                                               watched_output.outpoint.into_bitcoin_outpoint();
                                                                        if txin.previous_output == watched_outpoint {
                                                                                is_spend = true;
                                                                                break;
@@ -350,21 +358,24 @@ where
                                                                let prob_conf_height = possible_output_spend.height as u32;
                                                                let confirmed_tx = self.get_confirmed_tx(&tx, prob_conf_height)?;
                                                                confirmed_txs.push(confirmed_tx);
-                                                       }
+                                                       },
                                                        Err(e) => {
-                                                               log_trace!(self.logger,
+                                                               log_trace!(
+                                                                       self.logger,
                                                                        "Inconsistency: Tx {} was unconfirmed during syncing: {}",
-                                                                       txid, e);
+                                                                       txid,
+                                                                       e
+                                                               );
                                                                return Err(InternalError::Inconsistency);
-                                                       }
+                                                       },
                                                }
                                        }
                                }
-                       }
+                       },
                        Err(e) => {
                                log_error!(self.logger, "Failed to look up script histories: {}.", e);
                                return Err(InternalError::Failed);
-                       }
+                       },
                }
 
                // Sort all confirmed transactions first by block height, then by in-block
@@ -376,9 +387,12 @@ where
                Ok(confirmed_txs)
        }
 
-       fn get_unconfirmed_transactions(
-               &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
-       ) -> Result<Vec<Txid>, InternalError> {
+       fn get_unconfirmed_transactions<C: Deref>(
+               &self, confirmables: &Vec<C>,
+       ) -> Result<Vec<Txid>, InternalError>
+       where
+               C::Target: Confirm,
+       {
                // Query the interface for relevant txids and check whether the relevant blocks are still
                // in the best chain, mark them unconfirmed otherwise
                let relevant_txids = confirmables
@@ -406,9 +420,9 @@ where
                Ok(unconfirmed_txs)
        }
 
-       fn get_confirmed_tx(&self, tx: &Transaction, prob_conf_height: u32)
-               -> Result<ConfirmedTx, InternalError>
-       {
+       fn get_confirmed_tx(
+               &self, tx: &Transaction, prob_conf_height: u32,
+       ) -> Result<ConfirmedTx, InternalError> {
                let txid = tx.txid();
                match self.client.transaction_get_merkle(&txid, prob_conf_height as usize) {
                        Ok(merkle_res) => {
@@ -416,58 +430,67 @@ where
                                match self.client.block_header(prob_conf_height as usize) {
                                        Ok(block_header) => {
                                                let pos = merkle_res.pos;
-                                               if !self.validate_merkle_proof(&txid,
-                                                       &block_header.merkle_root, merkle_res)?
-                                               {
-                                                       log_trace!(self.logger,
+                                               if !self.validate_merkle_proof(
+                                                       &txid,
+                                                       &block_header.merkle_root,
+                                                       merkle_res,
+                                               )? {
+                                                       log_trace!(
+                                                               self.logger,
                                                                "Inconsistency: Block {} was unconfirmed during syncing.",
-                                                               block_header.block_hash());
+                                                               block_header.block_hash()
+                                                       );
                                                        return Err(InternalError::Inconsistency);
                                                }
                                                let confirmed_tx = ConfirmedTx {
                                                        tx: tx.clone(),
                                                        txid,
-                                                       block_header, block_height: prob_conf_height,
+                                                       block_header,
+                                                       block_height: prob_conf_height,
                                                        pos,
                                                };
                                                Ok(confirmed_tx)
-                                       }
+                                       },
                                        Err(e) => {
-                                               log_error!(self.logger,
+                                               log_error!(
+                                                       self.logger,
                                                        "Failed to retrieve block header for height {}: {}.",
-                                                       prob_conf_height, e);
+                                                       prob_conf_height,
+                                                       e
+                                               );
                                                Err(InternalError::Failed)
-                                       }
+                                       },
                                }
-                       }
+                       },
                        Err(e) => {
-                               log_trace!(self.logger,
+                               log_trace!(
+                                       self.logger,
                                        "Inconsistency: Tx {} was unconfirmed during syncing: {}",
-                                       txid, e);
+                                       txid,
+                                       e
+                               );
                                Err(InternalError::Inconsistency)
-                       }
+                       },
                }
        }
 
        /// Returns a reference to the underlying Electrum client.
+       ///
+       /// This is not exported to bindings users as the underlying client from BDK is not exported.
        pub fn client(&self) -> &ElectrumClient {
                &self.client
        }
 
-       fn validate_merkle_proof(&self, txid: &Txid, merkle_root: &TxMerkleNode,
-               merkle_res: GetMerkleRes) -> Result<bool, InternalError>
-       {
+       fn validate_merkle_proof(
+               &self, txid: &Txid, merkle_root: &TxMerkleNode, merkle_res: GetMerkleRes,
+       ) -> Result<bool, InternalError> {
                let mut index = merkle_res.pos;
                let mut cur = txid.to_raw_hash();
                for mut bytes in merkle_res.merkle {
                        bytes.reverse();
                        // unwrap() safety: `bytes` has len 32 so `from_slice` can never fail.
                        let next_hash = Sha256d::from_slice(&bytes).unwrap();
-                       let (left, right) = if index % 2 == 0 {
-                               (cur, next_hash)
-                       } else {
-                               (next_hash, cur)
-                       };
+                       let (left, right) = if index % 2 == 0 { (cur, next_hash) } else { (next_hash, cur) };
 
                        let data = [&left[..], &right[..]].concat();
                        cur = Sha256d::hash(&data);
index d1f4a319e8686c86218e93ea80303dfb90c6957c..be59cb026b4cd1b760b06ecd95a26e2d48c8a340 100644 (file)
@@ -31,7 +31,7 @@ impl fmt::Display for InternalError {
                        Self::Failed => write!(f, "Failed to conduct transaction sync."),
                        Self::Inconsistency => {
                                write!(f, "Encountered an inconsistency during transaction sync.")
-                       }
+                       },
                }
        }
 }
index 538918ada953f74e8170864be1a20f7a6e3bf7ad..f176d535124e67681cfabe7575e7eccad5edd0f4 100644 (file)
@@ -1,21 +1,21 @@
-use crate::error::{TxSyncError, InternalError};
-use crate::common::{SyncState, FilterQueue, ConfirmedTx};
+use crate::common::{ConfirmedTx, FilterQueue, SyncState};
+use crate::error::{InternalError, TxSyncError};
 
-use lightning::util::logger::Logger;
-use lightning::{log_error, log_debug, log_trace};
 use lightning::chain::WatchedOutput;
 use lightning::chain::{Confirm, Filter};
+use lightning::util::logger::Logger;
+use lightning::{log_debug, log_error, log_trace};
 
 use bitcoin::{BlockHash, Script, Txid};
 
-use esplora_client::Builder;
-#[cfg(feature = "async-interface")]
-use esplora_client::r#async::AsyncClient;
 #[cfg(not(feature = "async-interface"))]
 use esplora_client::blocking::BlockingClient;
+#[cfg(feature = "async-interface")]
+use esplora_client::r#async::AsyncClient;
+use esplora_client::Builder;
 
-use std::collections::HashSet;
 use core::ops::Deref;
+use std::collections::HashSet;
 
 /// Synchronizes LDK with a given [`Esplora`] server.
 ///
@@ -51,7 +51,7 @@ where
        pub fn new(server_url: String, logger: L) -> Self {
                let builder = Builder::new(&server_url);
                #[cfg(not(feature = "async-interface"))]
-               let client = builder.build_blocking().unwrap();
+               let client = builder.build_blocking();
                #[cfg(feature = "async-interface")]
                let client = builder.build_async().unwrap();
 
@@ -59,15 +59,12 @@ where
        }
 
        /// Returns a new [`EsploraSyncClient`] object using the given Esplora client.
+       ///
+       /// This is not exported to bindings users as the underlying client from BDK is not exported.
        pub fn from_client(client: EsploraClientType, logger: L) -> Self {
                let sync_state = MutexType::new(SyncState::new());
                let queue = std::sync::Mutex::new(FilterQueue::new());
-               Self {
-                       sync_state,
-                       queue,
-                       client,
-                       logger,
-               }
+               Self { sync_state, queue, client, logger }
        }
 
        /// Synchronizes the given `confirmables` via their [`Confirm`] interface implementations. This
@@ -82,7 +79,10 @@ where
        /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
        /// [`Filter`]: lightning::chain::Filter
        #[maybe_async]
-       pub fn sync(&self, confirmables: Vec<&(dyn Confirm + Sync + Send)>) -> Result<(), TxSyncError> {
+       pub fn sync<C: Deref>(&self, confirmables: Vec<C>) -> Result<(), TxSyncError>
+       where
+               C::Target: Confirm,
+       {
                // This lock makes sure we're syncing once at a time.
                #[cfg(not(feature = "async-interface"))]
                let mut sync_state = self.sync_state.lock().unwrap();
@@ -126,9 +126,9 @@ where
                                                                        num_unconfirmed += unconfirmed_txs.len();
                                                                        sync_state.sync_unconfirmed_transactions(
                                                                                &confirmables,
-                                                                               unconfirmed_txs
+                                                                               unconfirmed_txs,
                                                                        );
-                                                               }
+                                                               },
                                                                Err(err) => {
                                                                        // (Semi-)permanent failure, retry later.
                                                                        log_error!(self.logger,
@@ -138,7 +138,7 @@ where
                                                                                );
                                                                        sync_state.pending_sync = true;
                                                                        return Err(TxSyncError::from(err));
-                                                               }
+                                                               },
                                                        }
                                                },
                                                Err(err) => {
@@ -150,17 +150,24 @@ where
                                                        );
                                                        sync_state.pending_sync = true;
                                                        return Err(TxSyncError::from(err));
-                                               }
+                                               },
                                        }
 
-                                       match maybe_await!(self.sync_best_block_updated(&confirmables, &mut sync_state, &tip_hash)) {
-                                               Ok(()) => {}
+                                       match maybe_await!(self.sync_best_block_updated(
+                                               &confirmables,
+                                               &mut sync_state,
+                                               &tip_hash
+                                       )) {
+                                               Ok(()) => {},
                                                Err(InternalError::Inconsistency) => {
                                                        // Immediately restart syncing when we encounter any inconsistencies.
-                                                       log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting.");
+                                                       log_debug!(
+                                                               self.logger,
+                                                               "Encountered inconsistency during transaction sync, restarting."
+                                                       );
                                                        sync_state.pending_sync = true;
                                                        continue;
-                                               }
+                                               },
                                                Err(err) => {
                                                        // (Semi-)permanent failure, retry later.
                                                        log_error!(self.logger,
@@ -170,7 +177,7 @@ where
                                                        );
                                                        sync_state.pending_sync = true;
                                                        return Err(TxSyncError::from(err));
-                                               }
+                                               },
                                        }
                                }
 
@@ -189,11 +196,9 @@ where
                                                                        continue;
                                                                }
                                                                num_confirmed += confirmed_txs.len();
-                                                               sync_state.sync_confirmed_transactions(
-                                                                       &confirmables,
-                                                                       confirmed_txs
-                                                               );
-                                                       }
+                                                               sync_state
+                                                                       .sync_confirmed_transactions(&confirmables, confirmed_txs);
+                                                       },
                                                        Err(err) => {
                                                                // (Semi-)permanent failure, retry later.
                                                                log_error!(self.logger,
@@ -203,15 +208,18 @@ where
                                                                );
                                                                sync_state.pending_sync = true;
                                                                return Err(TxSyncError::from(err));
-                                                       }
+                                                       },
                                                }
-                                       }
+                                       },
                                        Err(InternalError::Inconsistency) => {
                                                // Immediately restart syncing when we encounter any inconsistencies.
-                                               log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting.");
+                                               log_debug!(
+                                                       self.logger,
+                                                       "Encountered inconsistency during transaction sync, restarting."
+                                               );
                                                sync_state.pending_sync = true;
                                                continue;
-                                       }
+                                       },
                                        Err(err) => {
                                                // (Semi-)permanent failure, retry later.
                                                log_error!(self.logger,
@@ -221,26 +229,39 @@ where
                                                );
                                                sync_state.pending_sync = true;
                                                return Err(TxSyncError::from(err));
-                                       }
+                                       },
                                }
                                sync_state.last_sync_hash = Some(tip_hash);
                                sync_state.pending_sync = false;
                        }
                }
                #[cfg(feature = "time")]
-               log_debug!(self.logger, "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.",
-                               tip_hash, start_time.elapsed().as_millis(), num_confirmed, num_unconfirmed);
+               log_debug!(
+                       self.logger,
+                       "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.",
+                       tip_hash,
+                       start_time.elapsed().as_millis(),
+                       num_confirmed,
+                       num_unconfirmed
+               );
                #[cfg(not(feature = "time"))]
-               log_debug!(self.logger, "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.",
-                               tip_hash, num_confirmed, num_unconfirmed);
+               log_debug!(
+                       self.logger,
+                       "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.",
+                       tip_hash,
+                       num_confirmed,
+                       num_unconfirmed
+               );
                Ok(())
        }
 
        #[maybe_async]
-       fn sync_best_block_updated(
-               &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, sync_state: &mut SyncState, tip_hash: &BlockHash,
-       ) -> Result<(), InternalError> {
-
+       fn sync_best_block_updated<C: Deref>(
+               &self, confirmables: &Vec<C>, sync_state: &mut SyncState, tip_hash: &BlockHash,
+       ) -> Result<(), InternalError>
+       where
+               C::Target: Confirm,
+       {
                // Inform the interface of the new block.
                let tip_header = maybe_await!(self.client.get_header_by_hash(tip_hash))?;
                let tip_status = maybe_await!(self.client.get_block_status(&tip_hash))?;
@@ -263,7 +284,6 @@ where
        fn get_confirmed_transactions(
                &self, sync_state: &SyncState,
        ) -> Result<Vec<ConfirmedTx>, InternalError> {
-
                // First, check the confirmation status of registered transactions as well as the
                // status of dependent transactions of registered outputs.
 
@@ -279,7 +299,8 @@ where
                }
 
                for (_, output) in &sync_state.watched_outputs {
-                       if let Some(output_status) = maybe_await!(self.client
+                       if let Some(output_status) = maybe_await!(self
+                               .client
                                .get_output_status(&output.outpoint.txid, output.outpoint.index as u64))?
                        {
                                if let Some(spending_txid) = output_status.txid {
@@ -294,13 +315,11 @@ where
                                                        }
                                                }
 
-                                               if let Some(confirmed_tx) = maybe_await!(self
-                                                       .get_confirmed_tx(
-                                                               spending_txid,
-                                                               spending_tx_status.block_hash,
-                                                               spending_tx_status.block_height,
-                                                       ))?
-                                               {
+                                               if let Some(confirmed_tx) = maybe_await!(self.get_confirmed_tx(
+                                                       spending_txid,
+                                                       spending_tx_status.block_hash,
+                                                       spending_tx_status.block_height,
+                                               ))? {
                                                        confirmed_txs.push(confirmed_tx);
                                                }
                                        }
@@ -326,7 +345,13 @@ where
                        let block_hash = block_header.block_hash();
                        if let Some(expected_block_hash) = expected_block_hash {
                                if expected_block_hash != block_hash {
-                                       log_trace!(self.logger, "Inconsistency: Tx {} expected in block {}, but is confirmed in {}", txid, expected_block_hash, block_hash);
+                                       log_trace!(
+                                               self.logger,
+                                               "Inconsistency: Tx {} expected in block {}, but is confirmed in {}",
+                                               txid,
+                                               expected_block_hash,
+                                               block_hash
+                                       );
                                        return Err(InternalError::Inconsistency);
                                }
                        }
@@ -358,7 +383,11 @@ where
                                } else {
                                        // If any previously-confirmed block suddenly is no longer confirmed, we found
                                        // an inconsistency and should start over.
-                                       log_trace!(self.logger, "Inconsistency: Tx {} was unconfirmed during syncing.", txid);
+                                       log_trace!(
+                                               self.logger,
+                                               "Inconsistency: Tx {} was unconfirmed during syncing.",
+                                               txid
+                                       );
                                        return Err(InternalError::Inconsistency);
                                }
                        }
@@ -367,9 +396,12 @@ where
        }
 
        #[maybe_async]
-       fn get_unconfirmed_transactions(
-               &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
-       ) -> Result<Vec<Txid>, InternalError> {
+       fn get_unconfirmed_transactions<C: Deref>(
+               &self, confirmables: &Vec<C>,
+       ) -> Result<Vec<Txid>, InternalError>
+       where
+               C::Target: Confirm,
+       {
                // Query the interface for relevant txids and check whether the relevant blocks are still
                // in the best chain, mark them unconfirmed otherwise
                let relevant_txids = confirmables
@@ -397,6 +429,8 @@ where
        }
 
        /// Returns a reference to the underlying esplora client.
+       ///
+       /// This is not exported to bindings users as the underlying client from BDK is not exported.
        pub fn client(&self) -> &EsploraClientType {
                &self.client
        }
@@ -413,7 +447,6 @@ type EsploraClientType = AsyncClient;
 #[cfg(not(feature = "async-interface"))]
 type EsploraClientType = BlockingClient;
 
-
 impl<L: Deref> Filter for EsploraSyncClient<L>
 where
        L::Target: Logger,
index 7bd4b4aee3f0784d5ad5aa92c7638e49b08790aa..96e0c0dfe9c4875136e13670548a9dbd9745a7a6 100644 (file)
 
 #![deny(rustdoc::broken_intra_doc_links)]
 #![deny(rustdoc::private_intra_doc_links)]
-
 #![deny(missing_docs)]
 #![deny(unsafe_code)]
-
 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
 
 #[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
@@ -83,7 +81,7 @@ mod error;
 #[cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum"))]
 pub use error::TxSyncError;
 
-#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
-pub use esplora::EsploraSyncClient;
 #[cfg(feature = "electrum")]
 pub use electrum::ElectrumSyncClient;
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+pub use esplora::EsploraSyncClient;
index 48044b236bf8c1e6360334d40b6c729dca468a03..b30594a717d9802cdabe766a2e9f3faa8bc3ae4c 100644 (file)
@@ -1,26 +1,29 @@
-#![cfg(all(not(target_os = "windows"), any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum")))]
+#![cfg(all(
+       not(target_os = "windows"),
+       any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum")
+))]
 
-#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
-use lightning_transaction_sync::EsploraSyncClient;
-#[cfg(feature = "electrum")]
-use lightning_transaction_sync::ElectrumSyncClient;
-use lightning::chain::{Confirm, Filter, WatchedOutput};
 use lightning::chain::transaction::{OutPoint, TransactionData};
+use lightning::chain::{Confirm, Filter, WatchedOutput};
 use lightning::util::test_utils::TestLogger;
+#[cfg(feature = "electrum")]
+use lightning_transaction_sync::ElectrumSyncClient;
+#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
+use lightning_transaction_sync::EsploraSyncClient;
 
-use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
-use bitcoin::{Amount, Txid, BlockHash};
+use bdk_macros::maybe_await;
 use bitcoin::blockdata::block::Header;
 use bitcoin::blockdata::constants::genesis_block;
-use bitcoin::network::constants::Network;
-use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
+use bitcoin::network::Network;
+use bitcoin::{Amount, BlockHash, Txid};
 use bitcoind::bitcoincore_rpc::RpcApi;
-use bdk_macros::maybe_await;
+use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
+use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
 
+use std::collections::{HashMap, HashSet};
 use std::env;
 use std::sync::Mutex;
 use std::time::Duration;
-use std::collections::{HashMap, HashSet};
 
 pub fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
        let bitcoind_exe =
@@ -63,8 +66,11 @@ pub fn wait_for_block(electrsd: &ElectrsD, min_height: usize) {
                        // it didn't. Since we can't proceed without subscribing, we try again after a delay
                        // and panic if it still fails.
                        std::thread::sleep(Duration::from_secs(1));
-                       electrsd.client.block_headers_subscribe_raw().expect("failed to subscribe to block headers")
-               }
+                       electrsd
+                               .client
+                               .block_headers_subscribe_raw()
+                               .expect("failed to subscribe to block headers")
+               },
        };
        loop {
                if header.height >= min_height {
@@ -90,7 +96,7 @@ where
                        None if delay.as_millis() < 512 => {
                                delay = delay.mul_f32(2.0);
                                tries += 1;
-                       }
+                       },
                        None if tries == 10 => panic!("Exceeded our maximum wait time."),
                        None => tries += 1,
                }
@@ -132,7 +138,8 @@ impl Confirm for TestConfirmable {
                        let block_hash = header.block_hash();
                        self.confirmed_txs.lock().unwrap().insert(txid, (block_hash, height));
                        self.unconfirmed_txs.lock().unwrap().remove(&txid);
-                       self.events.lock().unwrap().push(TestConfirmableEvent::Confirmed(txid, block_hash, height));
+                       let event = TestConfirmableEvent::Confirmed(txid, block_hash, height);
+                       self.events.lock().unwrap().push(event);
                }
        }
 
@@ -145,11 +152,13 @@ impl Confirm for TestConfirmable {
        fn best_block_updated(&self, header: &Header, height: u32) {
                let block_hash = header.block_hash();
                *self.best_block.lock().unwrap() = (block_hash, height);
-               self.events.lock().unwrap().push(TestConfirmableEvent::BestBlockUpdated(block_hash, height));
+               let event = TestConfirmableEvent::BestBlockUpdated(block_hash, height);
+               self.events.lock().unwrap().push(event);
        }
 
        fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
-               self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect::<Vec<_>>()
+               let lock = self.confirmed_txs.lock().unwrap();
+               lock.iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect()
        }
 }
 
@@ -165,13 +174,38 @@ macro_rules! test_syncing {
                assert_eq!(events.len(), 1);
 
                // Check registered confirmed transactions are marked confirmed
-               let new_address = $bitcoind.client.get_new_address(Some("test"),
-               Some(AddressType::Legacy)).unwrap().assume_checked();
-               let txid = $bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, None,
-               None, None, None, None).unwrap();
-               let second_txid = $bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None,
-               None, None, None, None, None).unwrap();
-               $tx_sync.register_tx(&txid, &new_address.payload.script_pubkey());
+               let new_address = $bitcoind
+                       .client
+                       .get_new_address(Some("test"), Some(AddressType::Legacy))
+                       .unwrap()
+                       .assume_checked();
+               let txid = $bitcoind
+                       .client
+                       .send_to_address(
+                               &new_address,
+                               Amount::from_sat(5000),
+                               None,
+                               None,
+                               None,
+                               None,
+                               None,
+                               None,
+                       )
+                       .unwrap();
+               let second_txid = $bitcoind
+                       .client
+                       .send_to_address(
+                               &new_address,
+                               Amount::from_sat(5000),
+                               None,
+                               None,
+                               None,
+                               None,
+                               None,
+                               None,
+                       )
+                       .unwrap();
+               $tx_sync.register_tx(&txid, &new_address.payload().script_pubkey());
 
                maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap();
 
@@ -193,13 +227,17 @@ macro_rules! test_syncing {
                let block_hash = tx_res.info.blockhash.unwrap();
                let tx = tx_res.transaction().unwrap();
                let prev_outpoint = tx.input.first().unwrap().previous_output;
-               let prev_tx = $bitcoind.client.get_transaction(&prev_outpoint.txid, None).unwrap().transaction()
+               let prev_tx = $bitcoind
+                       .client
+                       .get_transaction(&prev_outpoint.txid, None)
+                       .unwrap()
+                       .transaction()
                        .unwrap();
                let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone();
                let output = WatchedOutput {
                        block_hash: Some(block_hash),
                        outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 },
-                       script_pubkey: prev_script_pubkey
+                       script_pubkey: prev_script_pubkey,
                };
 
                $tx_sync.register_output(output);
index 274b4755d50d0fc5671255b0651c52215deae685..8f238f5b5573f6e9269b6950df784255cfc4cc7a 100644 (file)
@@ -32,7 +32,7 @@ unsafe_revoked_tx_signing = []
 _test_vectors = []
 
 no-std = ["hashbrown", "possiblyrandom", "bitcoin/no-std", "core2/alloc", "libm"]
-std = ["bitcoin/std"]
+std = ["bitcoin/std", "bech32/std"]
 
 # Generates low-r bitcoin signatures, which saves 1 byte in 50% of the cases
 grind_signatures = []
@@ -40,7 +40,8 @@ grind_signatures = []
 default = ["std", "grind_signatures"]
 
 [dependencies]
-bitcoin = { version = "0.30.2", default-features = false, features = ["secp-recovery"] }
+bech32 = { version = "0.9.1", default-features = false }
+bitcoin = { version = "0.31.2", default-features = false, features = ["secp-recovery"] }
 
 hashbrown = { version = "0.13", optional = true, default-features = false }
 possiblyrandom = { version = "0.2", optional = true, default-features = false }
@@ -55,7 +56,7 @@ libm = { version = "0.2", optional = true, default-features = false }
 regex = "1.5.6"
 
 [dev-dependencies.bitcoin]
-version = "0.30.2"
+version = "0.31.2"
 default-features = false
 features = ["bitcoinconsensus", "secp-recovery"]
 
@@ -63,4 +64,4 @@ features = ["bitcoinconsensus", "secp-recovery"]
 criterion = { version = "0.4", optional = true, default-features = false }
 
 [target.'cfg(taproot)'.dependencies]
-musig2 = { git = "https://github.com/arik-so/rust-musig2", rev = "cff11e3" }
+musig2 = { git = "https://github.com/arik-so/rust-musig2", rev = "739533fc" }
index 5e44c792d33b9c49df82c2d9840e462ad45cb9f6..3b71f77c6d5f8488593468fa8f57fcba33af8f30 100644 (file)
@@ -17,7 +17,7 @@ use crate::blinded_path::BlindedHop;
 use crate::blinded_path::utils;
 use crate::io;
 use crate::ln::types::PaymentSecret;
-use crate::ln::channelmanager::CounterpartyForwardingInfo;
+use crate::ln::channel_state::CounterpartyForwardingInfo;
 use crate::ln::features::BlindedHopFeatures;
 use crate::ln::msgs::DecodeError;
 use crate::offers::invoice::BlindedPayInfo;
index 04f72d4ce3bfa9c074551988b4a386fff66be0f6..58bf5f8002d27cc7ab092fc8cc288a8e52377acf 100644 (file)
@@ -38,7 +38,7 @@ use crate::events::{Event, EventHandler};
 use crate::util::logger::{Logger, WithContext};
 use crate::util::errors::APIError;
 use crate::util::wakers::{Future, Notifier};
-use crate::ln::channelmanager::ChannelDetails;
+use crate::ln::channel_state::ChannelDetails;
 
 use crate::prelude::*;
 use crate::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard};
index 3ca15e48337f3bb2da922814be39f0acde240818..6291006fc9cb1c6a6fc99a96f7f6561e355d8ab4 100644 (file)
@@ -20,6 +20,7 @@
 //! security-domain-separated system design, you should consider having multiple paths for
 //! ChannelMonitors to get out of the HSM and onto monitoring devices.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::block::Header;
 use bitcoin::blockdata::transaction::{OutPoint as BitcoinOutPoint, TxOut, Transaction};
 use bitcoin::blockdata::script::{Script, ScriptBuf};
@@ -28,10 +29,10 @@ use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hash_types::{Txid, BlockHash};
 
+use bitcoin::ecdsa::Signature as BitcoinSignature;
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1::{SecretKey, PublicKey};
 use bitcoin::secp256k1;
-use bitcoin::sighash::EcdsaSighashType;
 
 use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
 use crate::ln::types::{PaymentHash, PaymentPreimage, ChannelId};
@@ -411,7 +412,7 @@ impl OnchainEventEntry {
 /// The (output index, sats value) for the counterparty's output in a commitment transaction.
 ///
 /// This was added as an `Option` in 0.0.110.
-type CommitmentTxCounterpartyOutputInfo = Option<(u32, u64)>;
+type CommitmentTxCounterpartyOutputInfo = Option<(u32, Amount)>;
 
 /// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
 /// once they mature to enough confirmations (ANTI_REORG_DELAY)
@@ -2171,7 +2172,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
                                                } else { None }
                                        }) {
                                                res.push(Balance::ClaimableAwaitingConfirmations {
-                                                       amount_satoshis: value,
+                                                       amount_satoshis: value.to_sat(),
                                                        confirmation_height: conf_thresh,
                                                });
                                        } else {
@@ -2194,7 +2195,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
                                                        descriptor: SpendableOutputDescriptor::StaticOutput { output, .. }
                                                } = &event.event {
                                                        res.push(Balance::ClaimableAwaitingConfirmations {
-                                                               amount_satoshis: output.value,
+                                                               amount_satoshis: output.value.to_sat(),
                                                                confirmation_height: event.confirmation_threshold(),
                                                        });
                                                        if let Some(confirmed_to_self_idx) = confirmed_counterparty_output.map(|(idx, _)| idx) {
@@ -2213,7 +2214,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
                                                        .is_output_spend_pending(&BitcoinOutPoint::new(txid, confirmed_to_self_idx));
                                                if output_spendable {
                                                        res.push(Balance::CounterpartyRevokedOutputClaimable {
-                                                               amount_satoshis: amt,
+                                                               amount_satoshis: amt.to_sat(),
                                                        });
                                                }
                                        } else {
@@ -2430,8 +2431,8 @@ macro_rules! fail_unbroadcast_htlcs {
                debug_assert_eq!($commitment_tx_confirmed.txid(), $commitment_txid_confirmed);
 
                macro_rules! check_htlc_fails {
-                       ($txid: expr, $commitment_tx: expr) => {
-                               if let Some(ref latest_outpoints) = $self.counterparty_claimable_outpoints.get($txid) {
+                       ($txid: expr, $commitment_tx: expr, $per_commitment_outpoints: expr) => {
+                               if let Some(ref latest_outpoints) = $per_commitment_outpoints {
                                        for &(ref htlc, ref source_option) in latest_outpoints.iter() {
                                                if let &Some(ref source) = source_option {
                                                        // Check if the HTLC is present in the commitment transaction that was
@@ -2491,10 +2492,10 @@ macro_rules! fail_unbroadcast_htlcs {
                        }
                }
                if let Some(ref txid) = $self.current_counterparty_commitment_txid {
-                       check_htlc_fails!(txid, "current");
+                       check_htlc_fails!(txid, "current", $self.counterparty_claimable_outpoints.get(txid));
                }
                if let Some(ref txid) = $self.prev_counterparty_commitment_txid {
-                       check_htlc_fails!(txid, "previous");
+                       check_htlc_fails!(txid, "previous", $self.counterparty_claimable_outpoints.get(txid));
                }
        } }
 }
@@ -2763,15 +2764,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                // If the channel is force closed, try to claim the output from this preimage.
                // First check if a counterparty commitment transaction has been broadcasted:
                macro_rules! claim_htlcs {
-                       ($commitment_number: expr, $txid: expr) => {
-                               let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None);
+                       ($commitment_number: expr, $txid: expr, $htlcs: expr) => {
+                               let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None, $htlcs);
                                self.onchain_tx_handler.update_claims_view_from_requests(htlc_claim_reqs, self.best_block.height, self.best_block.height, broadcaster, fee_estimator, logger);
                        }
                }
                if let Some(txid) = self.current_counterparty_commitment_txid {
                        if txid == confirmed_spend_txid {
                                if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
-                                       claim_htlcs!(*commitment_number, txid);
+                                       claim_htlcs!(*commitment_number, txid, self.counterparty_claimable_outpoints.get(&txid));
                                } else {
                                        debug_assert!(false);
                                        log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number");
@@ -2782,7 +2783,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                if let Some(txid) = self.prev_counterparty_commitment_txid {
                        if txid == confirmed_spend_txid {
                                if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
-                                       claim_htlcs!(*commitment_number, txid);
+                                       claim_htlcs!(*commitment_number, txid, self.counterparty_claimable_outpoints.get(&txid));
                                } else {
                                        debug_assert!(false);
                                        log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number");
@@ -3064,7 +3065,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                        debug_assert_eq!(self.current_holder_commitment_tx.txid, commitment_txid);
                                        let pending_htlcs = self.current_holder_commitment_tx.non_dust_htlcs();
                                        let commitment_tx_fee_satoshis = self.channel_value_satoshis -
-                                               commitment_tx.output.iter().fold(0u64, |sum, output| sum + output.value);
+                                               commitment_tx.output.iter().fold(0u64, |sum, output| sum + output.value.to_sat());
                                        ret.push(Event::BumpTransaction(BumpTransactionEvent::ChannelClose {
                                                channel_id,
                                                counterparty_node_id,
@@ -3104,9 +3105,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                        },
                                                        commitment_txid: htlc.commitment_txid,
                                                        per_commitment_number: htlc.per_commitment_number,
-                                                       per_commitment_point: self.onchain_tx_handler.signer.get_per_commitment_point(
-                                                               htlc.per_commitment_number, &self.onchain_tx_handler.secp_ctx,
-                                                       ),
+                                                       per_commitment_point: htlc.per_commitment_point,
                                                        feerate_per_kw: 0,
                                                        htlc: htlc.htlc,
                                                        preimage: htlc.preimage,
@@ -3204,7 +3203,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
 
                let sig = self.onchain_tx_handler.signer.sign_justice_revoked_output(
                        &justice_tx, input_idx, value, &per_commitment_key, &self.onchain_tx_handler.secp_ctx)?;
-               justice_tx.input[input_idx].witness.push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All);
+               justice_tx.input[input_idx].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(sig));
                justice_tx.input[input_idx].witness.push(&[1u8]);
                justice_tx.input[input_idx].witness.push(revokeable_redeemscript.as_bytes());
                Ok(justice_tx)
@@ -3232,16 +3231,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
        /// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
        /// HTLC-Success/HTLC-Timeout transactions.
        ///
-       /// Returns packages to claim the revoked output(s), as well as additional outputs to watch and
-       /// general information about the output that is to the counterparty in the commitment
-       /// transaction.
+       /// Returns packages to claim the revoked output(s) and general information about the output that
+       /// is to the counterparty in the commitment transaction.
        fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L)
-               -> (Vec<PackageTemplate>, TransactionOutputs, CommitmentTxCounterpartyOutputInfo)
+               -> (Vec<PackageTemplate>, CommitmentTxCounterpartyOutputInfo)
        where L::Target: Logger {
                // Most secp and related errors trying to create keys means we have no hope of constructing
                // a spend transaction...so we return no transactions to broadcast
                let mut claimable_outpoints = Vec::new();
-               let mut watch_outputs = Vec::new();
                let mut to_counterparty_output_info = None;
 
                let commitment_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers!
@@ -3251,7 +3248,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        ( $thing : expr ) => {
                                match $thing {
                                        Ok(a) => a,
-                                       Err(_) => return (claimable_outpoints, (commitment_txid, watch_outputs), to_counterparty_output_info)
+                                       Err(_) => return (claimable_outpoints, to_counterparty_output_info)
                                }
                        };
                }
@@ -3265,7 +3262,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key));
 
                        let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
-                       let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
+                       let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh();
 
                        // First, process non-htlc outputs (to_holder & to_counterparty)
                        for (idx, outp) in tx.output.iter().enumerate() {
@@ -3279,14 +3276,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        }
 
                        // Then, try to find revoked htlc outputs
-                       if let Some(ref per_commitment_data) = per_commitment_option {
-                               for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
+                       if let Some(per_commitment_claimable_data) = per_commitment_option {
+                               for (htlc, _) in per_commitment_claimable_data {
                                        if let Some(transaction_output_index) = htlc.transaction_output_index {
                                                if transaction_output_index as usize >= tx.output.len() ||
-                                                               tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
+                                                               tx.output[transaction_output_index as usize].value != htlc.to_bitcoin_amount() {
                                                        // per_commitment_data is corrupt or our commitment signing key leaked!
-                                                       return (claimable_outpoints, (commitment_txid, watch_outputs),
-                                                               to_counterparty_output_info);
+                                                       return (claimable_outpoints, to_counterparty_output_info);
                                                }
                                                let revk_htlc_outp = RevokedHTLCOutput::build(per_commitment_point, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, htlc.amount_msat / 1000, htlc.clone(), &self.onchain_tx_handler.channel_transaction_parameters.channel_type_features);
                                                let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedHTLCOutput(revk_htlc_outp), htlc.cltv_expiry, height);
@@ -3299,14 +3295,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        if !claimable_outpoints.is_empty() || per_commitment_option.is_some() { // ie we're confident this is actually ours
                                // We're definitely a counterparty commitment transaction!
                                log_error!(logger, "Got broadcast of revoked counterparty commitment transaction, going to generate general spend tx with {} inputs", claimable_outpoints.len());
-                               for (idx, outp) in tx.output.iter().enumerate() {
-                                       watch_outputs.push((idx as u32, outp.clone()));
-                               }
                                self.counterparty_commitment_txn_on_chain.insert(commitment_txid, commitment_number);
 
-                               if let Some(per_commitment_data) = per_commitment_option {
+                               if let Some(per_commitment_claimable_data) = per_commitment_option {
                                        fail_unbroadcast_htlcs!(self, "revoked_counterparty", commitment_txid, tx, height,
-                                               block_hash, per_commitment_data.iter().map(|(htlc, htlc_source)|
+                                               block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
                                                        (htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
                                                ), logger);
                                } else {
@@ -3319,7 +3312,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                block_hash, [].iter().map(|reference| *reference), logger);
                                }
                        }
-               } else if let Some(per_commitment_data) = per_commitment_option {
+               } else if let Some(per_commitment_claimable_data) = per_commitment_option {
                        // While this isn't useful yet, there is a potential race where if a counterparty
                        // revokes a state at the same time as the commitment transaction for that state is
                        // confirmed, and the watchtower receives the block before the user, the user could
@@ -3327,35 +3320,31 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        // already processed the block, resulting in the counterparty_commitment_txn_on_chain entry
                        // not being generated by the above conditional. Thus, to be safe, we go ahead and
                        // insert it here.
-                       for (idx, outp) in tx.output.iter().enumerate() {
-                               watch_outputs.push((idx as u32, outp.clone()));
-                       }
                        self.counterparty_commitment_txn_on_chain.insert(commitment_txid, commitment_number);
 
                        log_info!(logger, "Got broadcast of non-revoked counterparty commitment transaction {}", commitment_txid);
                        fail_unbroadcast_htlcs!(self, "counterparty", commitment_txid, tx, height, block_hash,
-                               per_commitment_data.iter().map(|(htlc, htlc_source)|
+                               per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
                                        (htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
                                ), logger);
-
                        let (htlc_claim_reqs, counterparty_output_info) =
-                               self.get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx));
+                               self.get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx), per_commitment_option);
                        to_counterparty_output_info = counterparty_output_info;
                        for req in htlc_claim_reqs {
                                claimable_outpoints.push(req);
                        }
 
                }
-               (claimable_outpoints, (commitment_txid, watch_outputs), to_counterparty_output_info)
+               (claimable_outpoints, to_counterparty_output_info)
        }
 
        /// Returns the HTLC claim package templates and the counterparty output info
-       fn get_counterparty_output_claim_info(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>)
+       fn get_counterparty_output_claim_info(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>)
        -> (Vec<PackageTemplate>, CommitmentTxCounterpartyOutputInfo) {
                let mut claimable_outpoints = Vec::new();
                let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None;
 
-               let htlc_outputs = match self.counterparty_claimable_outpoints.get(&commitment_txid) {
+               let per_commitment_claimable_data = match per_commitment_option {
                        Some(outputs) => outputs,
                        None => return (claimable_outpoints, to_counterparty_output_info),
                };
@@ -3385,7 +3374,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
 
                        let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
                                self.counterparty_commitment_params.on_counterparty_tx_csv,
-                               &delayed_key).to_v0_p2wsh();
+                               &delayed_key).to_p2wsh();
                        for (idx, outp) in transaction.output.iter().enumerate() {
                                if outp.script_pubkey == revokeable_p2wsh {
                                        to_counterparty_output_info =
@@ -3394,11 +3383,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        }
                }
 
-               for (_, &(ref htlc, _)) in htlc_outputs.iter().enumerate() {
+               for  &(ref htlc, _) in per_commitment_claimable_data.iter() {
                        if let Some(transaction_output_index) = htlc.transaction_output_index {
                                if let Some(transaction) = tx {
                                        if transaction_output_index as usize >= transaction.output.len() ||
-                                               transaction.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
+                                               transaction.output[transaction_output_index as usize].value != htlc.to_bitcoin_amount() {
                                                        // per_commitment_data is corrupt or our commitment signing key leaked!
                                                        return (claimable_outpoints, to_counterparty_output_info);
                                                }
@@ -3481,7 +3470,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len());
 
                let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key);
-               let broadcasted_holder_revokable_script = Some((redeemscript.to_v0_p2wsh(), holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone()));
+               let broadcasted_holder_revokable_script = Some((redeemscript.to_p2wsh(), holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone()));
 
                for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
                        if let Some(transaction_output_index) = htlc.transaction_output_index {
@@ -3584,6 +3573,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        if counterparty_commitment_txid == confirmed_commitment_txid {
                                continue;
                        }
+                       // If we have generated claims for counterparty_commitment_txid earlier, we can rely on always
+                       // having claim related htlcs for counterparty_commitment_txid in counterparty_claimable_outpoints.
                        for (htlc, _) in self.counterparty_claimable_outpoints.get(counterparty_commitment_txid).unwrap_or(&vec![]) {
                                log_trace!(logger, "Canceling claims for previously confirmed counterparty commitment {}",
                                        counterparty_commitment_txid);
@@ -3719,11 +3710,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
        {
                let txn_matched = self.filter_block(txdata);
                for tx in &txn_matched {
-                       let mut output_val = 0;
+                       let mut output_val = Amount::ZERO;
                        for out in tx.output.iter() {
-                               if out.value > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
+                               if out.value > Amount::MAX_MONEY { panic!("Value-overflowing transaction provided to block connected"); }
                                output_val += out.value;
-                               if output_val > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
+                               if output_val > Amount::MAX_MONEY { panic!("Value-overflowing transaction provided to block connected"); }
                        }
                }
 
@@ -3776,24 +3767,25 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                        self.funding_spend_seen = true;
                                        let mut commitment_tx_to_counterparty_output = None;
                                        if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8*3) as u8 == 0x20 {
-                                               let (mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
-                                                       self.check_spend_counterparty_transaction(&tx, height, &block_hash, &logger);
-                                               commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
-                                               if !new_outputs.1.is_empty() {
-                                                       watch_outputs.push(new_outputs);
-                                               }
-                                               claimable_outpoints.append(&mut new_outpoints);
-                                               if new_outpoints.is_empty() {
-                                                       if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &block_hash, &logger) {
-                                                               #[cfg(not(fuzzing))]
-                                                               debug_assert!(commitment_tx_to_counterparty_output.is_none(),
-                                                                       "A commitment transaction matched as both a counterparty and local commitment tx?");
-                                                               if !new_outputs.1.is_empty() {
-                                                                       watch_outputs.push(new_outputs);
-                                                               }
-                                                               claimable_outpoints.append(&mut new_outpoints);
-                                                               balance_spendable_csv = Some(self.on_holder_tx_csv);
+                                               if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &block_hash, &logger) {
+                                                       if !new_outputs.1.is_empty() {
+                                                               watch_outputs.push(new_outputs);
+                                                       }
+
+                                                       claimable_outpoints.append(&mut new_outpoints);
+                                                       balance_spendable_csv = Some(self.on_holder_tx_csv);
+                                               } else {
+                                                       let mut new_watch_outputs = Vec::new();
+                                                       for (idx, outp) in tx.output.iter().enumerate() {
+                                                               new_watch_outputs.push((idx as u32, outp.clone()));
                                                        }
+                                                       watch_outputs.push((txid, new_watch_outputs));
+
+                                                       let (mut new_outpoints, counterparty_output_idx_sats) =
+                                                               self.check_spend_counterparty_transaction(&tx, height, &block_hash, &logger);
+                                                       commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
+
+                                                       claimable_outpoints.append(&mut new_outpoints);
                                                }
                                        }
                                        self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
@@ -4069,7 +4061,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                        // If the expected script is a known type, check that the witness
                                                        // appears to be spending the correct type (ie that the match would
                                                        // actually succeed in BIP 158/159-style filters).
-                                                       if _script_pubkey.is_v0_p2wsh() {
+                                                       if _script_pubkey.is_p2wsh() {
                                                                if input.witness.last().unwrap().to_vec() == deliberately_bogus_accepted_htlc_witness_program() {
                                                                        // In at least one test we use a deliberately bogus witness
                                                                        // script which hit an old panic. Thus, we check for that here
@@ -4078,7 +4070,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                                }
 
                                                                assert_eq!(&bitcoin::Address::p2wsh(&ScriptBuf::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey);
-                                                       } else if _script_pubkey.is_v0_p2wpkh() {
+                                                       } else if _script_pubkey.is_p2wpkh() {
                                                                assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap(), bitcoin::Network::Bitcoin).unwrap().script_pubkey(), _script_pubkey);
                                                        } else { panic!(); }
                                                }
@@ -4219,9 +4211,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                        }
 
                        macro_rules! check_htlc_valid_counterparty {
-                               ($counterparty_txid: expr, $htlc_output: expr) => {
-                                       if let Some(txid) = $counterparty_txid {
-                                               for &(ref pending_htlc, ref pending_source) in self.counterparty_claimable_outpoints.get(&txid).unwrap() {
+                               ($htlc_output: expr, $per_commitment_data: expr) => {
+                                               for &(ref pending_htlc, ref pending_source) in $per_commitment_data {
                                                        if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat {
                                                                if let &Some(ref source) = pending_source {
                                                                        log_claim!("revoked counterparty commitment tx", false, pending_htlc, true);
@@ -4230,7 +4221,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                                }
                                                        }
                                                }
-                                       }
                                }
                        }
 
@@ -4247,9 +4237,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                                // resolve the source HTLC with the original sender.
                                                                payment_data = Some(((*source).clone(), htlc_output.payment_hash, htlc_output.amount_msat));
                                                        } else if !$holder_tx {
-                                                               check_htlc_valid_counterparty!(self.current_counterparty_commitment_txid, htlc_output);
+                                                               if let Some(current_counterparty_commitment_txid) = &self.current_counterparty_commitment_txid {
+                                                                       check_htlc_valid_counterparty!(htlc_output, self.counterparty_claimable_outpoints.get(current_counterparty_commitment_txid).unwrap());
+                                                               }
                                                                if payment_data.is_none() {
-                                                                       check_htlc_valid_counterparty!(self.prev_counterparty_commitment_txid, htlc_output);
+                                                                       if let Some(prev_counterparty_commitment_txid) = &self.prev_counterparty_commitment_txid {
+                                                                               check_htlc_valid_counterparty!(htlc_output, self.counterparty_claimable_outpoints.get(prev_counterparty_commitment_txid).unwrap());
+                                                                       }
                                                                }
                                                        }
                                                        if payment_data.is_none() {
@@ -4287,7 +4281,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                }
                        }
                        if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(&input.previous_output.txid) {
-                               scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref().clone()).map(|boxed| &**boxed))),
+                               scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed))),
                                        "counterparty commitment tx", false);
                        }
 
@@ -4719,11 +4713,11 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
                // wrong `counterparty_payment_script` was being tracked. Fix it now on deserialization to
                // give them a chance to recognize the spendable output.
                if onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() &&
-                       counterparty_payment_script.is_v0_p2wpkh()
+                       counterparty_payment_script.is_p2wpkh()
                {
                        let payment_point = onchain_tx_handler.channel_transaction_parameters.holder_pubkeys.payment_point;
                        counterparty_payment_script =
-                               chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point).to_v0_p2wsh();
+                               chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point).to_p2wsh();
                }
 
                Ok((best_block.block_hash, ChannelMonitor::from_impl(ChannelMonitorImpl {
@@ -4788,10 +4782,11 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
 
 #[cfg(test)]
 mod tests {
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::locktime::absolute::LockTime;
        use bitcoin::blockdata::script::{ScriptBuf, Builder};
        use bitcoin::blockdata::opcodes;
-       use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
+       use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, Version};
        use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
        use bitcoin::sighash;
        use bitcoin::sighash::EcdsaSighashType;
@@ -4799,7 +4794,7 @@ mod tests {
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::hex::FromHex;
        use bitcoin::hash_types::{BlockHash, Txid};
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::{SecretKey,PublicKey};
        use bitcoin::secp256k1::Secp256k1;
        use bitcoin::{Sequence, Witness};
@@ -4959,7 +4954,7 @@ mod tests {
                        }
                }
                let dummy_sig = crate::crypto::utils::sign(&secp_ctx,
-                       &bitcoin::secp256k1::Message::from_slice(&[42; 32]).unwrap(),
+                       &bitcoin::secp256k1::Message::from_digest([42; 32]),
                        &SecretKey::from_slice(&[42; 32]).unwrap());
 
                macro_rules! test_preimages_exist {
@@ -5091,7 +5086,7 @@ mod tests {
                                        transaction_output_index: Some($idx as u32),
                                };
                                let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { chan_utils::get_revokeable_redeemscript(&RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey), 256, &DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(pubkey), &pubkey)) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, $opt_anchors, &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey)) };
-                               let sighash = hash_to_message!(&$sighash_parts.segwit_signature_hash($idx, &redeem_script, $amount, EcdsaSighashType::All).unwrap()[..]);
+                               let sighash = hash_to_message!(&$sighash_parts.p2wsh_signature_hash($idx, &redeem_script, $amount, EcdsaSighashType::All).unwrap()[..]);
                                let sig = secp_ctx.sign_ecdsa(&sighash, &privkey);
                                let mut ser_sig = sig.serialize_der().to_vec();
                                ser_sig.push(EcdsaSighashType::All as u8);
@@ -5120,7 +5115,7 @@ mod tests {
 
                // Justice tx with 1 to_holder, 2 revoked offered HTLCs, 1 revoked received HTLCs
                for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() {
-                       let mut claim_tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                       let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                        let mut sum_actual_sigs = 0;
                        for i in 0..4 {
                                claim_tx.input.push(TxIn {
@@ -5135,7 +5130,7 @@ mod tests {
                        }
                        claim_tx.output.push(TxOut {
                                script_pubkey: script_pubkey.clone(),
-                               value: 0,
+                               value: Amount::ZERO,
                        });
                        let base_weight = claim_tx.weight().to_wu();
                        let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT, weight_revoked_offered_htlc(channel_type_features), weight_revoked_offered_htlc(channel_type_features), weight_revoked_received_htlc(channel_type_features)];
@@ -5143,7 +5138,7 @@ mod tests {
                        {
                                let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx);
                                for (idx, inp) in inputs_weight.iter().enumerate() {
-                                       sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, channel_type_features);
+                                       sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features);
                                        inputs_total_weight += inp;
                                }
                        }
@@ -5152,7 +5147,7 @@ mod tests {
 
                // Claim tx with 1 offered HTLCs, 3 received HTLCs
                for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() {
-                       let mut claim_tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                       let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                        let mut sum_actual_sigs = 0;
                        for i in 0..4 {
                                claim_tx.input.push(TxIn {
@@ -5167,7 +5162,7 @@ mod tests {
                        }
                        claim_tx.output.push(TxOut {
                                script_pubkey: script_pubkey.clone(),
-                               value: 0,
+                               value: Amount::ZERO,
                        });
                        let base_weight = claim_tx.weight().to_wu();
                        let inputs_weight = vec![weight_offered_htlc(channel_type_features), weight_received_htlc(channel_type_features), weight_received_htlc(channel_type_features), weight_received_htlc(channel_type_features)];
@@ -5175,7 +5170,7 @@ mod tests {
                        {
                                let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx);
                                for (idx, inp) in inputs_weight.iter().enumerate() {
-                                       sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, channel_type_features);
+                                       sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features);
                                        inputs_total_weight += inp;
                                }
                        }
@@ -5184,7 +5179,7 @@ mod tests {
 
                // Justice tx with 1 revoked HTLC-Success tx output
                for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() {
-                       let mut claim_tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                       let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                        let mut sum_actual_sigs = 0;
                        claim_tx.input.push(TxIn {
                                previous_output: BitcoinOutPoint {
@@ -5197,7 +5192,7 @@ mod tests {
                        });
                        claim_tx.output.push(TxOut {
                                script_pubkey: script_pubkey.clone(),
-                               value: 0,
+                               value: Amount::ZERO,
                        });
                        let base_weight = claim_tx.weight().to_wu();
                        let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT];
@@ -5205,7 +5200,7 @@ mod tests {
                        {
                                let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx);
                                for (idx, inp) in inputs_weight.iter().enumerate() {
-                                       sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, channel_type_features);
+                                       sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features);
                                        inputs_total_weight += inp;
                                }
                        }
index 9207313d5fcb93b50fe1f1b16a294e86e683725d..e43c08d55e513a906000d52a2fd6795580bb5037 100644 (file)
@@ -13,7 +13,7 @@ use bitcoin::blockdata::block::{Block, Header};
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::script::{Script, ScriptBuf};
 use bitcoin::hash_types::{BlockHash, Txid};
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::PublicKey;
 
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, MonitorEvent};
index f66258c2c764d72d884b9670ab13ab511b2ce833..e5757cfd1e52f5b1da358f4fd88a706052447147 100644 (file)
@@ -12,6 +12,7 @@
 //! OnchainTxHandler objects are fully-part of ChannelMonitor and encapsulates all
 //! building, tracking, bumping and notifications functions.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
@@ -19,6 +20,7 @@ use bitcoin::blockdata::script::{Script, ScriptBuf};
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hash_types::{Txid, BlockHash};
+use bitcoin::secp256k1::PublicKey;
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1;
 
@@ -179,6 +181,7 @@ pub(crate) struct ExternalHTLCClaim {
        pub(crate) htlc: HTLCOutputInCommitment,
        pub(crate) preimage: Option<PaymentPreimage>,
        pub(crate) counterparty_sig: Signature,
+       pub(crate) per_commitment_point: PublicKey,
 }
 
 // Represents the different types of claims for which events are yielded externally to satisfy said
@@ -615,7 +618,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
                                assert!(new_feerate != 0);
 
                                let transaction = cached_request.maybe_finalize_malleable_package(
-                                       cur_height, self, output_value, self.destination_script.clone(), logger
+                                       cur_height, self, Amount::from_sat(output_value), self.destination_script.clone(), logger
                                ).unwrap();
                                assert!(predicted_weight >= transaction.0.weight().to_wu());
                                return Some((new_timer, new_feerate, OnchainClaim::Tx(transaction)));
@@ -644,7 +647,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
                                        let package_target_feerate_sat_per_1000_weight = cached_request
                                                .compute_package_feerate(fee_estimator, conf_target, feerate_strategy);
                                        if let Some(input_amount_sat) = output.funding_amount {
-                                               let fee_sat = input_amount_sat - tx.0.output.iter().map(|output| output.value).sum::<u64>();
+                                               let fee_sat = input_amount_sat - tx.0.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
                                                let commitment_tx_feerate_sat_per_1000_weight =
                                                        compute_feerate_sat_per_1000_weight(fee_sat, tx.0.weight().to_wu());
                                                if commitment_tx_feerate_sat_per_1000_weight >= package_target_feerate_sat_per_1000_weight {
@@ -1230,6 +1233,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
                                                htlc: htlc.clone(),
                                                preimage: *preimage,
                                                counterparty_sig: counterparty_htlc_sig,
+                                               per_commitment_point: trusted_tx.per_commitment_point(),
                                        }
                                })
                };
index 3c800a3587a43d52dcfd431652546372fc31bcc2..906e730dbf248325e4d5e8ab45d00fba29b4a2db 100644 (file)
@@ -13,6 +13,7 @@
 
 
 use bitcoin::{Sequence, Witness};
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::transaction::{TxOut,TxIn, Transaction};
@@ -21,6 +22,7 @@ use bitcoin::blockdata::script::{Script, ScriptBuf};
 use bitcoin::hash_types::Txid;
 use bitcoin::secp256k1::{SecretKey,PublicKey};
 use bitcoin::sighash::EcdsaSighashType;
+use bitcoin::transaction::Version;
 
 use crate::ln::types::PaymentPreimage;
 use crate::ln::chan_utils::{self, TxCreationKeys, HTLCOutputInCommitment};
@@ -121,13 +123,13 @@ pub(crate) struct RevokedOutput {
        counterparty_htlc_base_key: HtlcBasepoint,
        per_commitment_key: SecretKey,
        weight: u64,
-       amount: u64,
+       amount: Amount,
        on_counterparty_tx_csv: u16,
        is_counterparty_balance_on_anchors: Option<()>,
 }
 
 impl RevokedOutput {
-       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool) -> Self {
+       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: Amount, on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool) -> Self {
                RevokedOutput {
                        per_commitment_point,
                        counterparty_delayed_payment_base_key,
@@ -501,7 +503,7 @@ pub(crate) enum PackageSolvingData {
 impl PackageSolvingData {
        fn amount(&self) -> u64 {
                let amt = match self {
-                       PackageSolvingData::RevokedOutput(ref outp) => outp.amount,
+                       PackageSolvingData::RevokedOutput(ref outp) => outp.amount.to_sat(),
                        PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.amount,
                        PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
                        PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
@@ -586,7 +588,7 @@ impl PackageSolvingData {
                                let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
                                let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key);
                                //TODO: should we panic on signer failure ?
-                               if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(&bumped_tx, i, outp.amount, &outp.per_commitment_key, &onchain_handler.secp_ctx) {
+                               if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(&bumped_tx, i, outp.amount.to_sat(), &outp.per_commitment_key, &onchain_handler.secp_ctx) {
                                        let mut ser_sig = sig.serialize_der().to_vec();
                                        ser_sig.push(EcdsaSighashType::All as u8);
                                        bumped_tx.input[i].witness.push(ser_sig);
@@ -911,12 +913,12 @@ impl PackageTemplate {
                htlcs
        }
        pub(crate) fn maybe_finalize_malleable_package<L: Logger, Signer: EcdsaChannelSigner>(
-               &self, current_height: u32, onchain_handler: &mut OnchainTxHandler<Signer>, value: u64,
+               &self, current_height: u32, onchain_handler: &mut OnchainTxHandler<Signer>, value: Amount,
                destination_script: ScriptBuf, logger: &L
        ) -> Option<MaybeSignedTransaction> {
                debug_assert!(self.is_malleable());
                let mut bumped_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::from_consensus(self.package_locktime(current_height)),
                        input: vec![],
                        output: vec![TxOut {
@@ -1198,6 +1200,7 @@ mod tests {
        use crate::ln::types::{PaymentPreimage, PaymentHash};
        use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint};
 
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
        use bitcoin::blockdata::script::ScriptBuf;
        use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
@@ -1215,7 +1218,7 @@ mod tests {
                        {
                                let dumb_scalar = SecretKey::from_slice(&<Vec<u8>>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
                                let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar);
-                               PackageSolvingData::RevokedOutput(RevokedOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), dumb_scalar, 0, 0, $is_counterparty_balance_on_anchors))
+                               PackageSolvingData::RevokedOutput(RevokedOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), dumb_scalar, Amount::ZERO, 0, $is_counterparty_balance_on_anchors))
                        }
                }
        }
index 5450586ee96725a2519a911515fc9c2c9f9e1aea..13ecf2539a21de1a4c1f5c2409b1f9619e5bc5f0 100644 (file)
@@ -25,7 +25,7 @@ use bitcoin::blockdata::transaction::Transaction;
 ///
 /// use bitcoin::blockdata::block::Block;
 /// use bitcoin::blockdata::constants::genesis_block;
-/// use bitcoin::network::constants::Network;
+/// use bitcoin::network::Network;
 /// use lightning::chain::transaction::TransactionData;
 ///
 /// let block = genesis_block(Network::Bitcoin);
index 9587cff58c0c208db14d6b00faab7722a2d5e531..a1ef44c1bc15e0c46342d4beec870ca3766d339f 100644 (file)
@@ -32,14 +32,15 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
 use crate::sync::Mutex;
 use crate::util::logger::Logger;
 
-use bitcoin::{OutPoint, PubkeyHash, Sequence, ScriptBuf, Transaction, TxIn, TxOut, Witness, WPubkeyHash};
+use bitcoin::{OutPoint, Psbt, PubkeyHash, Sequence, ScriptBuf, Transaction, TxIn, TxOut, Witness, WPubkeyHash};
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::consensus::Encodable;
-use bitcoin::psbt::PartiallySignedTransaction;
 use bitcoin::secp256k1;
 use bitcoin::secp256k1::{PublicKey, Secp256k1};
 use bitcoin::secp256k1::ecdsa::Signature;
+use bitcoin::transaction::Version;
 
 pub(crate) const EMPTY_SCRIPT_SIG_WEIGHT: u64 = 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64;
 
@@ -62,8 +63,8 @@ impl AnchorDescriptor {
        /// [`Self::unsigned_tx_input`].
        pub fn previous_utxo(&self) -> TxOut {
                TxOut {
-                       script_pubkey: self.witness_script().to_v0_p2wsh(),
-                       value: ANCHOR_OUTPUT_VALUE_SATOSHI,
+                       script_pubkey: self.witness_script().to_p2wsh(),
+                       value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI),
                }
        }
 
@@ -257,7 +258,7 @@ pub struct Utxo {
 
 impl Utxo {
        /// Returns a `Utxo` with the `satisfaction_weight` estimate for a legacy P2PKH output.
-       pub fn new_p2pkh(outpoint: OutPoint, value: u64, pubkey_hash: &PubkeyHash) -> Self {
+       pub fn new_p2pkh(outpoint: OutPoint, value: Amount, pubkey_hash: &PubkeyHash) -> Self {
                let script_sig_size = 1 /* script_sig length */ +
                        1 /* OP_PUSH73 */ +
                        73 /* sig including sighash flag */ +
@@ -274,7 +275,7 @@ impl Utxo {
        }
 
        /// Returns a `Utxo` with the `satisfaction_weight` estimate for a P2WPKH nested in P2SH output.
-       pub fn new_nested_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self {
+       pub fn new_nested_p2wpkh(outpoint: OutPoint, value: Amount, pubkey_hash: &WPubkeyHash) -> Self {
                let script_sig_size = 1 /* script_sig length */ +
                        1 /* OP_0 */ +
                        1 /* OP_PUSH20 */ +
@@ -283,19 +284,19 @@ impl Utxo {
                        outpoint,
                        output: TxOut {
                                value,
-                               script_pubkey: ScriptBuf::new_p2sh(&ScriptBuf::new_v0_p2wpkh(pubkey_hash).script_hash()),
+                               script_pubkey: ScriptBuf::new_p2sh(&ScriptBuf::new_p2wpkh(pubkey_hash).script_hash()),
                        },
                        satisfaction_weight: script_sig_size * WITNESS_SCALE_FACTOR as u64 + P2WPKH_WITNESS_WEIGHT,
                }
        }
 
        /// Returns a `Utxo` with the `satisfaction_weight` estimate for a SegWit v0 P2WPKH output.
-       pub fn new_v0_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self {
+       pub fn new_v0_p2wpkh(outpoint: OutPoint, value: Amount, pubkey_hash: &WPubkeyHash) -> Self {
                Self {
                        outpoint,
                        output: TxOut {
                                value,
-                               script_pubkey: ScriptBuf::new_v0_p2wpkh(pubkey_hash),
+                               script_pubkey: ScriptBuf::new_p2wpkh(pubkey_hash),
                        },
                        satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT + P2WPKH_WITNESS_WEIGHT,
                }
@@ -356,7 +357,7 @@ pub trait CoinSelectionSource {
        ///
        /// If your wallet does not support signing PSBTs you can call `psbt.extract_tx()` to get the
        /// unsigned transaction and then sign it with your wallet.
-       fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result<Transaction, ()>;
+       fn sign_psbt(&self, psbt: Psbt) -> Result<Transaction, ()>;
 }
 
 /// An alternative to [`CoinSelectionSource`] that can be implemented and used along [`Wallet`] to
@@ -373,7 +374,7 @@ pub trait WalletSource {
        ///
        /// If your wallet does not support signing PSBTs you can call `psbt.extract_tx()` to get the
        /// unsigned transaction and then sign it with your wallet.
-       fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result<Transaction, ()>;
+       fn sign_psbt(&self, psbt: Psbt) -> Result<Transaction, ()>;
 }
 
 /// A wrapper over [`WalletSource`] that implements [`CoinSelection`] by preferring UTXOs that would
@@ -414,7 +415,7 @@ where
        fn select_confirmed_utxos_internal(
                &self, utxos: &[Utxo], claim_id: ClaimId, force_conflicting_utxo_spend: bool,
                tolerate_high_network_feerates: bool, target_feerate_sat_per_1000_weight: u32,
-               preexisting_tx_weight: u64, input_amount_sat: u64, target_amount_sat: u64,
+               preexisting_tx_weight: u64, input_amount_sat: Amount, target_amount_sat: Amount,
        ) -> Result<CoinSelection, ()> {
                let mut locked_utxos = self.locked_utxos.lock().unwrap();
                let mut eligible_utxos = utxos.iter().filter_map(|utxo| {
@@ -424,9 +425,9 @@ where
                                        return None;
                                }
                        }
-                       let fee_to_spend_utxo = fee_for_weight(
+                       let fee_to_spend_utxo = Amount::from_sat(fee_for_weight(
                                target_feerate_sat_per_1000_weight, BASE_INPUT_WEIGHT + utxo.satisfaction_weight,
-                       );
+                       ));
                        let should_spend = if tolerate_high_network_feerates {
                                utxo.output.value > fee_to_spend_utxo
                        } else {
@@ -442,7 +443,7 @@ where
                eligible_utxos.sort_unstable_by_key(|(utxo, _)| utxo.output.value);
 
                let mut selected_amount = input_amount_sat;
-               let mut total_fees = fee_for_weight(target_feerate_sat_per_1000_weight, preexisting_tx_weight);
+               let mut total_fees = Amount::from_sat(fee_for_weight(target_feerate_sat_per_1000_weight, preexisting_tx_weight));
                let mut selected_utxos = Vec::new();
                for (utxo, fee_to_spend_utxo) in eligible_utxos {
                        if selected_amount >= target_amount_sat + total_fees {
@@ -469,8 +470,8 @@ where
                        (8 /* value */ + change_script.consensus_encode(&mut sink()).unwrap() as u64) *
                                WITNESS_SCALE_FACTOR as u64,
                );
-               let change_output_amount = remaining_amount.saturating_sub(change_output_fee);
-               let change_output = if change_output_amount < change_script.dust_value().to_sat() {
+               let change_output_amount = Amount::from_sat(remaining_amount.to_sat().saturating_sub(change_output_fee));
+               let change_output = if change_output_amount < change_script.dust_value() {
                        log_debug!(self.logger, "Coin selection attempt did not yield change output");
                        None
                } else {
@@ -504,7 +505,7 @@ where
 
                let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
                        ((BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64);
-               let input_amount_sat: u64 = must_spend.iter().map(|input| input.previous_utxo.value).sum();
+               let input_amount_sat = must_spend.iter().map(|input| input.previous_utxo.value).sum();
                let target_amount_sat = must_pay_to.iter().map(|output| output.value).sum();
                let do_coin_selection = |force_conflicting_utxo_spend: bool, tolerate_high_network_feerates: bool| {
                        log_debug!(self.logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})",
@@ -520,7 +521,7 @@ where
                        .or_else(|_| do_coin_selection(true, true))
        }
 
-       fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result<Transaction, ()> {
+       fn sign_psbt(&self, psbt: Psbt) -> Result<Transaction, ()> {
                self.source.sign_psbt(psbt)
        }
 }
@@ -583,7 +584,7 @@ where
                        // way to include a dummy output.
                        log_debug!(self.logger, "Including dummy OP_RETURN output since an output is needed and a change output was not provided");
                        tx.output.push(TxOut {
-                               value: 0,
+                               value: Amount::ZERO,
                                script_pubkey: ScriptBuf::new_op_return(&[]),
                        });
                }
@@ -600,6 +601,7 @@ where
                // account. We do so by pretending the commitment transaction's fee and weight are part of
                // the anchor input.
                let mut anchor_utxo = anchor_descriptor.previous_utxo();
+               let commitment_tx_fee_sat = Amount::from_sat(commitment_tx_fee_sat);
                anchor_utxo.value += commitment_tx_fee_sat;
                let must_spend = vec![Input {
                        outpoint: anchor_descriptor.outpoint,
@@ -607,7 +609,7 @@ where
                        satisfaction_weight: commitment_tx.weight().to_wu() + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT,
                }];
                #[cfg(debug_assertions)]
-               let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::<u64>();
+               let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::<Amount>();
 
                log_debug!(self.logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW",
                        package_target_feerate_sat_per_1000_weight);
@@ -616,7 +618,7 @@ where
                )?;
 
                let mut anchor_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::ZERO, // TODO: Use next best height.
                        input: vec![anchor_descriptor.unsigned_tx_input()],
                        output: vec![],
@@ -627,13 +629,13 @@ where
                        coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>();
                #[cfg(debug_assertions)]
                let total_input_amount = must_spend_amount +
-                       coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::<u64>();
+                       coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum();
 
                self.process_coin_selection(&mut anchor_tx, &coin_selection);
                let anchor_txid = anchor_tx.txid();
 
                // construct psbt
-               let mut anchor_psbt = PartiallySignedTransaction::from_unsigned_tx(anchor_tx).unwrap();
+               let mut anchor_psbt = Psbt::from_unsigned_tx(anchor_tx).unwrap();
                // add witness_utxo to anchor input
                anchor_psbt.inputs[0].witness_utxo = Some(anchor_descriptor.previous_utxo());
                // add witness_utxo to remaining inputs
@@ -665,10 +667,10 @@ where
                        assert!(expected_signed_tx_weight >= signed_tx_weight &&
                                expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight);
 
-                       let expected_package_fee = fee_for_weight(package_target_feerate_sat_per_1000_weight,
-                               signed_tx_weight + commitment_tx.weight().to_wu());
+                       let expected_package_fee = Amount::from_sat(fee_for_weight(package_target_feerate_sat_per_1000_weight,
+                               signed_tx_weight + commitment_tx.weight().to_wu()));
                        let package_fee = total_input_amount -
-                               anchor_tx.output.iter().map(|output| output.value).sum::<u64>();
+                               anchor_tx.output.iter().map(|output| output.value).sum();
                        // Our fee should be within a 5% error margin of the expected fee based on the
                        // feerate and transaction weight and we should never pay less than required.
                        let fee_error_margin = expected_package_fee * 5 / 100;
@@ -689,7 +691,7 @@ where
                htlc_descriptors: &[HTLCDescriptor], tx_lock_time: LockTime,
        ) -> Result<(), ()> {
                let mut htlc_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: tx_lock_time,
                        input: vec![],
                        output: vec![],
@@ -718,7 +720,7 @@ where
                let must_spend_satisfaction_weight =
                        must_spend.iter().map(|input| input.satisfaction_weight).sum::<u64>();
                #[cfg(debug_assertions)]
-               let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::<u64>();
+               let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value.to_sat()).sum::<u64>();
 
                let coin_selection: CoinSelection = self.utxo_source.select_confirmed_utxos(
                        claim_id, must_spend, &htlc_tx.output, target_feerate_sat_per_1000_weight,
@@ -729,12 +731,12 @@ where
                        coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>();
                #[cfg(debug_assertions)]
                let total_input_amount = must_spend_amount +
-                       coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::<u64>();
+                       coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value.to_sat()).sum::<u64>();
 
                self.process_coin_selection(&mut htlc_tx, &coin_selection);
 
                // construct psbt
-               let mut htlc_psbt = PartiallySignedTransaction::from_unsigned_tx(htlc_tx).unwrap();
+               let mut htlc_psbt = Psbt::from_unsigned_tx(htlc_tx).unwrap();
                // add witness_utxo to htlc inputs
                for (i, htlc_descriptor) in htlc_descriptors.iter().enumerate() {
                        debug_assert_eq!(htlc_psbt.unsigned_tx.input[i].previous_output, htlc_descriptor.outpoint());
@@ -775,7 +777,7 @@ where
 
                        let expected_signed_tx_fee = fee_for_weight(target_feerate_sat_per_1000_weight, signed_tx_weight);
                        let signed_tx_fee = total_input_amount -
-                               htlc_tx.output.iter().map(|output| output.value).sum::<u64>();
+                               htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
                        // Our fee should be within a 5% error margin of the expected fee based on the
                        // feerate and transaction weight and we should never pay less than required.
                        let fee_error_margin = expected_signed_tx_fee * 5 / 100;
index a4bf1501b194376ac8ae2d1894084337d5be2fa0..45ed895ade7a0f9010c07a3bc7de73e1e1dd6913 100644 (file)
@@ -38,6 +38,7 @@ use bitcoin::blockdata::script::ScriptBuf;
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::secp256k1::PublicKey;
+use bitcoin::transaction::Version;
 use crate::io;
 use core::time::Duration;
 use core::ops::Deref;
@@ -653,6 +654,11 @@ pub enum Event {
                /// The sender-intended sum total of all the MPP parts. This will be `None` for events
                /// serialized prior to LDK version 0.0.117.
                sender_intended_total_msat: Option<u64>,
+               /// The fields in the onion which were received with each HTLC. Only fields which were
+               /// identical in each HTLC involved in the payment will be included here.
+               ///
+               /// Payments received on LDK versions prior to 0.0.124 will have this field unset.
+               onion_fields: Option<RecipientOnionFields>,
        },
        /// Indicates that a peer connection with a node is needed in order to send an [`OnionMessage`].
        ///
@@ -1348,7 +1354,7 @@ impl Writeable for Event {
                                // We never write the OpenChannelRequest events as, upon disconnection, peers
                                // drop any channels which have not yet exchanged funding_signed.
                        },
-                       &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id, ref htlcs, ref sender_intended_total_msat } => {
+                       &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id, ref htlcs, ref sender_intended_total_msat, ref onion_fields } => {
                                19u8.write(writer)?;
                                write_tlv_fields!(writer, {
                                        (0, payment_hash, required),
@@ -1357,6 +1363,7 @@ impl Writeable for Event {
                                        (4, amount_msat, required),
                                        (5, *htlcs, optional_vec),
                                        (7, sender_intended_total_msat, option),
+                                       (9, onion_fields, option),
                                });
                        },
                        &Event::ProbeSuccessful { ref payment_id, ref payment_hash, ref path } => {
@@ -1664,7 +1671,7 @@ impl MaybeReadable for Event {
                        11u8 => {
                                let mut f = || {
                                        let mut channel_id = ChannelId::new_zero();
-                                       let mut transaction = Transaction{ version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                                       let mut transaction = Transaction{ version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                                        read_tlv_fields!(reader, {
                                                (0, channel_id, required),
                                                (2, transaction, required),
@@ -1719,6 +1726,7 @@ impl MaybeReadable for Event {
                                        let mut receiver_node_id = None;
                                        let mut htlcs: Option<Vec<ClaimedHTLC>> = Some(vec![]);
                                        let mut sender_intended_total_msat: Option<u64> = None;
+                                       let mut onion_fields = None;
                                        read_tlv_fields!(reader, {
                                                (0, payment_hash, required),
                                                (1, receiver_node_id, option),
@@ -1726,6 +1734,7 @@ impl MaybeReadable for Event {
                                                (4, amount_msat, required),
                                                (5, htlcs, optional_vec),
                                                (7, sender_intended_total_msat, option),
+                                               (9, onion_fields, option),
                                        });
                                        Ok(Some(Event::PaymentClaimed {
                                                receiver_node_id,
@@ -1734,6 +1743,7 @@ impl MaybeReadable for Event {
                                                amount_msat,
                                                htlcs: htlcs.unwrap_or(vec![]),
                                                sender_intended_total_msat,
+                                               onion_fields,
                                        }))
                                };
                                f()
index 613df570d4e3bf40051d25e59a5d6fa45823dbdb..4342886f37e342e983e1901b415557f6501409e4 100644 (file)
@@ -12,6 +12,7 @@
 
 use bitcoin::{Transaction, TxOut, TxIn, Amount};
 use bitcoin::blockdata::locktime::absolute::LockTime;
+use bitcoin::transaction::Version;
 
 use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
 use crate::events::bump_transaction::WalletSource;
@@ -344,12 +345,12 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
 
        let closing_node = if remote_commitment { &nodes[1] } else { &nodes[0] };
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: closing_node.wallet_source.get_change_script().unwrap(),
                        },
                ],
@@ -363,12 +364,13 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
        // Route an HTLC and set the signer as unavailable.
        let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
        route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       let error_message = "Channel force-closed";
 
        nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &chan_id, false);
 
        if remote_commitment {
                // Make the counterparty broadcast its latest commitment.
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()).unwrap();
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_added_monitors(&nodes[1], 1);
                check_closed_broadcast(&nodes[1], 1, true);
                check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100_000);
index 4c254628de6ec63525473aa927802ec6a8eb270c..c1d65fd1a118f2f3e669950d2e2ed2db8b4cf97e 100644 (file)
@@ -180,7 +180,9 @@ fn mpp_to_one_hop_blinded_path() {
        let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_route[1], amt_msat, payment_hash.clone(),
                Some(payment_secret), ev.clone(), true, None);
-       claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage)
+       );
 }
 
 #[test]
@@ -244,7 +246,9 @@ fn mpp_to_three_hop_blinded_paths() {
        let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_route[1], amt_msat, payment_hash.clone(),
                Some(payment_secret), ev.clone(), true, None);
-       claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage)
+       );
 }
 
 enum ForwardCheckFail {
@@ -462,6 +466,7 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
                (chan.0.contents, chan.2)
        };
 
+       let error_message = "Channel force-closed";
        let amt_msat = 5000;
        let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None);
        let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000,
@@ -494,7 +499,7 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
                                ProcessPendingHTLCsCheck::FwdChannelClosed => {
                                        // Force close the next-hop channel so when we go to forward in process_pending_htlc_forwards,
                                        // the intro node will error backwards.
-                                       $curr_node.node.force_close_broadcasting_latest_txn(&$failed_chan_id, &$next_node.node.get_our_node_id()).unwrap();
+                                       $curr_node.node.force_close_broadcasting_latest_txn(&$failed_chan_id, &$next_node.node.get_our_node_id(), error_message.to_string()).unwrap();
                                        let events = $curr_node.node.get_and_clear_pending_events();
                                        match events[0] {
                                                crate::events::Event::PendingHTLCsForwardable { .. } => {},
@@ -643,7 +648,9 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) {
        expect_pending_htlcs_forwardable!(nodes[2]);
 
        expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, None, nodes[2].node.get_our_node_id());
-       do_claim_payment_along_route(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, payment_preimage);
+       do_claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+       );
        expect_payment_sent(&nodes[0], payment_preimage, Some(Some(1000)), true, true);
 }
 
@@ -1217,7 +1224,9 @@ fn blinded_keysend() {
 
        let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_route[0], amt_msat, payment_hash, Some(payment_secret), ev.clone(), true, Some(keysend_preimage));
-       claim_payment_along_route(&nodes[0], expected_route, false, keysend_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_route, keysend_preimage)
+       );
 }
 
 #[test]
@@ -1268,7 +1277,9 @@ fn blinded_mpp_keysend() {
        let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_route[1], amt_msat, payment_hash.clone(),
                Some(payment_secret), ev.clone(), true, Some(keysend_preimage));
-       claim_payment_along_route(&nodes[0], expected_route, false, keysend_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_route, keysend_preimage)
+       );
 }
 
 #[test]
@@ -1316,5 +1327,8 @@ fn custom_tlvs_to_blinded_path() {
                .with_payment_secret(payment_secret)
                .with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+                       .with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone())
+       );
 }
index 3c99cdb0943c1f1ddd44d444eee5c0f255f0fab8..b7d3aec39dc125bc2927c780bdb05aee68b29d5b 100644 (file)
 //! Various utilities for building scripts related to channels. These are
 //! largely of interest for those implementing the traits on [`crate::sign`] by hand.
 
+use bitcoin::{PubkeyHash, WPubkeyHash};
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction};
 use bitcoin::sighash;
 use bitcoin::sighash::EcdsaSighashType;
-use bitcoin::address::Payload;
+use bitcoin::transaction::Version;
 
 use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::hash160::Hash as Hash160;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::ripemd160::Hash as Ripemd160;
-use bitcoin::hash_types::{Txid, PubkeyHash, WPubkeyHash};
+use bitcoin::hash_types::Txid;
 
 use crate::chain::chaininterface::fee_for_weight;
 use crate::chain::package::WEIGHT_REVOKED_OUTPUT;
@@ -31,10 +34,10 @@ use crate::util::ser::{Readable, RequiredWrapper, Writeable, Writer};
 use crate::util::transaction_utils;
 
 use bitcoin::blockdata::locktime::absolute::LockTime;
+use bitcoin::ecdsa::Signature as BitcoinSignature;
 use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar};
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message};
 use bitcoin::{secp256k1, Sequence, Witness};
-use bitcoin::PublicKey as BitcoinPublicKey;
 
 use crate::io;
 use core::cmp;
@@ -186,7 +189,7 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32]
 }
 
 /// Build a closing transaction
-pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value_sat: u64, to_holder_script: ScriptBuf, to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint) -> Transaction {
+pub fn build_closing_transaction(to_holder_value_sat: Amount, to_counterparty_value_sat: Amount, to_holder_script: ScriptBuf, to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint) -> Transaction {
        let txins = {
                let mut ins: Vec<TxIn> = Vec::new();
                ins.push(TxIn {
@@ -200,14 +203,14 @@ pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value
 
        let mut txouts: Vec<(TxOut, ())> = Vec::new();
 
-       if to_counterparty_value_sat > 0 {
+       if to_counterparty_value_sat > Amount::ZERO {
                txouts.push((TxOut {
                        script_pubkey: to_counterparty_script,
                        value: to_counterparty_value_sat
                }, ()));
        }
 
-       if to_holder_value_sat > 0 {
+       if to_holder_value_sat > Amount::ZERO {
                txouts.push((TxOut {
                        script_pubkey: to_holder_script,
                        value: to_holder_value_sat
@@ -222,7 +225,7 @@ pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value
        }
 
        Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: txins,
                output: outputs,
@@ -515,9 +518,9 @@ pub fn get_revokeable_redeemscript(revocation_key: &RevocationKey, contest_delay
 /// the channel type.
 pub fn get_counterparty_payment_script(channel_type_features: &ChannelTypeFeatures, payment_key: &PublicKey) -> ScriptBuf {
        if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
-               get_to_countersignatory_with_anchors_redeemscript(payment_key).to_v0_p2wsh()
+               get_to_countersignatory_with_anchors_redeemscript(payment_key).to_p2wsh()
        } else {
-               ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&payment_key.serialize()))
+               ScriptBuf::new_p2wpkh(&WPubkeyHash::hash(&payment_key.serialize()))
        }
 }
 
@@ -542,6 +545,15 @@ pub struct HTLCOutputInCommitment {
        pub transaction_output_index: Option<u32>,
 }
 
+impl HTLCOutputInCommitment {
+       /// Converts HTLC's value with millisatoshi precision into [bitcoin::Amount] with satoshi precision.
+       /// Typically this conversion is needed when transitioning from LN into base-layer Bitcoin,
+       /// e. g. in commitment transactions.
+       pub const fn to_bitcoin_amount(&self) -> Amount {
+               Amount::from_sat(self.amount_msat / 1000)
+       }
+}
+
 impl_writeable_tlv_based!(HTLCOutputInCommitment, {
        (0, offered, required),
        (2, amount_msat, required),
@@ -670,7 +682,7 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte
        ));
 
        Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::from_consensus(if htlc.offered { htlc.cltv_expiry } else { 0 }),
                input: txins,
                output: txouts,
@@ -698,14 +710,14 @@ pub(crate) fn build_htlc_output(
                htlc_success_tx_weight(channel_type_features)
        };
        let output_value = if channel_type_features.supports_anchors_zero_fee_htlc_tx() && !channel_type_features.supports_anchors_nonzero_fee_htlc_tx() {
-               htlc.amount_msat / 1000
+               htlc.to_bitcoin_amount()
        } else {
-               let total_fee = feerate_per_kw as u64 * weight / 1000;
-               htlc.amount_msat / 1000 - total_fee
+               let total_fee = Amount::from_sat(feerate_per_kw as u64 * weight / 1000);
+               htlc.to_bitcoin_amount() - total_fee
        };
 
        TxOut {
-               script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_v0_p2wsh(),
+               script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_p2wsh(),
                value: output_value,
        }
 }
@@ -724,8 +736,8 @@ pub fn build_htlc_input_witness(
        let mut witness = Witness::new();
        // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
        witness.push(vec![]);
-       witness.push_bitcoin_signature(&remote_sig.serialize_der(), remote_sighash_type);
-       witness.push_bitcoin_signature(&local_sig.serialize_der(), EcdsaSighashType::All);
+       witness.push_ecdsa_signature(&BitcoinSignature { sig: *remote_sig, hash_ty: remote_sighash_type });
+       witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(*local_sig));
        if let Some(preimage) = preimage {
                witness.push(preimage.0.to_vec());
        } else {
@@ -798,7 +810,7 @@ pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> ScriptBuf {
 
 /// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`.
 pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> {
-       let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh();
+       let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_p2wsh();
        commitment_tx.output.iter().enumerate()
                .find(|(_, txout)| txout.script_pubkey == anchor_script)
                .map(|(idx, txout)| (idx as u32, txout))
@@ -808,7 +820,7 @@ pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubk
 pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
        let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
        let mut ret = Witness::new();
-       ret.push_bitcoin_signature(&funding_sig.serialize_der(), EcdsaSighashType::All);
+       ret.push_ecdsa_signature(&BitcoinSignature::sighash_all(*funding_sig));
        ret.push(anchor_redeem_script.as_bytes());
        ret
 }
@@ -1036,7 +1048,7 @@ impl HolderCommitmentTransaction {
        pub fn dummy(htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> Self {
                let secp_ctx = Secp256k1::new();
                let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
-               let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
+               let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap());
 
                let keys = TxCreationKeys {
                        per_commitment_point: dummy_key.clone(),
@@ -1091,11 +1103,11 @@ impl HolderCommitmentTransaction {
                tx.input[0].witness.push(Vec::new());
 
                if self.holder_sig_first {
-                       tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
-                       tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
+                       tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(holder_sig));
+                       tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig));
                } else {
-                       tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
-                       tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
+                       tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig));
+                       tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(holder_sig));
                }
 
                tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
@@ -1125,7 +1137,7 @@ impl BuiltCommitmentTransaction {
        ///
        /// This can be used to verify a signature.
        pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
-               let sighash = &sighash::SighashCache::new(&self.transaction).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
+               let sighash = &sighash::SighashCache::new(&self.transaction).p2wsh_signature_hash(0, funding_redeemscript, Amount::from_sat(channel_value_satoshis), EcdsaSighashType::All).unwrap()[..];
                hash_to_message!(sighash)
        }
 
@@ -1152,8 +1164,8 @@ impl BuiltCommitmentTransaction {
 /// secret key.
 #[derive(Clone, Hash, PartialEq, Eq)]
 pub struct ClosingTransaction {
-       to_holder_value_sat: u64,
-       to_counterparty_value_sat: u64,
+       to_holder_value_sat: Amount,
+       to_counterparty_value_sat: Amount,
        to_holder_script: ScriptBuf,
        to_counterparty_script: ScriptBuf,
        built: Transaction,
@@ -1168,6 +1180,8 @@ impl ClosingTransaction {
                to_counterparty_script: ScriptBuf,
                funding_outpoint: OutPoint,
        ) -> Self {
+               let to_holder_value_sat = Amount::from_sat(to_holder_value_sat);
+               let to_counterparty_value_sat = Amount::from_sat(to_counterparty_value_sat);
                let built = build_closing_transaction(
                        to_holder_value_sat, to_counterparty_value_sat,
                        to_holder_script.clone(), to_counterparty_script.clone(),
@@ -1212,12 +1226,12 @@ impl ClosingTransaction {
 
        /// The value to be sent to the holder, or zero if the output will be omitted
        pub fn to_holder_value_sat(&self) -> u64 {
-               self.to_holder_value_sat
+               self.to_holder_value_sat.to_sat()
        }
 
        /// The value to be sent to the counterparty, or zero if the output will be omitted
        pub fn to_counterparty_value_sat(&self) -> u64 {
-               self.to_counterparty_value_sat
+               self.to_counterparty_value_sat.to_sat()
        }
 
        /// The destination of the holder's output
@@ -1257,7 +1271,7 @@ impl<'a> TrustedClosingTransaction<'a> {
        ///
        /// This can be used to verify a signature.
        pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
-               let sighash = &sighash::SighashCache::new(&self.inner.built).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
+               let sighash = &sighash::SighashCache::new(&self.inner.built).p2wsh_signature_hash(0, funding_redeemscript, Amount::from_sat(channel_value_satoshis), EcdsaSighashType::All).unwrap()[..];
                hash_to_message!(sighash)
        }
 
@@ -1278,8 +1292,8 @@ impl<'a> TrustedClosingTransaction<'a> {
 #[derive(Clone, Debug)]
 pub struct CommitmentTransaction {
        commitment_number: u64,
-       to_broadcaster_value_sat: u64,
-       to_countersignatory_value_sat: u64,
+       to_broadcaster_value_sat: Amount,
+       to_countersignatory_value_sat: Amount,
        to_broadcaster_delay: Option<u16>, // Added in 0.0.117
        feerate_per_kw: u32,
        htlcs: Vec<HTLCOutputInCommitment>,
@@ -1373,6 +1387,9 @@ impl CommitmentTransaction {
        ///
        /// This is not exported to bindings users due to the generic though we likely should expose a version without
        pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
+               let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
+               let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
+
                // Sort outputs and populate output indices while keeping track of the auxiliary data
                let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
 
@@ -1420,7 +1437,7 @@ impl CommitmentTransaction {
 
        fn make_transaction(obscured_commitment_transaction_number: u64, txins: Vec<TxIn>, outputs: Vec<TxOut>) -> Transaction {
                Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::from_consensus(((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32)),
                        input: txins,
                        output: outputs,
@@ -1431,17 +1448,17 @@ impl CommitmentTransaction {
        // - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
        //   caller needs to have sorted together with the HTLCs so it can keep track of the output index
        // - building of a bitcoin transaction during a verify() call, in which case T is just ()
-       fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
+       fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
                let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
                let contest_delay = channel_parameters.contest_delay();
 
                let mut txouts: Vec<(TxOut, Option<&mut HTLCOutputInCommitment>)> = Vec::new();
 
-               if to_countersignatory_value_sat > 0 {
+               if to_countersignatory_value_sat > Amount::ZERO {
                        let script = if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
-                           get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_v0_p2wsh()
+                               get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_p2wsh()
                        } else {
-                           Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)).unwrap().script_pubkey()
+                               ScriptBuf::new_p2wpkh(&Hash160::hash(&countersignatory_pubkeys.payment_point.serialize()).into())
                        };
                        txouts.push((
                                TxOut {
@@ -1452,7 +1469,7 @@ impl CommitmentTransaction {
                        ))
                }
 
-               if to_broadcaster_value_sat > 0 {
+               if to_broadcaster_value_sat > Amount::ZERO {
                        let redeem_script = get_revokeable_redeemscript(
                                &keys.revocation_key,
                                contest_delay,
@@ -1460,7 +1477,7 @@ impl CommitmentTransaction {
                        );
                        txouts.push((
                                TxOut {
-                                       script_pubkey: redeem_script.to_v0_p2wsh(),
+                                       script_pubkey: redeem_script.to_p2wsh(),
                                        value: to_broadcaster_value_sat,
                                },
                                None,
@@ -1468,23 +1485,23 @@ impl CommitmentTransaction {
                }
 
                if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
-                       if to_broadcaster_value_sat > 0 || !htlcs_with_aux.is_empty() {
+                       if to_broadcaster_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
                                let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
                                txouts.push((
                                        TxOut {
-                                               script_pubkey: anchor_script.to_v0_p2wsh(),
-                                               value: ANCHOR_OUTPUT_VALUE_SATOSHI,
+                                               script_pubkey: anchor_script.to_p2wsh(),
+                                               value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI),
                                        },
                                        None,
                                ));
                        }
 
-                       if to_countersignatory_value_sat > 0 || !htlcs_with_aux.is_empty() {
+                       if to_countersignatory_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
                                let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
                                txouts.push((
                                        TxOut {
-                                               script_pubkey: anchor_script.to_v0_p2wsh(),
-                                               value: ANCHOR_OUTPUT_VALUE_SATOSHI,
+                                               script_pubkey: anchor_script.to_p2wsh(),
+                                               value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI),
                                        },
                                        None,
                                ));
@@ -1495,8 +1512,8 @@ impl CommitmentTransaction {
                for (htlc, _) in htlcs_with_aux {
                        let script = chan_utils::get_htlc_redeemscript(&htlc, &channel_parameters.channel_type_features(), &keys);
                        let txout = TxOut {
-                               script_pubkey: script.to_v0_p2wsh(),
-                               value: htlc.amount_msat / 1000,
+                               script_pubkey: script.to_p2wsh(),
+                               value: htlc.to_bitcoin_amount(),
                        };
                        txouts.push((txout, Some(htlc)));
                }
@@ -1566,12 +1583,12 @@ impl CommitmentTransaction {
 
        /// The value to be sent to the broadcaster
        pub fn to_broadcaster_value_sat(&self) -> u64 {
-               self.to_broadcaster_value_sat
+               self.to_broadcaster_value_sat.to_sat()
        }
 
        /// The value to be sent to the counterparty
        pub fn to_countersignatory_value_sat(&self) -> u64 {
-               self.to_countersignatory_value_sat
+               self.to_countersignatory_value_sat.to_sat()
        }
 
        /// The feerate paid per 1000-weight-unit in this commitment transaction.
@@ -1679,7 +1696,7 @@ impl<'a> TrustedCommitmentTransaction<'a> {
 
                        let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, &self.channel_type_features, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
 
-                       let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]);
+                       let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, this_htlc.to_bitcoin_amount(), EcdsaSighashType::All).unwrap()[..]);
                        ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source));
                }
                Ok(ret)
@@ -1736,7 +1753,7 @@ impl<'a> TrustedCommitmentTransaction<'a> {
                        self.to_broadcaster_delay?,
                        &self.keys.broadcaster_delayed_payment_key,
                );
-               let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
+               let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh();
                let outputs = &self.inner.built.transaction.output;
                outputs.iter().enumerate()
                        .find(|(_, out)| out.script_pubkey == revokeable_p2wsh)
@@ -1772,13 +1789,13 @@ impl<'a> TrustedCommitmentTransaction<'a> {
                        value,
                }];
                let mut justice_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::ZERO,
                        input,
                        output,
                };
                let weight = justice_tx.weight().to_wu() + WEIGHT_REVOKED_OUTPUT;
-               let fee = fee_for_weight(feerate_per_kw as u32, weight);
+               let fee = Amount::from_sat(fee_for_weight(feerate_per_kw as u32, weight));
                justice_tx.output[0].value = value.checked_sub(fee).ok_or(())?;
                Ok(justice_tx)
        }
@@ -1906,7 +1923,7 @@ mod tests {
                builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
                let tx = builder.build(1000, 2000);
                assert_eq!(tx.built.transaction.output.len(), 4);
-               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersignatory_with_anchors_redeemscript(&builder.counterparty_pubkeys.payment_point).to_v0_p2wsh());
+               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersignatory_with_anchors_redeemscript(&builder.counterparty_pubkeys.payment_point).to_p2wsh());
 
                // Generate broadcaster output and anchor
                let tx = builder.build(3000, 0);
@@ -1938,11 +1955,11 @@ mod tests {
                let tx = builder.build(3000, 0);
                let keys = &builder.keys.clone();
                assert_eq!(tx.built.transaction.output.len(), 3);
-               assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh());
-               assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh());
-               assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh().to_hex_string(),
+               assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
+               assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
+               assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh().to_hex_string(),
                                   "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb");
-               assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh().to_hex_string(),
+               assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh().to_hex_string(),
                                   "0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d");
 
                // Generate broadcaster output and received and offered HTLC outputs,  with anchors
@@ -1950,11 +1967,11 @@ mod tests {
                builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
                let tx = builder.build(3000, 0);
                assert_eq!(tx.built.transaction.output.len(), 5);
-               assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh());
-               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh());
-               assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh().to_hex_string(),
+               assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh());
+               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh());
+               assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(),
                                   "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc");
-               assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh().to_hex_string(),
+               assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(),
                                   "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7");
        }
 
@@ -2000,7 +2017,7 @@ mod tests {
                        .unwrap()[..]).unwrap();
                let pubkey_hash = BitcoinPublicKey::new(
                        PublicKey::from_secret_key(&Secp256k1::new(), &secret_key)).wpubkey_hash().unwrap();
-               let destination_script = ScriptBuf::new_v0_p2wpkh(&pubkey_hash);
+               let destination_script = ScriptBuf::new_p2wpkh(&pubkey_hash);
 
                let justice_tx = tx.trust().build_to_local_justice_tx(253, destination_script.clone()).unwrap();
                assert_eq!(justice_tx.input.len(), 1);
@@ -2009,7 +2026,7 @@ mod tests {
                assert!(justice_tx.input[0].sequence.is_rbf());
 
                assert_eq!(justice_tx.output.len(), 1);
-               assert!(justice_tx.output[0].value < 1000);
+               assert!(justice_tx.output[0].value.to_sat() < 1000);
                assert_eq!(justice_tx.output[0].script_pubkey, destination_script);
        }
 
index 7d332f2ad78b8897fa3d27e00ae23745a2d49f5b..b33e19620b1994282e19329cf7538a99e3b27676 100644 (file)
@@ -14,7 +14,7 @@
 
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::hash_types::BlockHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor};
 use crate::chain::transaction::OutPoint;
 use crate::chain::{ChannelMonitorUpdateStatus, Listen, Watch};
@@ -207,7 +207,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
        }
 
        // ...and make sure we can force-close a frozen channel
-       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors!(nodes[0], 1);
        check_closed_broadcast!(nodes[0], true);
 
@@ -2025,7 +2026,9 @@ fn test_path_paused_mpp() {
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), true, None);
 
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+       );
 }
 
 #[test]
@@ -3222,17 +3225,18 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool,
        let _ = get_revoke_commit_msgs!(nodes[1], nodes[2].node.get_our_node_id());
 
        let mon_bc = get_monitor!(nodes[1], chan_id_bc).encode();
+       let error_message = "Channel force-closed";
 
        if close_chans_before_reload {
                if !close_only_a {
                        chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
-                       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_bc, &nodes[2].node.get_our_node_id()).unwrap();
+                       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_bc, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap();
                        check_closed_broadcast(&nodes[1], 1, true);
                        check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[2].node.get_our_node_id()], 100000);
                }
 
                chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[0].node.get_our_node_id()).unwrap();
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_broadcast(&nodes[1], 1, true);
                check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000);
        }
@@ -3253,8 +3257,9 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool,
                        assert_eq!(bs_close_txn.len(), 3);
                }
        }
+       let error_message = "Channel force-closed";
 
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
        let as_closing_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
        assert_eq!(as_closing_tx.len(), 1);
@@ -3391,10 +3396,11 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) {
        let manager_b = nodes[1].node.encode();
        reload_node!(nodes[1], &manager_b, &[&mon_ab, &mon_bc], persister, new_chain_monitor, nodes_1_deserialized);
 
+       let error_message = "Channel force-closed";
        if close_during_reload {
                // Test that we still free the B<->C channel if the A<->B channel closed while we reloaded
                // (as learned about during the on-reload block connection).
-               nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id()).unwrap();
+               nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_added_monitors!(nodes[0], 1);
                check_closed_broadcast!(nodes[0], true);
                check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100_000);
index b830f9f31e6815842e6aca89aee8543827e195c7..d6ab1876ae0a31af8dfacc5bac01e35ed438e008 100644 (file)
@@ -7,6 +7,7 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
 use bitcoin::blockdata::transaction::Transaction;
@@ -29,7 +30,8 @@ use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::DecodeError;
 use crate::ln::script::{self, ShutdownScript};
-use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT, ChannelShutdownState};
+use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
+use crate::ln::channelmanager::{self, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
 use crate::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 crate::ln::chan_utils;
 use crate::ln::onion_utils::HTLCFailReason;
@@ -185,45 +187,6 @@ enum InboundHTLCState {
        LocalRemoved(InboundHTLCRemovalReason),
 }
 
-/// Exposes the state of pending inbound HTLCs.
-///
-/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
-/// through the following states in the state machine:
-/// - Announced for addition by the originating node through the update_add_htlc message.
-/// - Added to the commitment transaction of the receiving node and originating node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
-///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
-/// - Removed from the commitment transaction of the originating node and receiving node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-///
-/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
-#[derive(Clone, Debug, PartialEq)]
-pub enum InboundHTLCStateDetails {
-       /// We have added this HTLC in our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// before this HTLC is included on the remote commitment transaction.
-       AwaitingRemoteRevokeToAdd,
-       /// This HTLC has been included in the commitment_signed and revoke_and_ack messages on both sides
-       /// and is included in both commitment transactions.
-       ///
-       /// This HTLC is now safe to either forward or be claimed as a payment by us. The HTLC will
-       /// remain in this state until the forwarded upstream HTLC has been resolved and we resolve this
-       /// HTLC correspondingly, or until we claim it as a payment. If it is part of a multipart
-       /// payment, it will only be claimed together with other required parts.
-       Committed,
-       /// We have received the preimage for this HTLC and it is being removed by fulfilling it with
-       /// update_fulfill_htlc. This HTLC is still on both commitment transactions, but we are awaiting
-       /// the appropriate revoke_and_ack's from the remote before this HTLC is removed from the remote
-       /// commitment transaction after update_fulfill_htlc.
-       AwaitingRemoteRevokeToRemoveFulfill,
-       /// The HTLC is being removed by failing it with update_fail_htlc or update_fail_malformed_htlc.
-       /// This HTLC is still on both commitment transactions, but we are awaiting the appropriate
-       /// revoke_and_ack's from the remote before this HTLC is removed from the remote commitment
-       /// transaction.
-       AwaitingRemoteRevokeToRemoveFail,
-}
-
 impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
        fn from(state: &InboundHTLCState) -> Option<InboundHTLCStateDetails> {
                match state {
@@ -244,13 +207,6 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
        }
 }
 
-impl_writeable_tlv_based_enum_upgradable!(InboundHTLCStateDetails,
-       (0, AwaitingRemoteRevokeToAdd) => {},
-       (2, Committed) => {},
-       (4, AwaitingRemoteRevokeToRemoveFulfill) => {},
-       (6, AwaitingRemoteRevokeToRemoveFail) => {};
-);
-
 struct InboundHTLCOutput {
        htlc_id: u64,
        amount_msat: u64,
@@ -259,53 +215,6 @@ struct InboundHTLCOutput {
        state: InboundHTLCState,
 }
 
-/// Exposes details around pending inbound HTLCs.
-#[derive(Clone, Debug, PartialEq)]
-pub struct InboundHTLCDetails {
-       /// The HTLC ID.
-       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
-       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
-       /// and not part of any commitment transaction.
-       pub htlc_id: u64,
-       /// The amount in msat.
-       pub amount_msat: u64,
-       /// The block height at which this HTLC expires.
-       pub cltv_expiry: u32,
-       /// The payment hash.
-       pub payment_hash: PaymentHash,
-       /// The state of the HTLC in the state machine.
-       ///
-       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
-       /// waiting for to advance to the next state.
-       ///
-       /// See [`InboundHTLCStateDetails`] for information on the specific states.
-       ///
-       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
-       /// states may result in `None` here.
-       pub state: Option<InboundHTLCStateDetails>,
-       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
-       /// from the local commitment transaction and added to the commitment transaction fee.
-       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
-       /// transactions as well.
-       ///
-       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
-       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
-       /// fee.
-       ///
-       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
-       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
-       pub is_dust: bool,
-}
-
-impl_writeable_tlv_based!(InboundHTLCDetails, {
-       (0, htlc_id, required),
-       (2, amount_msat, required),
-       (4, cltv_expiry, required),
-       (6, payment_hash, required),
-       (7, state, upgradable_option),
-       (8, is_dust, required),
-});
-
 #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
 enum OutboundHTLCState {
        /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
@@ -339,42 +248,6 @@ enum OutboundHTLCState {
        AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome),
 }
 
-/// Exposes the state of pending outbound HTLCs.
-///
-/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
-/// through the following states in the state machine:
-/// - Announced for addition by the originating node through the update_add_htlc message.
-/// - Added to the commitment transaction of the receiving node and originating node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
-///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
-/// - Removed from the commitment transaction of the originating node and receiving node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-///
-/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
-#[derive(Clone, Debug, PartialEq)]
-pub enum OutboundHTLCStateDetails {
-       /// We are awaiting the appropriate revoke_and_ack's from the remote before the HTLC is added
-       /// on the remote's commitment transaction after update_add_htlc.
-       AwaitingRemoteRevokeToAdd,
-       /// The HTLC has been added to the remote's commitment transaction by sending commitment_signed
-       /// and receiving revoke_and_ack in return.
-       ///
-       /// The HTLC will remain in this state until the remote node resolves the HTLC, or until we
-       /// unilaterally close the channel due to a timeout with an uncooperative remote node.
-       Committed,
-       /// The HTLC has been fulfilled successfully by the remote with a preimage in update_fulfill_htlc,
-       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// for the removal from its commitment transaction.
-       AwaitingRemoteRevokeToRemoveSuccess,
-       /// The HTLC has been failed by the remote with update_fail_htlc or update_fail_malformed_htlc,
-       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// for the removal from its commitment transaction.
-       AwaitingRemoteRevokeToRemoveFailure,
-}
-
 impl From<&OutboundHTLCState> for OutboundHTLCStateDetails {
        fn from(state: &OutboundHTLCState) -> OutboundHTLCStateDetails {
                match state {
@@ -398,13 +271,6 @@ impl From<&OutboundHTLCState> for OutboundHTLCStateDetails {
        }
 }
 
-impl_writeable_tlv_based_enum_upgradable!(OutboundHTLCStateDetails,
-       (0, AwaitingRemoteRevokeToAdd) => {},
-       (2, Committed) => {},
-       (4, AwaitingRemoteRevokeToRemoveSuccess) => {},
-       (6, AwaitingRemoteRevokeToRemoveFailure) => {};
-);
-
 #[derive(Clone)]
 #[cfg_attr(test, derive(Debug, PartialEq))]
 enum OutboundHTLCOutcome {
@@ -443,58 +309,6 @@ struct OutboundHTLCOutput {
        skimmed_fee_msat: Option<u64>,
 }
 
-/// Exposes details around pending outbound HTLCs.
-#[derive(Clone, Debug, PartialEq)]
-pub struct OutboundHTLCDetails {
-       /// The HTLC ID.
-       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
-       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
-       /// and not part of any commitment transaction.
-       ///
-       /// Not present when we are awaiting a remote revocation and the HTLC is not added yet.
-       pub htlc_id: Option<u64>,
-       /// The amount in msat.
-       pub amount_msat: u64,
-       /// The block height at which this HTLC expires.
-       pub cltv_expiry: u32,
-       /// The payment hash.
-       pub payment_hash: PaymentHash,
-       /// The state of the HTLC in the state machine.
-       ///
-       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
-       /// waiting for to advance to the next state.
-       ///
-       /// See [`OutboundHTLCStateDetails`] for information on the specific states.
-       ///
-       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
-       /// states may result in `None` here.
-       pub state: Option<OutboundHTLCStateDetails>,
-       /// The extra fee being skimmed off the top of this HTLC.
-       pub skimmed_fee_msat: Option<u64>,
-       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
-       /// from the local commitment transaction and added to the commitment transaction fee.
-       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
-       /// transactions as well.
-       ///
-       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
-       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
-       /// fee.
-       ///
-       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
-       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
-       pub is_dust: bool,
-}
-
-impl_writeable_tlv_based!(OutboundHTLCDetails, {
-       (0, htlc_id, required),
-       (2, amount_msat, required),
-       (4, cltv_expiry, required),
-       (6, payment_hash, required),
-       (7, state, upgradable_option),
-       (8, skimmed_fee_msat, required),
-       (10, is_dust, required),
-});
-
 /// See AwaitingRemoteRevoke ChannelState for more info
 #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
 enum HTLCUpdateAwaitingACK {
@@ -4534,7 +4348,7 @@ impl<SP: Deref> Channel<SP> where
 
                                let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys);
                                let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
-                               let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]);
+                               let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
                                log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
                                        log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
                                        encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
@@ -6030,7 +5844,7 @@ impl<SP: Deref> Channel<SP> where
                };
 
                for outp in closing_tx.trust().built_transaction().output.iter() {
-                       if !outp.script_pubkey.is_witness_program() && outp.value < MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS {
+                       if !outp.script_pubkey.is_witness_program() && outp.value < Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS) {
                                return Err(ChannelError::Close("Remote sent us a closing_signed with a dust output. Always use segwit closing scripts!".to_owned()));
                        }
                }
@@ -6582,8 +6396,8 @@ impl<SP: Deref> Channel<SP> where
                                if self.context.funding_tx_confirmation_height == 0 {
                                        if tx.txid() == funding_txo.txid {
                                                let txo_idx = funding_txo.index as usize;
-                                               if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() ||
-                                                               tx.output[txo_idx].value != self.context.channel_value_satoshis {
+                                               if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_p2wsh() ||
+                                                               tx.output[txo_idx].value.to_sat() != self.context.channel_value_satoshis {
                                                        if self.context.is_outbound() {
                                                                // If we generated the funding transaction and it doesn't match what it
                                                                // should, the client is really broken and we should just panic and
@@ -6598,7 +6412,7 @@ impl<SP: Deref> Channel<SP> where
                                                        return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
                                                } else {
                                                        if self.context.is_outbound() {
-                                                               if !tx.is_coin_base() {
+                                                               if !tx.is_coinbase() {
                                                                        for input in tx.input.iter() {
                                                                                if input.witness.is_empty() {
                                                                                        // We generated a malleable funding transaction, implying we've
@@ -6618,7 +6432,7 @@ impl<SP: Deref> Channel<SP> where
                                                }
                                                // If this is a coinbase transaction and not a 0-conf channel
                                                // we should update our min_depth to 100 to handle coinbase maturity
-                                               if tx.is_coin_base() &&
+                                               if tx.is_coinbase() &&
                                                        self.context.minimum_depth.unwrap_or(0) > 0 &&
                                                        self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
                                                        self.context.minimum_depth = Some(COINBASE_MATURITY);
@@ -7562,7 +7376,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
 
                // If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100.
                // We can skip this if it is a zero-conf channel.
-               if funding_transaction.is_coin_base() &&
+               if funding_transaction.is_coinbase() &&
                        self.context.minimum_depth.unwrap_or(0) > 0 &&
                        self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
                        self.context.minimum_depth = Some(COINBASE_MATURITY);
@@ -7842,7 +7656,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
 
                let funding_redeemscript = self.context.get_funding_redeemscript();
                let funding_txo = self.context.get_funding_txo().unwrap();
-               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
+               let funding_txo_script = funding_redeemscript.to_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
                let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
                let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
@@ -8140,7 +7954,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                let (counterparty_initial_commitment_tx, funding_signed) = self.context.get_funding_signed_msg(logger);
 
                let funding_redeemscript = self.context.get_funding_redeemscript();
-               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
+               let funding_txo_script = funding_redeemscript.to_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
                let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
                let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
@@ -9511,11 +9325,12 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
 #[cfg(test)]
 mod tests {
        use std::cmp;
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::{ScriptBuf, Builder};
-       use bitcoin::blockdata::transaction::{Transaction, TxOut};
+       use bitcoin::blockdata::transaction::{Transaction, TxOut, Version};
        use bitcoin::blockdata::opcodes;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use crate::ln::onion_utils::INVALID_ONION_BLINDING;
        use crate::ln::types::{PaymentHash, PaymentPreimage};
        use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
@@ -9544,9 +9359,8 @@ mod tests {
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::hex::FromHex;
-       use bitcoin::hash_types::WPubkeyHash;
        use bitcoin::blockdata::locktime::absolute::LockTime;
-       use bitcoin::address::{WitnessProgram, WitnessVersion};
+       use bitcoin::{WitnessProgram, WitnessVersion, WPubkeyHash};
        use crate::prelude::*;
 
        #[test]
@@ -9702,8 +9516,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -9831,8 +9645,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -10020,8 +9834,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -10087,8 +9901,8 @@ mod tests {
                        &features, &outbound_chan.get_open_channel(ChainHash::using_genesis_block(network)), 7, &config, 0, &&logger, false
                ).unwrap();
                outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(), &config.channel_handshake_limits, &features).unwrap();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: outbound_chan.context.get_funding_redeemscript(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: outbound_chan.context.get_funding_redeemscript(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created = outbound_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap().unwrap();
@@ -10345,7 +10159,7 @@ mod tests {
                                                &htlc, $opt_anchors, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
                                        let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys);
                                        let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
-                                       let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap();
+                                       let htlc_sighash = Message::from_digest(sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap().as_raw_hash().to_byte_array());
                                        assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key.to_public_key()).is_ok(), "verify counterparty htlc sig");
 
                                        let mut preimage: Option<PaymentPreimage> = None;
@@ -11211,15 +11025,15 @@ mod tests {
                // Fund the channel with a batch funding transaction.
                let output_script = node_a_chan.context.get_funding_redeemscript();
                let tx = Transaction {
-                       version: 1,
+                       version: Version::ONE,
                        lock_time: LockTime::ZERO,
                        input: Vec::new(),
                        output: vec![
                                TxOut {
-                                       value: 10000000, script_pubkey: output_script.clone(),
+                                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                                },
                                TxOut {
-                                       value: 10000000, script_pubkey: Builder::new().into_script(),
+                                       value: Amount::from_sat(10000000), script_pubkey: Builder::new().into_script(),
                                },
                        ]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
diff --git a/lightning/src/ln/channel_state.rs b/lightning/src/ln/channel_state.rs
new file mode 100644 (file)
index 0000000..5e71b8f
--- /dev/null
@@ -0,0 +1,705 @@
+// 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.
+
+//! Information about the state of a channel.
+
+use alloc::vec::Vec;
+
+use bitcoin::secp256k1::PublicKey;
+
+use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator};
+use crate::chain::transaction::OutPoint;
+use crate::io;
+use crate::ln::channel::ChannelContext;
+use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
+use crate::ln::msgs::DecodeError;
+use crate::ln::types::{ChannelId, PaymentHash};
+use crate::sign::SignerProvider;
+use crate::util::config::ChannelConfig;
+use crate::util::ser::{Readable, Writeable, Writer};
+
+use core::ops::Deref;
+
+/// Exposes the state of pending inbound HTLCs.
+///
+/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
+/// through the following states in the state machine:
+/// - Announced for addition by the originating node through the update_add_htlc message.
+/// - Added to the commitment transaction of the receiving node and originating node in turn
+///   through the exchange of commitment_signed and revoke_and_ack messages.
+/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
+///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
+/// - Removed from the commitment transaction of the originating node and receiving node in turn
+///   through the exchange of commitment_signed and revoke_and_ack messages.
+///
+/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
+#[derive(Clone, Debug, PartialEq)]
+pub enum InboundHTLCStateDetails {
+       /// We have added this HTLC in our commitment transaction by receiving commitment_signed and
+       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
+       /// before this HTLC is included on the remote commitment transaction.
+       AwaitingRemoteRevokeToAdd,
+       /// This HTLC has been included in the commitment_signed and revoke_and_ack messages on both sides
+       /// and is included in both commitment transactions.
+       ///
+       /// This HTLC is now safe to either forward or be claimed as a payment by us. The HTLC will
+       /// remain in this state until the forwarded upstream HTLC has been resolved and we resolve this
+       /// HTLC correspondingly, or until we claim it as a payment. If it is part of a multipart
+       /// payment, it will only be claimed together with other required parts.
+       Committed,
+       /// We have received the preimage for this HTLC and it is being removed by fulfilling it with
+       /// update_fulfill_htlc. This HTLC is still on both commitment transactions, but we are awaiting
+       /// the appropriate revoke_and_ack's from the remote before this HTLC is removed from the remote
+       /// commitment transaction after update_fulfill_htlc.
+       AwaitingRemoteRevokeToRemoveFulfill,
+       /// The HTLC is being removed by failing it with update_fail_htlc or update_fail_malformed_htlc.
+       /// This HTLC is still on both commitment transactions, but we are awaiting the appropriate
+       /// revoke_and_ack's from the remote before this HTLC is removed from the remote commitment
+       /// transaction.
+       AwaitingRemoteRevokeToRemoveFail,
+}
+
+impl_writeable_tlv_based_enum_upgradable!(InboundHTLCStateDetails,
+       (0, AwaitingRemoteRevokeToAdd) => {},
+       (2, Committed) => {},
+       (4, AwaitingRemoteRevokeToRemoveFulfill) => {},
+       (6, AwaitingRemoteRevokeToRemoveFail) => {};
+);
+
+/// Exposes details around pending inbound HTLCs.
+#[derive(Clone, Debug, PartialEq)]
+pub struct InboundHTLCDetails {
+       /// The HTLC ID.
+       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
+       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
+       /// and not part of any commitment transaction.
+       pub htlc_id: u64,
+       /// The amount in msat.
+       pub amount_msat: u64,
+       /// The block height at which this HTLC expires.
+       pub cltv_expiry: u32,
+       /// The payment hash.
+       pub payment_hash: PaymentHash,
+       /// The state of the HTLC in the state machine.
+       ///
+       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
+       /// waiting for to advance to the next state.
+       ///
+       /// See [`InboundHTLCStateDetails`] for information on the specific states.
+       ///
+       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
+       /// states may result in `None` here.
+       pub state: Option<InboundHTLCStateDetails>,
+       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
+       /// from the local commitment transaction and added to the commitment transaction fee.
+       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
+       /// transactions as well.
+       ///
+       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
+       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
+       /// fee.
+       ///
+       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
+       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
+       pub is_dust: bool,
+}
+
+impl_writeable_tlv_based!(InboundHTLCDetails, {
+       (0, htlc_id, required),
+       (2, amount_msat, required),
+       (4, cltv_expiry, required),
+       (6, payment_hash, required),
+       (7, state, upgradable_option),
+       (8, is_dust, required),
+});
+
+/// Exposes the state of pending outbound HTLCs.
+///
+/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
+/// through the following states in the state machine:
+/// - Announced for addition by the originating node through the update_add_htlc message.
+/// - Added to the commitment transaction of the receiving node and originating node in turn
+///   through the exchange of commitment_signed and revoke_and_ack messages.
+/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
+///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
+/// - Removed from the commitment transaction of the originating node and receiving node in turn
+///   through the exchange of commitment_signed and revoke_and_ack messages.
+///
+/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
+#[derive(Clone, Debug, PartialEq)]
+pub enum OutboundHTLCStateDetails {
+       /// We are awaiting the appropriate revoke_and_ack's from the remote before the HTLC is added
+       /// on the remote's commitment transaction after update_add_htlc.
+       AwaitingRemoteRevokeToAdd,
+       /// The HTLC has been added to the remote's commitment transaction by sending commitment_signed
+       /// and receiving revoke_and_ack in return.
+       ///
+       /// The HTLC will remain in this state until the remote node resolves the HTLC, or until we
+       /// unilaterally close the channel due to a timeout with an uncooperative remote node.
+       Committed,
+       /// The HTLC has been fulfilled successfully by the remote with a preimage in update_fulfill_htlc,
+       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
+       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
+       /// for the removal from its commitment transaction.
+       AwaitingRemoteRevokeToRemoveSuccess,
+       /// The HTLC has been failed by the remote with update_fail_htlc or update_fail_malformed_htlc,
+       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
+       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
+       /// for the removal from its commitment transaction.
+       AwaitingRemoteRevokeToRemoveFailure,
+}
+
+impl_writeable_tlv_based_enum_upgradable!(OutboundHTLCStateDetails,
+       (0, AwaitingRemoteRevokeToAdd) => {},
+       (2, Committed) => {},
+       (4, AwaitingRemoteRevokeToRemoveSuccess) => {},
+       (6, AwaitingRemoteRevokeToRemoveFailure) => {};
+);
+
+/// Exposes details around pending outbound HTLCs.
+#[derive(Clone, Debug, PartialEq)]
+pub struct OutboundHTLCDetails {
+       /// The HTLC ID.
+       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
+       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
+       /// and not part of any commitment transaction.
+       ///
+       /// Not present when we are awaiting a remote revocation and the HTLC is not added yet.
+       pub htlc_id: Option<u64>,
+       /// The amount in msat.
+       pub amount_msat: u64,
+       /// The block height at which this HTLC expires.
+       pub cltv_expiry: u32,
+       /// The payment hash.
+       pub payment_hash: PaymentHash,
+       /// The state of the HTLC in the state machine.
+       ///
+       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
+       /// waiting for to advance to the next state.
+       ///
+       /// See [`OutboundHTLCStateDetails`] for information on the specific states.
+       ///
+       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
+       /// states may result in `None` here.
+       pub state: Option<OutboundHTLCStateDetails>,
+       /// The extra fee being skimmed off the top of this HTLC.
+       pub skimmed_fee_msat: Option<u64>,
+       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
+       /// from the local commitment transaction and added to the commitment transaction fee.
+       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
+       /// transactions as well.
+       ///
+       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
+       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
+       /// fee.
+       ///
+       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
+       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
+       pub is_dust: bool,
+}
+
+impl_writeable_tlv_based!(OutboundHTLCDetails, {
+       (0, htlc_id, required),
+       (2, amount_msat, required),
+       (4, cltv_expiry, required),
+       (6, payment_hash, required),
+       (7, state, upgradable_option),
+       (8, skimmed_fee_msat, required),
+       (10, is_dust, required),
+});
+
+/// Information needed for constructing an invoice route hint for this channel.
+#[derive(Clone, Debug, PartialEq)]
+pub struct CounterpartyForwardingInfo {
+       /// Base routing fee in millisatoshis.
+       pub fee_base_msat: u32,
+       /// Amount in millionths of a satoshi the channel will charge per transferred satoshi.
+       pub fee_proportional_millionths: u32,
+       /// The minimum difference in cltv_expiry between an ingoing HTLC and its outgoing counterpart,
+       /// such that the outgoing HTLC is forwardable to this counterparty. See `msgs::ChannelUpdate`'s
+       /// `cltv_expiry_delta` for more details.
+       pub cltv_expiry_delta: u16,
+}
+
+impl_writeable_tlv_based!(CounterpartyForwardingInfo, {
+       (2, fee_base_msat, required),
+       (4, fee_proportional_millionths, required),
+       (6, cltv_expiry_delta, required),
+});
+
+/// Channel parameters which apply to our counterparty. These are split out from [`ChannelDetails`]
+/// to better separate parameters.
+#[derive(Clone, Debug, PartialEq)]
+pub struct ChannelCounterparty {
+       /// The node_id of our counterparty
+       pub node_id: PublicKey,
+       /// The Features the channel counterparty provided upon last connection.
+       /// Useful for routing as it is the most up-to-date copy of the counterparty's features and
+       /// many routing-relevant features are present in the init context.
+       pub features: InitFeatures,
+       /// The value, in satoshis, that must always be held in the channel for our counterparty. This
+       /// value ensures that if our counterparty broadcasts a revoked state, we can punish them by
+       /// claiming at least this value on chain.
+       ///
+       /// This value is not included in [`inbound_capacity_msat`] as it can never be spent.
+       ///
+       /// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
+       pub unspendable_punishment_reserve: u64,
+       /// Information on the fees and requirements that the counterparty requires when forwarding
+       /// payments to us through this channel.
+       pub forwarding_info: Option<CounterpartyForwardingInfo>,
+       /// The smallest value HTLC (in msat) the remote peer will accept, for this channel. This field
+       /// is only `None` before we have received either the `OpenChannel` or `AcceptChannel` message
+       /// from the remote peer, or for `ChannelCounterparty` objects serialized prior to LDK 0.0.107.
+       pub outbound_htlc_minimum_msat: Option<u64>,
+       /// The largest value HTLC (in msat) the remote peer currently will accept, for this channel.
+       pub outbound_htlc_maximum_msat: Option<u64>,
+}
+
+impl_writeable_tlv_based!(ChannelCounterparty, {
+       (2, node_id, required),
+       (4, features, required),
+       (6, unspendable_punishment_reserve, required),
+       (8, forwarding_info, option),
+       (9, outbound_htlc_minimum_msat, option),
+       (11, outbound_htlc_maximum_msat, option),
+});
+
+/// Details of a channel, as returned by [`ChannelManager::list_channels`] and [`ChannelManager::list_usable_channels`]
+///
+/// [`ChannelManager::list_channels`]: crate::ln::channelmanager::ChannelManager::list_channels
+/// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels
+#[derive(Clone, Debug, PartialEq)]
+pub struct ChannelDetails {
+       /// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
+       /// thereafter this is the txid of the funding transaction xor the funding transaction output).
+       /// Note that this means this value is *not* persistent - it can change once during the
+       /// lifetime of the channel.
+       pub channel_id: ChannelId,
+       /// Parameters which apply to our counterparty. See individual fields for more information.
+       pub counterparty: ChannelCounterparty,
+       /// The Channel's funding transaction output, if we've negotiated the funding transaction with
+       /// our counterparty already.
+       pub funding_txo: Option<OutPoint>,
+       /// The features which this channel operates with. See individual features for more info.
+       ///
+       /// `None` until negotiation completes and the channel type is finalized.
+       pub channel_type: Option<ChannelTypeFeatures>,
+       /// The position of the funding transaction in the chain. None if the funding transaction has
+       /// not yet been confirmed and the channel fully opened.
+       ///
+       /// Note that if [`inbound_scid_alias`] is set, it must be used for invoices and inbound
+       /// payments instead of this. See [`get_inbound_payment_scid`].
+       ///
+       /// For channels with [`confirmations_required`] set to `Some(0)`, [`outbound_scid_alias`] may
+       /// be used in place of this in outbound routes. See [`get_outbound_payment_scid`].
+       ///
+       /// [`inbound_scid_alias`]: Self::inbound_scid_alias
+       /// [`outbound_scid_alias`]: Self::outbound_scid_alias
+       /// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
+       /// [`get_outbound_payment_scid`]: Self::get_outbound_payment_scid
+       /// [`confirmations_required`]: Self::confirmations_required
+       pub short_channel_id: Option<u64>,
+       /// An optional [`short_channel_id`] alias for this channel, randomly generated by us and
+       /// usable in place of [`short_channel_id`] to reference the channel in outbound routes when
+       /// the channel has not yet been confirmed (as long as [`confirmations_required`] is
+       /// `Some(0)`).
+       ///
+       /// This will be `None` as long as the channel is not available for routing outbound payments.
+       ///
+       /// [`short_channel_id`]: Self::short_channel_id
+       /// [`confirmations_required`]: Self::confirmations_required
+       pub outbound_scid_alias: Option<u64>,
+       /// An optional [`short_channel_id`] alias for this channel, randomly generated by our
+       /// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
+       /// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
+       /// when they see a payment to be routed to us.
+       ///
+       /// Our counterparty may choose to rotate this value at any time, though will always recognize
+       /// previous values for inbound payment forwarding.
+       ///
+       /// [`short_channel_id`]: Self::short_channel_id
+       pub inbound_scid_alias: Option<u64>,
+       /// The value, in satoshis, of this channel as appears in the funding output
+       pub channel_value_satoshis: u64,
+       /// The value, in satoshis, that must always be held in the channel for us. This value ensures
+       /// that if we broadcast a revoked state, our counterparty can punish us by claiming at least
+       /// this value on chain.
+       ///
+       /// This value is not included in [`outbound_capacity_msat`] as it can never be spent.
+       ///
+       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
+       ///
+       /// [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
+       pub unspendable_punishment_reserve: Option<u64>,
+       /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
+       /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
+       /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
+       /// `user_channel_id` will be randomized for an inbound channel.  This may be zero for objects
+       /// serialized with LDK versions prior to 0.0.113.
+       ///
+       /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
+       /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
+       /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
+       pub user_channel_id: u128,
+       /// The currently negotiated fee rate denominated in satoshi per 1000 weight units,
+       /// which is applied to commitment and HTLC transactions.
+       ///
+       /// This value will be `None` for objects serialized with LDK versions prior to 0.0.115.
+       pub feerate_sat_per_1000_weight: Option<u32>,
+       /// Our total balance.  This is the amount we would get if we close the channel.
+       /// This value is not exact. Due to various in-flight changes and feerate changes, exactly this
+       /// amount is not likely to be recoverable on close.
+       ///
+       /// This does not include any pending HTLCs which are not yet fully resolved (and, thus, whose
+       /// balance is not available for inclusion in new outbound HTLCs). This further does not include
+       /// any pending outgoing HTLCs which are awaiting some other resolution to be sent.
+       /// This does not consider any on-chain fees.
+       ///
+       /// See also [`ChannelDetails::outbound_capacity_msat`]
+       pub balance_msat: u64,
+       /// The available outbound capacity for sending HTLCs to the remote peer. This does not include
+       /// any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
+       /// available for inclusion in new outbound HTLCs). This further does not include any pending
+       /// outgoing HTLCs which are awaiting some other resolution to be sent.
+       ///
+       /// See also [`ChannelDetails::balance_msat`]
+       ///
+       /// This value is not exact. Due to various in-flight changes, feerate changes, and our
+       /// conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
+       /// should be able to spend nearly this amount.
+       pub outbound_capacity_msat: u64,
+       /// The available outbound capacity for sending a single HTLC to the remote peer. This is
+       /// similar to [`ChannelDetails::outbound_capacity_msat`] but it may be further restricted by
+       /// the current state and per-HTLC limit(s). This is intended for use when routing, allowing us
+       /// to use a limit as close as possible to the HTLC limit we can currently send.
+       ///
+       /// See also [`ChannelDetails::next_outbound_htlc_minimum_msat`],
+       /// [`ChannelDetails::balance_msat`], and [`ChannelDetails::outbound_capacity_msat`].
+       pub next_outbound_htlc_limit_msat: u64,
+       /// The minimum value for sending a single HTLC to the remote peer. This is the equivalent of
+       /// [`ChannelDetails::next_outbound_htlc_limit_msat`] but represents a lower-bound, rather than
+       /// an upper-bound. This is intended for use when routing, allowing us to ensure we pick a
+       /// route which is valid.
+       pub next_outbound_htlc_minimum_msat: u64,
+       /// The available inbound capacity for the remote peer to send HTLCs to us. This does not
+       /// include any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
+       /// available for inclusion in new inbound HTLCs).
+       /// Note that there are some corner cases not fully handled here, so the actual available
+       /// inbound capacity may be slightly higher than this.
+       ///
+       /// This value is not exact. Due to various in-flight changes, feerate changes, and our
+       /// counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
+       /// However, our counterparty should be able to spend nearly this amount.
+       pub inbound_capacity_msat: u64,
+       /// The number of required confirmations on the funding transaction before the funding will be
+       /// considered "locked". This number is selected by the channel fundee (i.e. us if
+       /// [`is_outbound`] is *not* set), and can be selected for inbound channels with
+       /// [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
+       /// [`ChannelHandshakeLimits::max_minimum_depth`].
+       ///
+       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
+       ///
+       /// [`is_outbound`]: ChannelDetails::is_outbound
+       /// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
+       /// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
+       pub confirmations_required: Option<u32>,
+       /// The current number of confirmations on the funding transaction.
+       ///
+       /// This value will be `None` for objects serialized with LDK versions prior to 0.0.113.
+       pub confirmations: Option<u32>,
+       /// The number of blocks (after our commitment transaction confirms) that we will need to wait
+       /// until we can claim our funds after we force-close the channel. During this time our
+       /// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
+       /// force-closes the channel and broadcasts a commitment transaction we do not have to wait any
+       /// time to claim our non-HTLC-encumbered funds.
+       ///
+       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
+       pub force_close_spend_delay: Option<u16>,
+       /// True if the channel was initiated (and thus funded) by us.
+       pub is_outbound: bool,
+       /// True if the channel is confirmed, channel_ready messages have been exchanged, and the
+       /// channel is not currently being shut down. `channel_ready` message exchange implies the
+       /// required confirmation count has been reached (and we were connected to the peer at some
+       /// point after the funding transaction received enough confirmations). The required
+       /// confirmation count is provided in [`confirmations_required`].
+       ///
+       /// [`confirmations_required`]: ChannelDetails::confirmations_required
+       pub is_channel_ready: bool,
+       /// The stage of the channel's shutdown.
+       /// `None` for `ChannelDetails` serialized on LDK versions prior to 0.0.116.
+       pub channel_shutdown_state: Option<ChannelShutdownState>,
+       /// True if the channel is (a) confirmed and channel_ready messages have been exchanged, (b)
+       /// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
+       ///
+       /// This is a strict superset of `is_channel_ready`.
+       pub is_usable: bool,
+       /// True if this channel is (or will be) publicly-announced.
+       pub is_public: bool,
+       /// The smallest value HTLC (in msat) we will accept, for this channel. This field
+       /// is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.107
+       pub inbound_htlc_minimum_msat: Option<u64>,
+       /// The largest value HTLC (in msat) we currently will accept, for this channel.
+       pub inbound_htlc_maximum_msat: Option<u64>,
+       /// Set of configurable parameters that affect channel operation.
+       ///
+       /// This field is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.109.
+       pub config: Option<ChannelConfig>,
+       /// Pending inbound HTLCs.
+       ///
+       /// This field is empty for objects serialized with LDK versions prior to 0.0.122.
+       pub pending_inbound_htlcs: Vec<InboundHTLCDetails>,
+       /// Pending outbound HTLCs.
+       ///
+       /// This field is empty for objects serialized with LDK versions prior to 0.0.122.
+       pub pending_outbound_htlcs: Vec<OutboundHTLCDetails>,
+}
+
+impl ChannelDetails {
+       /// Gets the current SCID which should be used to identify this channel for inbound payments.
+       /// This should be used for providing invoice hints or in any other context where our
+       /// counterparty will forward a payment to us.
+       ///
+       /// This is either the [`ChannelDetails::inbound_scid_alias`], if set, or the
+       /// [`ChannelDetails::short_channel_id`]. See those for more information.
+       pub fn get_inbound_payment_scid(&self) -> Option<u64> {
+               self.inbound_scid_alias.or(self.short_channel_id)
+       }
+
+       /// Gets the current SCID which should be used to identify this channel for outbound payments.
+       /// This should be used in [`Route`]s to describe the first hop or in other contexts where
+       /// we're sending or forwarding a payment outbound over this channel.
+       ///
+       /// This is either the [`ChannelDetails::short_channel_id`], if set, or the
+       /// [`ChannelDetails::outbound_scid_alias`]. See those for more information.
+       ///
+       /// [`Route`]: crate::routing::router::Route
+       pub fn get_outbound_payment_scid(&self) -> Option<u64> {
+               self.short_channel_id.or(self.outbound_scid_alias)
+       }
+
+       pub(super) fn from_channel_context<SP: Deref, F: Deref>(
+               context: &ChannelContext<SP>, best_block_height: u32, latest_features: InitFeatures,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
+       ) -> Self
+       where
+               SP::Target: SignerProvider,
+               F::Target: FeeEstimator,
+       {
+               let balance = context.get_available_balances(fee_estimator);
+               let (to_remote_reserve_satoshis, to_self_reserve_satoshis) =
+                       context.get_holder_counterparty_selected_channel_reserve_satoshis();
+               ChannelDetails {
+                       channel_id: context.channel_id(),
+                       counterparty: ChannelCounterparty {
+                               node_id: context.get_counterparty_node_id(),
+                               features: latest_features,
+                               unspendable_punishment_reserve: to_remote_reserve_satoshis,
+                               forwarding_info: context.counterparty_forwarding_info(),
+                               // Ensures that we have actually received the `htlc_minimum_msat` value
+                               // from the counterparty through the `OpenChannel` or `AcceptChannel`
+                               // message (as they are always the first message from the counterparty).
+                               // Else `Channel::get_counterparty_htlc_minimum_msat` could return the
+                               // default `0` value set by `Channel::new_outbound`.
+                               outbound_htlc_minimum_msat: if context.have_received_message() {
+                                       Some(context.get_counterparty_htlc_minimum_msat())
+                               } else {
+                                       None
+                               },
+                               outbound_htlc_maximum_msat: context.get_counterparty_htlc_maximum_msat(),
+                       },
+                       funding_txo: context.get_funding_txo(),
+                       // Note that accept_channel (or open_channel) is always the first message, so
+                       // `have_received_message` indicates that type negotiation has completed.
+                       channel_type: if context.have_received_message() {
+                               Some(context.get_channel_type().clone())
+                       } else {
+                               None
+                       },
+                       short_channel_id: context.get_short_channel_id(),
+                       outbound_scid_alias: if context.is_usable() {
+                               Some(context.outbound_scid_alias())
+                       } else {
+                               None
+                       },
+                       inbound_scid_alias: context.latest_inbound_scid_alias(),
+                       channel_value_satoshis: context.get_value_satoshis(),
+                       feerate_sat_per_1000_weight: Some(context.get_feerate_sat_per_1000_weight()),
+                       unspendable_punishment_reserve: to_self_reserve_satoshis,
+                       balance_msat: balance.balance_msat,
+                       inbound_capacity_msat: balance.inbound_capacity_msat,
+                       outbound_capacity_msat: balance.outbound_capacity_msat,
+                       next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
+                       next_outbound_htlc_minimum_msat: balance.next_outbound_htlc_minimum_msat,
+                       user_channel_id: context.get_user_id(),
+                       confirmations_required: context.minimum_depth(),
+                       confirmations: Some(context.get_funding_tx_confirmations(best_block_height)),
+                       force_close_spend_delay: context.get_counterparty_selected_contest_delay(),
+                       is_outbound: context.is_outbound(),
+                       is_channel_ready: context.is_usable(),
+                       is_usable: context.is_live(),
+                       is_public: context.should_announce(),
+                       inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum_msat()),
+                       inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(),
+                       config: Some(context.config()),
+                       channel_shutdown_state: Some(context.shutdown_state()),
+                       pending_inbound_htlcs: context.get_pending_inbound_htlc_details(),
+                       pending_outbound_htlcs: context.get_pending_outbound_htlc_details(),
+               }
+       }
+}
+
+impl Writeable for ChannelDetails {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               // `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
+               // versions prior to 0.0.113, the u128 is serialized as two separate u64 values.
+               let user_channel_id_low = self.user_channel_id as u64;
+               let user_channel_id_high_opt = Some((self.user_channel_id >> 64) as u64);
+               write_tlv_fields!(writer, {
+                       (1, self.inbound_scid_alias, option),
+                       (2, self.channel_id, required),
+                       (3, self.channel_type, option),
+                       (4, self.counterparty, required),
+                       (5, self.outbound_scid_alias, option),
+                       (6, self.funding_txo, option),
+                       (7, self.config, option),
+                       (8, self.short_channel_id, option),
+                       (9, self.confirmations, option),
+                       (10, self.channel_value_satoshis, required),
+                       (12, self.unspendable_punishment_reserve, option),
+                       (14, user_channel_id_low, required),
+                       (16, self.balance_msat, required),
+                       (18, self.outbound_capacity_msat, required),
+                       (19, self.next_outbound_htlc_limit_msat, required),
+                       (20, self.inbound_capacity_msat, required),
+                       (21, self.next_outbound_htlc_minimum_msat, required),
+                       (22, self.confirmations_required, option),
+                       (24, self.force_close_spend_delay, option),
+                       (26, self.is_outbound, required),
+                       (28, self.is_channel_ready, required),
+                       (30, self.is_usable, required),
+                       (32, self.is_public, required),
+                       (33, self.inbound_htlc_minimum_msat, option),
+                       (35, self.inbound_htlc_maximum_msat, option),
+                       (37, user_channel_id_high_opt, option),
+                       (39, self.feerate_sat_per_1000_weight, option),
+                       (41, self.channel_shutdown_state, option),
+                       (43, self.pending_inbound_htlcs, optional_vec),
+                       (45, self.pending_outbound_htlcs, optional_vec),
+               });
+               Ok(())
+       }
+}
+
+impl Readable for ChannelDetails {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               _init_and_read_len_prefixed_tlv_fields!(reader, {
+                       (1, inbound_scid_alias, option),
+                       (2, channel_id, required),
+                       (3, channel_type, option),
+                       (4, counterparty, required),
+                       (5, outbound_scid_alias, option),
+                       (6, funding_txo, option),
+                       (7, config, option),
+                       (8, short_channel_id, option),
+                       (9, confirmations, option),
+                       (10, channel_value_satoshis, required),
+                       (12, unspendable_punishment_reserve, option),
+                       (14, user_channel_id_low, required),
+                       (16, balance_msat, required),
+                       (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() as u64)),
+                       (20, inbound_capacity_msat, required),
+                       (21, next_outbound_htlc_minimum_msat, (default_value, 0)),
+                       (22, confirmations_required, option),
+                       (24, force_close_spend_delay, option),
+                       (26, is_outbound, required),
+                       (28, is_channel_ready, required),
+                       (30, is_usable, required),
+                       (32, is_public, required),
+                       (33, inbound_htlc_minimum_msat, option),
+                       (35, inbound_htlc_maximum_msat, option),
+                       (37, user_channel_id_high_opt, option),
+                       (39, feerate_sat_per_1000_weight, option),
+                       (41, channel_shutdown_state, option),
+                       (43, pending_inbound_htlcs, optional_vec),
+                       (45, pending_outbound_htlcs, optional_vec),
+               });
+
+               // `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
+               // versions prior to 0.0.113, the u128 is serialized as two separate u64 values.
+               let user_channel_id_low: u64 = user_channel_id_low.0.unwrap();
+               let user_channel_id = user_channel_id_low as u128
+                       + ((user_channel_id_high_opt.unwrap_or(0 as u64) as u128) << 64);
+
+               Ok(Self {
+                       inbound_scid_alias,
+                       channel_id: channel_id.0.unwrap(),
+                       channel_type,
+                       counterparty: counterparty.0.unwrap(),
+                       outbound_scid_alias,
+                       funding_txo,
+                       config,
+                       short_channel_id,
+                       channel_value_satoshis: channel_value_satoshis.0.unwrap(),
+                       unspendable_punishment_reserve,
+                       user_channel_id,
+                       balance_msat: balance_msat.0.unwrap(),
+                       outbound_capacity_msat: outbound_capacity_msat.0.unwrap(),
+                       next_outbound_htlc_limit_msat: next_outbound_htlc_limit_msat.0.unwrap(),
+                       next_outbound_htlc_minimum_msat: next_outbound_htlc_minimum_msat.0.unwrap(),
+                       inbound_capacity_msat: inbound_capacity_msat.0.unwrap(),
+                       confirmations_required,
+                       confirmations,
+                       force_close_spend_delay,
+                       is_outbound: is_outbound.0.unwrap(),
+                       is_channel_ready: is_channel_ready.0.unwrap(),
+                       is_usable: is_usable.0.unwrap(),
+                       is_public: is_public.0.unwrap(),
+                       inbound_htlc_minimum_msat,
+                       inbound_htlc_maximum_msat,
+                       feerate_sat_per_1000_weight,
+                       channel_shutdown_state,
+                       pending_inbound_htlcs: pending_inbound_htlcs.unwrap_or(Vec::new()),
+                       pending_outbound_htlcs: pending_outbound_htlcs.unwrap_or(Vec::new()),
+               })
+       }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+/// Further information on the details of the channel shutdown.
+/// Upon channels being forced closed (i.e. commitment transaction confirmation detected
+/// by `ChainMonitor`), ChannelShutdownState will be set to `ShutdownComplete` or
+/// the channel will be removed shortly.
+/// Also note, that in normal operation, peers could disconnect at any of these states
+/// and require peer re-connection before making progress onto other states
+pub enum ChannelShutdownState {
+       /// Channel has not sent or received a shutdown message.
+       NotShuttingDown,
+       /// Local node has sent a shutdown message for this channel.
+       ShutdownInitiated,
+       /// Shutdown message exchanges have concluded and the channels are in the midst of
+       /// resolving all existing open HTLCs before closing can continue.
+       ResolvingHTLCs,
+       /// All HTLCs have been resolved, nodes are currently negotiating channel close onchain fee rates.
+       NegotiatingClosingFee,
+       /// We've successfully negotiated a closing_signed dance. At this point `ChannelManager` is about
+       /// to drop the channel.
+       ShutdownComplete,
+}
+
+impl_writeable_tlv_based_enum!(ChannelShutdownState,
+       (0, NotShuttingDown) => {},
+       (2, ShutdownInitiated) => {},
+       (4, ResolvingHTLCs) => {},
+       (6, NegotiatingClosingFee) => {},
+       (8, ShutdownComplete) => {}, ;
+);
index 51b3fc1539bcd9edc04f355ece36da40598db5b6..992fd3c6f02d258c82a570e40567ddc2049b06c3 100644 (file)
@@ -21,7 +21,7 @@ use bitcoin::blockdata::block::Header;
 use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::key::constants::SECRET_KEY_SIZE;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
@@ -46,7 +46,7 @@ use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, Messa
 use crate::ln::inbound_payment;
 use crate::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext};
-pub use crate::ln::channel::{InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
+use crate::ln::channel_state::ChannelDetails;
 use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
 #[cfg(any(feature = "_test_utils", test))]
 use crate::ln::features::Bolt11InvoiceFeatures;
@@ -681,6 +681,7 @@ struct ClaimingPayment {
        receiver_node_id: PublicKey,
        htlcs: Vec<events::ClaimedHTLC>,
        sender_intended_value: Option<u64>,
+       onion_fields: Option<RecipientOnionFields>,
 }
 impl_writeable_tlv_based!(ClaimingPayment, {
        (0, amount_msat, required),
@@ -688,6 +689,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
        (4, receiver_node_id, required),
        (5, htlcs, optional_vec),
        (7, sender_intended_value, option),
+       (9, onion_fields, option),
 });
 
 struct ClaimablePayment {
@@ -1168,7 +1170,7 @@ where
 ///
 /// ```
 /// use bitcoin::BlockHash;
-/// use bitcoin::network::constants::Network;
+/// use bitcoin::network::Network;
 /// use lightning::chain::BestBlock;
 /// # use lightning::chain::channelmonitor::ChannelMonitor;
 /// use lightning::ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs};
@@ -1354,11 +1356,12 @@ where
 /// #
 /// # fn example<T: AChannelManager>(channel_manager: T) {
 /// # let channel_manager = channel_manager.get_cm();
+/// # let error_message = "Channel force-closed";
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, ..  } => {
 ///         if !is_trusted(counterparty_node_id) {
 ///             match channel_manager.force_close_without_broadcasting_txn(
-///                 &temporary_channel_id, &counterparty_node_id
+///                 &temporary_channel_id, &counterparty_node_id, error_message.to_string()
 ///             ) {
 ///                 Ok(()) => println!("Rejecting channel {}", temporary_channel_id),
 ///                 Err(e) => println!("Error rejecting channel {}: {:?}", temporary_channel_id, e),
@@ -1551,8 +1554,9 @@ where
 /// #
 /// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
 /// # let channel_manager = channel_manager.get_cm();
+/// # let absolute_expiry = None;
 /// let offer = channel_manager
-///     .create_offer_builder()?
+///     .create_offer_builder(absolute_expiry)?
 /// # ;
 /// # // Needed for compiling for c_bindings
 /// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
@@ -2284,337 +2288,18 @@ const MAX_UNFUNDED_CHANNEL_PEERS: usize = 50;
 /// many peers we reject new (inbound) connections.
 const MAX_NO_CHANNEL_PEERS: usize = 250;
 
-/// Information needed for constructing an invoice route hint for this channel.
-#[derive(Clone, Debug, PartialEq)]
-pub struct CounterpartyForwardingInfo {
-       /// Base routing fee in millisatoshis.
-       pub fee_base_msat: u32,
-       /// Amount in millionths of a satoshi the channel will charge per transferred satoshi.
-       pub fee_proportional_millionths: u32,
-       /// The minimum difference in cltv_expiry between an ingoing HTLC and its outgoing counterpart,
-       /// such that the outgoing HTLC is forwardable to this counterparty. See `msgs::ChannelUpdate`'s
-       /// `cltv_expiry_delta` for more details.
-       pub cltv_expiry_delta: u16,
-}
-
-/// Channel parameters which apply to our counterparty. These are split out from [`ChannelDetails`]
-/// to better separate parameters.
-#[derive(Clone, Debug, PartialEq)]
-pub struct ChannelCounterparty {
-       /// The node_id of our counterparty
-       pub node_id: PublicKey,
-       /// The Features the channel counterparty provided upon last connection.
-       /// Useful for routing as it is the most up-to-date copy of the counterparty's features and
-       /// many routing-relevant features are present in the init context.
-       pub features: InitFeatures,
-       /// The value, in satoshis, that must always be held in the channel for our counterparty. This
-       /// value ensures that if our counterparty broadcasts a revoked state, we can punish them by
-       /// claiming at least this value on chain.
-       ///
-       /// This value is not included in [`inbound_capacity_msat`] as it can never be spent.
-       ///
-       /// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
-       pub unspendable_punishment_reserve: u64,
-       /// Information on the fees and requirements that the counterparty requires when forwarding
-       /// payments to us through this channel.
-       pub forwarding_info: Option<CounterpartyForwardingInfo>,
-       /// The smallest value HTLC (in msat) the remote peer will accept, for this channel. This field
-       /// is only `None` before we have received either the `OpenChannel` or `AcceptChannel` message
-       /// from the remote peer, or for `ChannelCounterparty` objects serialized prior to LDK 0.0.107.
-       pub outbound_htlc_minimum_msat: Option<u64>,
-       /// The largest value HTLC (in msat) the remote peer currently will accept, for this channel.
-       pub outbound_htlc_maximum_msat: Option<u64>,
-}
-
-/// Details of a channel, as returned by [`ChannelManager::list_channels`] and [`ChannelManager::list_usable_channels`]
-#[derive(Clone, Debug, PartialEq)]
-pub struct ChannelDetails {
-       /// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
-       /// thereafter this is the txid of the funding transaction xor the funding transaction output).
-       /// Note that this means this value is *not* persistent - it can change once during the
-       /// lifetime of the channel.
-       pub channel_id: ChannelId,
-       /// Parameters which apply to our counterparty. See individual fields for more information.
-       pub counterparty: ChannelCounterparty,
-       /// The Channel's funding transaction output, if we've negotiated the funding transaction with
-       /// our counterparty already.
-       pub funding_txo: Option<OutPoint>,
-       /// The features which this channel operates with. See individual features for more info.
-       ///
-       /// `None` until negotiation completes and the channel type is finalized.
-       pub channel_type: Option<ChannelTypeFeatures>,
-       /// The position of the funding transaction in the chain. None if the funding transaction has
-       /// not yet been confirmed and the channel fully opened.
-       ///
-       /// Note that if [`inbound_scid_alias`] is set, it must be used for invoices and inbound
-       /// payments instead of this. See [`get_inbound_payment_scid`].
-       ///
-       /// For channels with [`confirmations_required`] set to `Some(0)`, [`outbound_scid_alias`] may
-       /// be used in place of this in outbound routes. See [`get_outbound_payment_scid`].
-       ///
-       /// [`inbound_scid_alias`]: Self::inbound_scid_alias
-       /// [`outbound_scid_alias`]: Self::outbound_scid_alias
-       /// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
-       /// [`get_outbound_payment_scid`]: Self::get_outbound_payment_scid
-       /// [`confirmations_required`]: Self::confirmations_required
-       pub short_channel_id: Option<u64>,
-       /// An optional [`short_channel_id`] alias for this channel, randomly generated by us and
-       /// usable in place of [`short_channel_id`] to reference the channel in outbound routes when
-       /// the channel has not yet been confirmed (as long as [`confirmations_required`] is
-       /// `Some(0)`).
-       ///
-       /// This will be `None` as long as the channel is not available for routing outbound payments.
-       ///
-       /// [`short_channel_id`]: Self::short_channel_id
-       /// [`confirmations_required`]: Self::confirmations_required
-       pub outbound_scid_alias: Option<u64>,
-       /// An optional [`short_channel_id`] alias for this channel, randomly generated by our
-       /// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
-       /// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
-       /// when they see a payment to be routed to us.
-       ///
-       /// Our counterparty may choose to rotate this value at any time, though will always recognize
-       /// previous values for inbound payment forwarding.
-       ///
-       /// [`short_channel_id`]: Self::short_channel_id
-       pub inbound_scid_alias: Option<u64>,
-       /// The value, in satoshis, of this channel as appears in the funding output
-       pub channel_value_satoshis: u64,
-       /// The value, in satoshis, that must always be held in the channel for us. This value ensures
-       /// that if we broadcast a revoked state, our counterparty can punish us by claiming at least
-       /// this value on chain.
-       ///
-       /// This value is not included in [`outbound_capacity_msat`] as it can never be spent.
-       ///
-       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
-       ///
-       /// [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
-       pub unspendable_punishment_reserve: Option<u64>,
-       /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
-       /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
-       /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
-       /// `user_channel_id` will be randomized for an inbound channel.  This may be zero for objects
-       /// serialized with LDK versions prior to 0.0.113.
-       ///
-       /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
-       /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
-       /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
-       pub user_channel_id: u128,
-       /// The currently negotiated fee rate denominated in satoshi per 1000 weight units,
-       /// which is applied to commitment and HTLC transactions.
-       ///
-       /// This value will be `None` for objects serialized with LDK versions prior to 0.0.115.
-       pub feerate_sat_per_1000_weight: Option<u32>,
-       /// Our total balance.  This is the amount we would get if we close the channel.
-       /// This value is not exact. Due to various in-flight changes and feerate changes, exactly this
-       /// amount is not likely to be recoverable on close.
-       ///
-       /// This does not include any pending HTLCs which are not yet fully resolved (and, thus, whose
-       /// balance is not available for inclusion in new outbound HTLCs). This further does not include
-       /// any pending outgoing HTLCs which are awaiting some other resolution to be sent.
-       /// This does not consider any on-chain fees.
-       ///
-       /// See also [`ChannelDetails::outbound_capacity_msat`]
-       pub balance_msat: u64,
-       /// The available outbound capacity for sending HTLCs to the remote peer. This does not include
-       /// any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
-       /// available for inclusion in new outbound HTLCs). This further does not include any pending
-       /// outgoing HTLCs which are awaiting some other resolution to be sent.
-       ///
-       /// See also [`ChannelDetails::balance_msat`]
-       ///
-       /// This value is not exact. Due to various in-flight changes, feerate changes, and our
-       /// conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
-       /// should be able to spend nearly this amount.
-       pub outbound_capacity_msat: u64,
-       /// The available outbound capacity for sending a single HTLC to the remote peer. This is
-       /// similar to [`ChannelDetails::outbound_capacity_msat`] but it may be further restricted by
-       /// the current state and per-HTLC limit(s). This is intended for use when routing, allowing us
-       /// to use a limit as close as possible to the HTLC limit we can currently send.
-       ///
-       /// See also [`ChannelDetails::next_outbound_htlc_minimum_msat`],
-       /// [`ChannelDetails::balance_msat`], and [`ChannelDetails::outbound_capacity_msat`].
-       pub next_outbound_htlc_limit_msat: u64,
-       /// The minimum value for sending a single HTLC to the remote peer. This is the equivalent of
-       /// [`ChannelDetails::next_outbound_htlc_limit_msat`] but represents a lower-bound, rather than
-       /// an upper-bound. This is intended for use when routing, allowing us to ensure we pick a
-       /// route which is valid.
-       pub next_outbound_htlc_minimum_msat: u64,
-       /// The available inbound capacity for the remote peer to send HTLCs to us. This does not
-       /// include any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
-       /// available for inclusion in new inbound HTLCs).
-       /// Note that there are some corner cases not fully handled here, so the actual available
-       /// inbound capacity may be slightly higher than this.
-       ///
-       /// This value is not exact. Due to various in-flight changes, feerate changes, and our
-       /// counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
-       /// However, our counterparty should be able to spend nearly this amount.
-       pub inbound_capacity_msat: u64,
-       /// The number of required confirmations on the funding transaction before the funding will be
-       /// considered "locked". This number is selected by the channel fundee (i.e. us if
-       /// [`is_outbound`] is *not* set), and can be selected for inbound channels with
-       /// [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
-       /// [`ChannelHandshakeLimits::max_minimum_depth`].
-       ///
-       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
-       ///
-       /// [`is_outbound`]: ChannelDetails::is_outbound
-       /// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
-       /// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
-       pub confirmations_required: Option<u32>,
-       /// The current number of confirmations on the funding transaction.
-       ///
-       /// This value will be `None` for objects serialized with LDK versions prior to 0.0.113.
-       pub confirmations: Option<u32>,
-       /// The number of blocks (after our commitment transaction confirms) that we will need to wait
-       /// until we can claim our funds after we force-close the channel. During this time our
-       /// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
-       /// force-closes the channel and broadcasts a commitment transaction we do not have to wait any
-       /// time to claim our non-HTLC-encumbered funds.
-       ///
-       /// This value will be `None` for outbound channels until the counterparty accepts the channel.
-       pub force_close_spend_delay: Option<u16>,
-       /// True if the channel was initiated (and thus funded) by us.
-       pub is_outbound: bool,
-       /// True if the channel is confirmed, channel_ready messages have been exchanged, and the
-       /// channel is not currently being shut down. `channel_ready` message exchange implies the
-       /// required confirmation count has been reached (and we were connected to the peer at some
-       /// point after the funding transaction received enough confirmations). The required
-       /// confirmation count is provided in [`confirmations_required`].
-       ///
-       /// [`confirmations_required`]: ChannelDetails::confirmations_required
-       pub is_channel_ready: bool,
-       /// The stage of the channel's shutdown.
-       /// `None` for `ChannelDetails` serialized on LDK versions prior to 0.0.116.
-       pub channel_shutdown_state: Option<ChannelShutdownState>,
-       /// True if the channel is (a) confirmed and channel_ready messages have been exchanged, (b)
-       /// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
-       ///
-       /// This is a strict superset of `is_channel_ready`.
-       pub is_usable: bool,
-       /// True if this channel is (or will be) publicly-announced.
-       pub is_public: bool,
-       /// The smallest value HTLC (in msat) we will accept, for this channel. This field
-       /// is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.107
-       pub inbound_htlc_minimum_msat: Option<u64>,
-       /// The largest value HTLC (in msat) we currently will accept, for this channel.
-       pub inbound_htlc_maximum_msat: Option<u64>,
-       /// Set of configurable parameters that affect channel operation.
-       ///
-       /// This field is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.109.
-       pub config: Option<ChannelConfig>,
-       /// Pending inbound HTLCs.
-       ///
-       /// This field is empty for objects serialized with LDK versions prior to 0.0.122.
-       pub pending_inbound_htlcs: Vec<InboundHTLCDetails>,
-       /// Pending outbound HTLCs.
-       ///
-       /// This field is empty for objects serialized with LDK versions prior to 0.0.122.
-       pub pending_outbound_htlcs: Vec<OutboundHTLCDetails>,
-}
-
-impl ChannelDetails {
-       /// Gets the current SCID which should be used to identify this channel for inbound payments.
-       /// This should be used for providing invoice hints or in any other context where our
-       /// counterparty will forward a payment to us.
-       ///
-       /// This is either the [`ChannelDetails::inbound_scid_alias`], if set, or the
-       /// [`ChannelDetails::short_channel_id`]. See those for more information.
-       pub fn get_inbound_payment_scid(&self) -> Option<u64> {
-               self.inbound_scid_alias.or(self.short_channel_id)
-       }
-
-       /// Gets the current SCID which should be used to identify this channel for outbound payments.
-       /// This should be used in [`Route`]s to describe the first hop or in other contexts where
-       /// we're sending or forwarding a payment outbound over this channel.
-       ///
-       /// This is either the [`ChannelDetails::short_channel_id`], if set, or the
-       /// [`ChannelDetails::outbound_scid_alias`]. See those for more information.
-       pub fn get_outbound_payment_scid(&self) -> Option<u64> {
-               self.short_channel_id.or(self.outbound_scid_alias)
-       }
-
-       fn from_channel_context<SP: Deref, F: Deref>(
-               context: &ChannelContext<SP>, best_block_height: u32, latest_features: InitFeatures,
-               fee_estimator: &LowerBoundedFeeEstimator<F>
-       ) -> Self
-       where
-               SP::Target: SignerProvider,
-               F::Target: FeeEstimator
-       {
-               let balance = context.get_available_balances(fee_estimator);
-               let (to_remote_reserve_satoshis, to_self_reserve_satoshis) =
-                       context.get_holder_counterparty_selected_channel_reserve_satoshis();
-               ChannelDetails {
-                       channel_id: context.channel_id(),
-                       counterparty: ChannelCounterparty {
-                               node_id: context.get_counterparty_node_id(),
-                               features: latest_features,
-                               unspendable_punishment_reserve: to_remote_reserve_satoshis,
-                               forwarding_info: context.counterparty_forwarding_info(),
-                               // Ensures that we have actually received the `htlc_minimum_msat` value
-                               // from the counterparty through the `OpenChannel` or `AcceptChannel`
-                               // message (as they are always the first message from the counterparty).
-                               // Else `Channel::get_counterparty_htlc_minimum_msat` could return the
-                               // default `0` value set by `Channel::new_outbound`.
-                               outbound_htlc_minimum_msat: if context.have_received_message() {
-                                       Some(context.get_counterparty_htlc_minimum_msat()) } else { None },
-                               outbound_htlc_maximum_msat: context.get_counterparty_htlc_maximum_msat(),
-                       },
-                       funding_txo: context.get_funding_txo(),
-                       // Note that accept_channel (or open_channel) is always the first message, so
-                       // `have_received_message` indicates that type negotiation has completed.
-                       channel_type: if context.have_received_message() { Some(context.get_channel_type().clone()) } else { None },
-                       short_channel_id: context.get_short_channel_id(),
-                       outbound_scid_alias: if context.is_usable() { Some(context.outbound_scid_alias()) } else { None },
-                       inbound_scid_alias: context.latest_inbound_scid_alias(),
-                       channel_value_satoshis: context.get_value_satoshis(),
-                       feerate_sat_per_1000_weight: Some(context.get_feerate_sat_per_1000_weight()),
-                       unspendable_punishment_reserve: to_self_reserve_satoshis,
-                       balance_msat: balance.balance_msat,
-                       inbound_capacity_msat: balance.inbound_capacity_msat,
-                       outbound_capacity_msat: balance.outbound_capacity_msat,
-                       next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
-                       next_outbound_htlc_minimum_msat: balance.next_outbound_htlc_minimum_msat,
-                       user_channel_id: context.get_user_id(),
-                       confirmations_required: context.minimum_depth(),
-                       confirmations: Some(context.get_funding_tx_confirmations(best_block_height)),
-                       force_close_spend_delay: context.get_counterparty_selected_contest_delay(),
-                       is_outbound: context.is_outbound(),
-                       is_channel_ready: context.is_usable(),
-                       is_usable: context.is_live(),
-                       is_public: context.should_announce(),
-                       inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum_msat()),
-                       inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(),
-                       config: Some(context.config()),
-                       channel_shutdown_state: Some(context.shutdown_state()),
-                       pending_inbound_htlcs: context.get_pending_inbound_htlc_details(),
-                       pending_outbound_htlcs: context.get_pending_outbound_htlc_details(),
-               }
-       }
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-/// Further information on the details of the channel shutdown.
-/// Upon channels being forced closed (i.e. commitment transaction confirmation detected
-/// by `ChainMonitor`), ChannelShutdownState will be set to `ShutdownComplete` or
-/// the channel will be removed shortly.
-/// Also note, that in normal operation, peers could disconnect at any of these states
-/// and require peer re-connection before making progress onto other states
-pub enum ChannelShutdownState {
-       /// Channel has not sent or received a shutdown message.
-       NotShuttingDown,
-       /// Local node has sent a shutdown message for this channel.
-       ShutdownInitiated,
-       /// Shutdown message exchanges have concluded and the channels are in the midst of
-       /// resolving all existing open HTLCs before closing can continue.
-       ResolvingHTLCs,
-       /// All HTLCs have been resolved, nodes are currently negotiating channel close onchain fee rates.
-       NegotiatingClosingFee,
-       /// We've successfully negotiated a closing_signed dance. At this point `ChannelManager` is about
-       /// to drop the channel.
-       ShutdownComplete,
-}
+/// The maximum expiration from the current time where an [`Offer`] or [`Refund`] is considered
+/// short-lived, while anything with a greater expiration is considered long-lived.
+///
+/// Using [`ChannelManager::create_offer_builder`] or [`ChannelManager::create_refund_builder`],
+/// will included a [`BlindedPath`] created using:
+/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and
+/// - [`MessageRouter::create_blinded_paths`] when long-lived.
+///
+/// Using compact [`BlindedPath`]s may provide better privacy as the [`MessageRouter`] could select
+/// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to
+/// become invalid over time as channels are closed. Thus, they are only suitable for short-term use.
+pub const MAX_SHORT_LIVED_RELATIVE_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
 
 /// Used by [`ChannelManager::list_recent_payments`] to express the status of recent payments.
 /// These include payments that have yet to find a successful path, or have unresolved HTLCs.
@@ -3698,8 +3383,11 @@ where
                Ok(counterparty_node_id)
        }
 
-       fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool) -> Result<(), APIError> {
+       fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool, error_message: String)
+       -> Result<(), APIError> {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
+               log_debug!(self.logger,
+                       "Force-closing channel, The error message sent to the peer : {}", error_message);
                match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None, broadcast) {
                        Ok(counterparty_node_id) => {
                                let per_peer_state = self.per_peer_state.read().unwrap();
@@ -3708,8 +3396,8 @@ where
                                        peer_state.pending_msg_events.push(
                                                events::MessageSendEvent::HandleError {
                                                        node_id: counterparty_node_id,
-                                                       action: msgs::ErrorAction::DisconnectPeer {
-                                                               msg: Some(msgs::ErrorMessage { channel_id: *channel_id, data: "Channel force-closed".to_owned() })
+                                                       action: msgs::ErrorAction::SendErrorMessage {
+                                                               msg: msgs::ErrorMessage { channel_id: *channel_id, data: error_message }
                                                        },
                                                }
                                        );
@@ -3720,39 +3408,53 @@ where
                }
        }
 
-       /// Force closes a channel, immediately broadcasting the latest local transaction(s) and
-       /// rejecting new HTLCs on the given channel. Fails if `channel_id` is unknown to
-       /// the manager, or if the `counterparty_node_id` isn't the counterparty of the corresponding
-       /// channel.
-       pub fn force_close_broadcasting_latest_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey)
+       /// Force closes a channel, immediately broadcasting the latest local transaction(s),
+       /// rejecting new HTLCs.
+       ///
+       /// The provided `error_message` is sent to connected peers for closing
+       /// channels and should be a human-readable description of what went wrong.
+       ///
+       /// Fails if `channel_id` is unknown to the manager, or if the `counterparty_node_id`
+       /// isn't the counterparty of the corresponding channel.
+       pub fn force_close_broadcasting_latest_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String)
        -> Result<(), APIError> {
-               self.force_close_sending_error(channel_id, counterparty_node_id, true)
+               self.force_close_sending_error(channel_id, counterparty_node_id, true, error_message)
        }
 
        /// Force closes a channel, rejecting new HTLCs on the given channel but skips broadcasting
-       /// the latest local transaction(s). Fails if `channel_id` is unknown to the manager, or if the
-       /// `counterparty_node_id` isn't the counterparty of the corresponding channel.
+       /// the latest local transaction(s).
        ///
+       /// The provided `error_message` is sent to connected peers for closing channels and should
+       /// be a human-readable description of what went wrong.
+       ///
+       /// Fails if `channel_id` is unknown to the manager, or if the
+       /// `counterparty_node_id` isn't the counterparty of the corresponding channel.
        /// You can always broadcast the latest local transaction(s) via
        /// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`].
-       pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey)
+       pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String)
        -> Result<(), APIError> {
-               self.force_close_sending_error(channel_id, counterparty_node_id, false)
+               self.force_close_sending_error(channel_id, counterparty_node_id, false, error_message)
        }
 
        /// Force close all channels, immediately broadcasting the latest local commitment transaction
        /// for each to the chain and rejecting new HTLCs on each.
-       pub fn force_close_all_channels_broadcasting_latest_txn(&self) {
+       ///
+       /// The provided `error_message` is sent to connected peers for closing channels and should
+       /// be a human-readable description of what went wrong.
+       pub fn force_close_all_channels_broadcasting_latest_txn(&self, error_message: String) {
                for chan in self.list_channels() {
-                       let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id);
+                       let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone());
                }
        }
 
        /// Force close all channels rejecting new HTLCs on each but without broadcasting the latest
        /// local transaction(s).
-       pub fn force_close_all_channels_without_broadcasting_txn(&self) {
+       ///
+       /// The provided `error_message` is sent to connected peers for closing channels and
+       /// should be a human-readable description of what went wrong.
+       pub fn force_close_all_channels_without_broadcasting_txn(&self, error_message: String) {
                for chan in self.list_channels() {
-                       let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id);
+                       let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone());
                }
        }
 
@@ -4633,7 +4335,7 @@ where
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
                let mut result = Ok(());
 
-               if !funding_transaction.is_coin_base() {
+               if !funding_transaction.is_coinbase() {
                        for inp in funding_transaction.input.iter() {
                                if inp.witness.is_empty() {
                                        result = result.and(Err(APIError::APIMisuseError {
@@ -4689,9 +4391,9 @@ where
                                is_batch_funding,
                                |chan, tx| {
                                        let mut output_index = None;
-                                       let expected_spk = chan.context.get_funding_redeemscript().to_v0_p2wsh();
+                                       let expected_spk = chan.context.get_funding_redeemscript().to_p2wsh();
                                        for (idx, outp) in tx.output.iter().enumerate() {
-                                               if outp.script_pubkey == expected_spk && outp.value == chan.context.get_value_satoshis() {
+                                               if outp.script_pubkey == expected_spk && outp.value.to_sat() == chan.context.get_value_satoshis() {
                                                        if output_index.is_some() {
                                                                return Err("Multiple outputs matched the expected script and value");
                                                        }
@@ -6325,19 +6027,27 @@ where
                                        }
                                }
 
-                               let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect();
-                               let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat);
-                               let dup_purpose = claimable_payments.pending_claiming_payments.insert(payment_hash,
-                                       ClaimingPayment { amount_msat: payment.htlcs.iter().map(|source| source.value).sum(),
-                                       payment_purpose: payment.purpose, receiver_node_id, htlcs, sender_intended_value
-                               });
-                               if dup_purpose.is_some() {
-                                       debug_assert!(false, "Shouldn't get a duplicate pending claim event ever");
-                                       log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug",
-                                               &payment_hash);
-                               }
+                               let claiming_payment = claimable_payments.pending_claiming_payments
+                                       .entry(payment_hash)
+                                       .and_modify(|_| {
+                                               debug_assert!(false, "Shouldn't get a duplicate pending claim event ever");
+                                               log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug",
+                                                       &payment_hash);
+                                       })
+                                       .or_insert_with(|| {
+                                               let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect();
+                                               let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat);
+                                               ClaimingPayment {
+                                                       amount_msat: payment.htlcs.iter().map(|source| source.value).sum(),
+                                                       payment_purpose: payment.purpose,
+                                                       receiver_node_id,
+                                                       htlcs,
+                                                       sender_intended_value,
+                                                       onion_fields: payment.onion_fields,
+                                               }
+                                       });
 
-                               if let Some(RecipientOnionFields { ref custom_tlvs, .. }) = payment.onion_fields {
+                               if let Some(RecipientOnionFields { ref custom_tlvs, .. }) = claiming_payment.onion_fields {
                                        if !custom_tlvs_known && custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
                                                log_info!(self.logger, "Rejecting payment with payment hash {} as we cannot accept payment with unknown even TLVs: {}",
                                                        &payment_hash, log_iter!(custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
@@ -6744,6 +6454,7 @@ where
                                                receiver_node_id,
                                                htlcs,
                                                sender_intended_value: sender_intended_total_msat,
+                                               onion_fields,
                                        }) = payment {
                                                self.pending_events.lock().unwrap().push_back((events::Event::PaymentClaimed {
                                                        payment_hash,
@@ -6752,6 +6463,7 @@ where
                                                        receiver_node_id: Some(receiver_node_id),
                                                        htlcs,
                                                        sender_intended_total_msat,
+                                                       onion_fields,
                                                }, None));
                                        }
                                },
@@ -7251,7 +6963,7 @@ where
                                        match phase.get_mut() {
                                                ChannelPhase::UnfundedOutboundV1(chan) => {
                                                        try_chan_phase_entry!(self, chan.accept_channel(&msg, &self.default_configuration.channel_handshake_limits, &peer_state.latest_features), phase);
-                                                       (chan.context.get_value_satoshis(), chan.context.get_funding_redeemscript().to_v0_p2wsh(), chan.context.get_user_id())
+                                                       (chan.context.get_value_satoshis(), chan.context.get_funding_redeemscript().to_p2wsh(), chan.context.get_user_id())
                                                },
                                                _ => {
                                                        return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got an unexpected accept_channel message from peer with counterparty_node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id));
@@ -8542,16 +8254,15 @@ where
 
 macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
        /// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
-       /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will
-       /// not have an expiration unless otherwise set on the builder.
+       /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer's
+       /// expiration will be `absolute_expiry` if `Some`, otherwise it will not expire.
        ///
        /// # Privacy
        ///
-       /// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the offer.
-       /// However, if one is not found, uses a one-hop [`BlindedPath`] with
-       /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
-       /// the node must be announced, otherwise, there is no way to find a path to the introduction in
-       /// order to send the [`InvoiceRequest`].
+       /// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the offer based on the given
+       /// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
+       /// privacy implications as well as those of the parameterized [`Router`], which implements
+       /// [`MessageRouter`].
        ///
        /// Also, uses a derived signing pubkey in the offer for recipient privacy.
        ///
@@ -8566,19 +8277,27 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
        ///
        /// [`Offer`]: crate::offers::offer::Offer
        /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
-       pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> {
+       pub fn create_offer_builder(
+               &$self, absolute_expiry: Option<Duration>
+       ) -> Result<$builder, Bolt12SemanticError> {
                let node_id = $self.get_our_node_id();
                let expanded_key = &$self.inbound_payment_key;
                let entropy = &*$self.entropy_source;
                let secp_ctx = &$self.secp_ctx;
 
-               let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
+               let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry)
+                       .map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = OfferBuilder::deriving_signing_pubkey(
                        node_id, expanded_key, entropy, secp_ctx
                )
                        .chain_hash($self.chain_hash)
                        .path(path);
 
+               let builder = match absolute_expiry {
+                       None => builder,
+                       Some(absolute_expiry) => builder.absolute_expiry(absolute_expiry),
+               };
+
                Ok(builder.into())
        }
 } }
@@ -8606,11 +8325,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
        ///
        /// # Privacy
        ///
-       /// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the refund.
-       /// However, if one is not found, uses a one-hop [`BlindedPath`] with
-       /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
-       /// the node must be announced, otherwise, there is no way to find a path to the introduction in
-       /// order to send the [`Bolt12Invoice`].
+       /// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the refund based on the given
+       /// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
+       /// privacy implications as well as those of the parameterized [`Router`], which implements
+       /// [`MessageRouter`].
        ///
        /// Also, uses a derived payer id in the refund for payer privacy.
        ///
@@ -8639,7 +8357,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
                let entropy = &*$self.entropy_source;
                let secp_ctx = &$self.secp_ctx;
 
-               let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
+               let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry))
+                       .map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = RefundBuilder::deriving_payer_id(
                        node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
                )?
@@ -8708,10 +8427,9 @@ where
        ///
        /// # Privacy
        ///
-       /// Uses a one-hop [`BlindedPath`] for the reply path with [`ChannelManager::get_our_node_id`]
-       /// as the introduction node and a derived payer id for payer privacy. As such, currently, the
-       /// node must be announced. Otherwise, there is no way to find a path to the introduction node
-       /// in order to send the [`Bolt12Invoice`].
+       /// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
+       /// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
+       /// docs of the parameterized [`Router`], which implements [`MessageRouter`].
        ///
        /// # Limitations
        ///
@@ -8988,6 +8706,38 @@ where
                inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
        }
 
+       /// Creates a blinded path by delegating to [`MessageRouter`] based on the path's intended
+       /// lifetime.
+       ///
+       /// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
+       /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
+       /// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
+       fn create_blinded_path_using_absolute_expiry(
+               &self, absolute_expiry: Option<Duration>
+       ) -> Result<BlindedPath, ()> {
+               let now = self.duration_since_epoch();
+               let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
+
+               if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
+                       self.create_compact_blinded_path()
+               } else {
+                       self.create_blinded_path()
+               }
+       }
+
+       pub(super) fn duration_since_epoch(&self) -> Duration {
+               #[cfg(not(feature = "std"))]
+               let now = Duration::from_secs(
+                       self.highest_seen_timestamp.load(Ordering::Acquire) as u64
+               );
+               #[cfg(feature = "std")]
+               let now = std::time::SystemTime::now()
+                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
+                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
+
+               now
+       }
+
        /// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
        ///
        /// Errors if the `MessageRouter` errors or returns an empty `Vec`.
@@ -8998,6 +8748,27 @@ where
                let peers = self.per_peer_state.read().unwrap()
                        .iter()
                        .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap()))
+                       .filter(|(_, peer)| peer.is_connected)
+                       .filter(|(_, peer)| peer.latest_features.supports_onion_messages())
+                       .map(|(node_id, _)| *node_id)
+                       .collect::<Vec<_>>();
+
+               self.router
+                       .create_blinded_paths(recipient, peers, secp_ctx)
+                       .and_then(|paths| paths.into_iter().next().ok_or(()))
+       }
+
+       /// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
+       ///
+       /// Errors if the `MessageRouter` errors or returns an empty `Vec`.
+       fn create_compact_blinded_path(&self) -> Result<BlindedPath, ()> {
+               let recipient = self.get_our_node_id();
+               let secp_ctx = &self.secp_ctx;
+
+               let peers = self.per_peer_state.read().unwrap()
+                       .iter()
+                       .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap()))
+                       .filter(|(_, peer)| peer.is_connected)
                        .filter(|(_, peer)| peer.latest_features.supports_onion_messages())
                        .map(|(node_id, peer)| ForwardNode {
                                node_id: *node_id,
@@ -9010,7 +8781,7 @@ where
                        .collect::<Vec<_>>();
 
                self.router
-                       .create_blinded_paths(recipient, peers, secp_ctx)
+                       .create_compact_blinded_paths(recipient, peers, secp_ctx)
                        .and_then(|paths| paths.into_iter().next().ok_or(()))
        }
 
@@ -10576,140 +10347,6 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl_writeable_tlv_based!(CounterpartyForwardingInfo, {
-       (2, fee_base_msat, required),
-       (4, fee_proportional_millionths, required),
-       (6, cltv_expiry_delta, required),
-});
-
-impl_writeable_tlv_based!(ChannelCounterparty, {
-       (2, node_id, required),
-       (4, features, required),
-       (6, unspendable_punishment_reserve, required),
-       (8, forwarding_info, option),
-       (9, outbound_htlc_minimum_msat, option),
-       (11, outbound_htlc_maximum_msat, option),
-});
-
-impl Writeable for ChannelDetails {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
-               // `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
-               // versions prior to 0.0.113, the u128 is serialized as two separate u64 values.
-               let user_channel_id_low = self.user_channel_id as u64;
-               let user_channel_id_high_opt = Some((self.user_channel_id >> 64) as u64);
-               write_tlv_fields!(writer, {
-                       (1, self.inbound_scid_alias, option),
-                       (2, self.channel_id, required),
-                       (3, self.channel_type, option),
-                       (4, self.counterparty, required),
-                       (5, self.outbound_scid_alias, option),
-                       (6, self.funding_txo, option),
-                       (7, self.config, option),
-                       (8, self.short_channel_id, option),
-                       (9, self.confirmations, option),
-                       (10, self.channel_value_satoshis, required),
-                       (12, self.unspendable_punishment_reserve, option),
-                       (14, user_channel_id_low, required),
-                       (16, self.balance_msat, required),
-                       (18, self.outbound_capacity_msat, required),
-                       (19, self.next_outbound_htlc_limit_msat, required),
-                       (20, self.inbound_capacity_msat, required),
-                       (21, self.next_outbound_htlc_minimum_msat, required),
-                       (22, self.confirmations_required, option),
-                       (24, self.force_close_spend_delay, option),
-                       (26, self.is_outbound, required),
-                       (28, self.is_channel_ready, required),
-                       (30, self.is_usable, required),
-                       (32, self.is_public, required),
-                       (33, self.inbound_htlc_minimum_msat, option),
-                       (35, self.inbound_htlc_maximum_msat, option),
-                       (37, user_channel_id_high_opt, option),
-                       (39, self.feerate_sat_per_1000_weight, option),
-                       (41, self.channel_shutdown_state, option),
-                       (43, self.pending_inbound_htlcs, optional_vec),
-                       (45, self.pending_outbound_htlcs, optional_vec),
-               });
-               Ok(())
-       }
-}
-
-impl Readable for ChannelDetails {
-       fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               _init_and_read_len_prefixed_tlv_fields!(reader, {
-                       (1, inbound_scid_alias, option),
-                       (2, channel_id, required),
-                       (3, channel_type, option),
-                       (4, counterparty, required),
-                       (5, outbound_scid_alias, option),
-                       (6, funding_txo, option),
-                       (7, config, option),
-                       (8, short_channel_id, option),
-                       (9, confirmations, option),
-                       (10, channel_value_satoshis, required),
-                       (12, unspendable_punishment_reserve, option),
-                       (14, user_channel_id_low, required),
-                       (16, balance_msat, required),
-                       (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() as u64)),
-                       (20, inbound_capacity_msat, required),
-                       (21, next_outbound_htlc_minimum_msat, (default_value, 0)),
-                       (22, confirmations_required, option),
-                       (24, force_close_spend_delay, option),
-                       (26, is_outbound, required),
-                       (28, is_channel_ready, required),
-                       (30, is_usable, required),
-                       (32, is_public, required),
-                       (33, inbound_htlc_minimum_msat, option),
-                       (35, inbound_htlc_maximum_msat, option),
-                       (37, user_channel_id_high_opt, option),
-                       (39, feerate_sat_per_1000_weight, option),
-                       (41, channel_shutdown_state, option),
-                       (43, pending_inbound_htlcs, optional_vec),
-                       (45, pending_outbound_htlcs, optional_vec),
-               });
-
-               // `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
-               // versions prior to 0.0.113, the u128 is serialized as two separate u64 values.
-               let user_channel_id_low: u64 = user_channel_id_low.0.unwrap();
-               let user_channel_id = user_channel_id_low as u128 +
-                       ((user_channel_id_high_opt.unwrap_or(0 as u64) as u128) << 64);
-
-               Ok(Self {
-                       inbound_scid_alias,
-                       channel_id: channel_id.0.unwrap(),
-                       channel_type,
-                       counterparty: counterparty.0.unwrap(),
-                       outbound_scid_alias,
-                       funding_txo,
-                       config,
-                       short_channel_id,
-                       channel_value_satoshis: channel_value_satoshis.0.unwrap(),
-                       unspendable_punishment_reserve,
-                       user_channel_id,
-                       balance_msat: balance_msat.0.unwrap(),
-                       outbound_capacity_msat: outbound_capacity_msat.0.unwrap(),
-                       next_outbound_htlc_limit_msat: next_outbound_htlc_limit_msat.0.unwrap(),
-                       next_outbound_htlc_minimum_msat: next_outbound_htlc_minimum_msat.0.unwrap(),
-                       inbound_capacity_msat: inbound_capacity_msat.0.unwrap(),
-                       confirmations_required,
-                       confirmations,
-                       force_close_spend_delay,
-                       is_outbound: is_outbound.0.unwrap(),
-                       is_channel_ready: is_channel_ready.0.unwrap(),
-                       is_usable: is_usable.0.unwrap(),
-                       is_public: is_public.0.unwrap(),
-                       inbound_htlc_minimum_msat,
-                       inbound_htlc_maximum_msat,
-                       feerate_sat_per_1000_weight,
-                       channel_shutdown_state,
-                       pending_inbound_htlcs: pending_inbound_htlcs.unwrap_or(Vec::new()),
-                       pending_outbound_htlcs: pending_outbound_htlcs.unwrap_or(Vec::new()),
-               })
-       }
-}
-
 impl_writeable_tlv_based!(PhantomRouteHints, {
        (2, channels, required_vec),
        (4, phantom_scid, required),
@@ -11344,14 +10981,6 @@ impl Readable for VecDeque<(Event, Option<EventCompletionAction>)> {
        }
 }
 
-impl_writeable_tlv_based_enum!(ChannelShutdownState,
-       (0, NotShuttingDown) => {},
-       (2, ShutdownInitiated) => {},
-       (4, ResolvingHTLCs) => {},
-       (6, NegotiatingClosingFee) => {},
-       (8, ShutdownComplete) => {}, ;
-);
-
 /// Arguments for the creation of a ChannelManager that are not deserialized.
 ///
 /// At a high-level, the process for deserializing a ChannelManager and resuming normal operation
@@ -12273,6 +11902,7 @@ where
                                                amount_msat: claimable_amt_msat,
                                                htlcs: payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(),
                                                sender_intended_total_msat: payment.htlcs.first().map(|htlc| htlc.total_msat),
+                                               onion_fields: payment.onion_fields,
                                        }, None));
                                }
                        }
@@ -12956,8 +12586,8 @@ mod tests {
 
                nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
                nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
-
-               nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_broadcast!(nodes[0], true);
                check_added_monitors!(nodes[0], 1);
                check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
@@ -13174,6 +12804,7 @@ mod tests {
                let channel_id = ChannelId::from_bytes([4; 32]);
                let unkown_public_key = PublicKey::from_secret_key(&Secp256k1::signing_only(), &SecretKey::from_slice(&[42; 32]).unwrap());
                let intercept_id = InterceptId([0; 32]);
+               let error_message = "Channel force-closed";
 
                // Test the API functions.
                check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None, None), unkown_public_key);
@@ -13182,9 +12813,9 @@ mod tests {
 
                check_unkown_peer_error(nodes[0].node.close_channel(&channel_id, &unkown_public_key), unkown_public_key);
 
-               check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key), unkown_public_key);
+               check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key);
 
-               check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), unkown_public_key);
+               check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key);
 
                check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key);
 
@@ -13206,15 +12837,16 @@ mod tests {
 
                // Dummy values
                let channel_id = ChannelId::from_bytes([4; 32]);
+               let error_message = "Channel force-closed";
 
                // Test the API functions.
                check_api_misuse_error(nodes[0].node.accept_inbound_channel(&channel_id, &counterparty_node_id, 42));
 
                check_channel_unavailable_error(nodes[0].node.close_channel(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
 
-               check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
+               check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id);
 
-               check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
+               check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id);
 
                check_channel_unavailable_error(nodes[0].node.forward_intercepted_htlc(InterceptId([0; 32]), &channel_id, counterparty_node_id, 1_000_000), channel_id, counterparty_node_id);
 
@@ -13568,6 +13200,7 @@ mod tests {
                anchors_config.manually_accept_inbound_channels = true;
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+               let error_message = "Channel force-closed";
 
                nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap();
                let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
@@ -13577,7 +13210,7 @@ mod tests {
                let events = nodes[1].node.get_and_clear_pending_events();
                match events[0] {
                        Event::OpenChannelRequest { temporary_channel_id, .. } => {
-                               nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id()).unwrap();
+                               nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                        }
                        _ => panic!("Unexpected event"),
                }
@@ -13685,12 +13318,13 @@ mod tests {
                let user_config = test_default_channel_config();
                let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[Some(user_config), Some(user_config)]);
                let nodes = create_network(2, &node_cfg, &node_chanmgr);
+               let error_message = "Channel force-closed";
 
                // Open a channel, immediately disconnect each other, and broadcast Alice's latest state.
                let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
                nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
                nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
-               nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+               nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_broadcast(&nodes[0], 1, true);
                check_added_monitors(&nodes[0], 1);
                check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
@@ -13811,10 +13445,12 @@ pub mod bench {
        use crate::util::test_utils;
        use crate::util::config::{UserConfig, MaxDustHTLCExposure};
 
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::locktime::absolute::LockTime;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::{Transaction, TxOut};
+       use bitcoin::transaction::Version;
 
        use crate::sync::{Arc, Mutex, RwLock};
 
@@ -13891,8 +13527,8 @@ pub mod bench {
 
                let tx;
                if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) {
-                       tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                               value: 8_000_000, script_pubkey: output_script,
+                       tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                               value: Amount::from_sat(8_000_000), script_pubkey: output_script,
                        }]};
                        node_a.funding_transaction_generated(&temporary_channel_id, &node_b.get_our_node_id(), tx.clone()).unwrap();
                } else { panic!(); }
index ff91654a3f79a33f2ed42cf9d2d4017ebde8fbae..51c608c1a6b47231762bbb35627032dcf33d19bc 100644 (file)
@@ -87,8 +87,7 @@ use core::borrow::Borrow;
 use core::hash::{Hash, Hasher};
 use core::marker::PhantomData;
 
-use bitcoin::bech32;
-use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32};
+use bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32};
 use crate::ln::msgs::DecodeError;
 use crate::util::ser::{Readable, WithoutLength, Writeable, Writer};
 
@@ -443,6 +442,9 @@ mod sealed {
                set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature);
 }
 
+const ANY_REQUIRED_FEATURES_MASK: u8 = 0b01_01_01_01;
+const ANY_OPTIONAL_FEATURES_MASK: u8 = 0b10_10_10_10;
+
 /// Tracks the set of features which a node implements, templated by the context in which it
 /// appears.
 ///
@@ -616,8 +618,8 @@ impl ChannelTypeFeatures {
                // ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
                // optional bits and then AND out the optional ones.
                for byte in ret.flags.iter_mut() {
-                       *byte |= (*byte & 0b10_10_10_10) >> 1;
-                       *byte &= 0b01_01_01_01;
+                       *byte |= (*byte & ANY_OPTIONAL_FEATURES_MASK) >> 1;
+                       *byte &= ANY_REQUIRED_FEATURES_MASK;
                }
                ret
        }
@@ -762,7 +764,7 @@ impl<T: sealed::Context> Features<T> {
        }
 
        pub(crate) fn supports_any_optional_bits(&self) -> bool {
-               self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
+               self.flags.iter().any(|&byte| (byte & ANY_OPTIONAL_FEATURES_MASK) != 0)
        }
 
        /// Returns true if this `Features` object contains required features unknown by `other`.
@@ -770,20 +772,30 @@ impl<T: sealed::Context> Features<T> {
                // Bitwise AND-ing with all even bits set except for known features will select required
                // unknown features.
                self.flags.iter().enumerate().any(|(i, &byte)| {
-                       const REQUIRED_FEATURES: u8 = 0b01_01_01_01;
-                       const OPTIONAL_FEATURES: u8 = 0b10_10_10_10;
-                       let unknown_features = if i < other.flags.len() {
-                               // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
-                               !(other.flags[i]
-                                       | ((other.flags[i] >> 1) & REQUIRED_FEATURES)
-                                       | ((other.flags[i] << 1) & OPTIONAL_FEATURES))
-                       } else {
-                               0b11_11_11_11
-                       };
-                       (byte & (REQUIRED_FEATURES & unknown_features)) != 0
+                       let unknown_features = unset_features_mask_at_position(other, i);
+                       (byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
                })
        }
 
+       pub(crate) fn required_unknown_bits_from(&self, other: &Self) -> Vec<usize> {
+               let mut unknown_bits = Vec::new();
+
+               // Bitwise AND-ing with all even bits set except for known features will select required
+               // unknown features.
+               self.flags.iter().enumerate().for_each(|(i, &byte)| {
+                       let unknown_features = unset_features_mask_at_position(other, i);
+                       if byte & unknown_features != 0 {
+                               for bit in (0..8).step_by(2) {
+                                       if ((byte & unknown_features) >> bit) & 1 == 1 {
+                                               unknown_bits.push(i * 8 + bit);
+                                       }
+                               }
+                       }
+               });
+
+               unknown_bits
+       }
+
        /// Returns true if this `Features` object contains unknown feature flags which are set as
        /// "required".
        pub fn requires_unknown_bits(&self) -> bool {
@@ -791,13 +803,12 @@ impl<T: sealed::Context> Features<T> {
                // unknown features.
                let byte_count = T::KNOWN_FEATURE_MASK.len();
                self.flags.iter().enumerate().any(|(i, &byte)| {
-                       let required_features = 0b01_01_01_01;
                        let unknown_features = if i < byte_count {
                                !T::KNOWN_FEATURE_MASK[i]
                        } else {
                                0b11_11_11_11
                        };
-                       (byte & (required_features & unknown_features)) != 0
+                       (byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
                })
        }
 
@@ -1018,10 +1029,21 @@ impl<T: sealed::Context> Readable for WithoutLength<Features<T>> {
        }
 }
 
+pub(crate) fn unset_features_mask_at_position<T: sealed::Context>(other: &Features<T>, index: usize) -> u8 {
+       if index < other.flags.len() {
+               // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
+               !(other.flags[index]
+                       | ((other.flags[index] >> 1) & ANY_REQUIRED_FEATURES_MASK)
+                       | ((other.flags[index] << 1) & ANY_OPTIONAL_FEATURES_MASK))
+       } else {
+               0b11_11_11_11
+       }
+}
+
 #[cfg(test)]
 mod tests {
        use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, Bolt11InvoiceFeatures, NodeFeatures, OfferFeatures, sealed};
-       use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
+       use bech32::{Base32Len, FromBase32, ToBase32, u5};
        use crate::util::ser::{Readable, WithoutLength, Writeable};
 
        #[test]
@@ -1034,11 +1056,24 @@ mod tests {
                features.set_unknown_feature_required();
                assert!(features.requires_unknown_bits());
                assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456788]);
 
                let mut features = ChannelFeatures::empty();
                features.set_unknown_feature_optional();
                assert!(!features.requires_unknown_bits());
                assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![]);
+
+               let mut features = ChannelFeatures::empty();
+               features.set_unknown_feature_required();
+               features.set_custom_bit(123456786).unwrap();
+               assert!(features.requires_unknown_bits());
+               assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456786, 123456788]);
+
+               let mut limiter = ChannelFeatures::empty();
+               limiter.set_unknown_feature_optional();
+               assert_eq!(features.required_unknown_bits_from(&limiter), vec![123456786]);
        }
 
        #[test]
index cbb2b0f2197c18ef34490d703026cffa706853d2..7e57f20595a5b05630ace9de66b6a854043c7f56 100644 (file)
@@ -35,15 +35,17 @@ use crate::util::test_utils;
 use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface};
 use crate::util::ser::{ReadableArgs, Writeable};
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::block::{Block, Header, Version};
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
 use bitcoin::hash_types::{BlockHash, TxMerkleNode};
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::Hash as _;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::pow::CompactTarget;
 use bitcoin::secp256k1::{PublicKey, SecretKey};
+use bitcoin::transaction;
 
 use alloc::rc::Rc;
 use core::cell::RefCell;
@@ -95,7 +97,7 @@ pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Nod
                txdata: Vec::new(),
        };
        for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
-               block.txdata.push(Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
+               block.txdata.push(Transaction { version: transaction::Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
        }
        block.txdata.push((*tx).clone());
        do_connect_block_without_consistency_checks(node, block, false);
@@ -113,7 +115,7 @@ pub fn confirm_transactions_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn:
        }
        let mut txdata = Vec::new();
        for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
-               txdata.push(Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
+               txdata.push(Transaction { version: transaction::Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
        }
        for tx in txn {
                txdata.push((*tx).clone());
@@ -1155,8 +1157,8 @@ fn internal_create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>,
                                Vec::new()
                        };
 
-                       let tx = Transaction { version: chan_id as i32, lock_time: LockTime::ZERO, input, output: vec![TxOut {
-                               value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                       let tx = Transaction { version: transaction::Version(chan_id as i32), lock_time: LockTime::ZERO, input, output: vec![TxOut {
+                               value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(),
                        }]};
                        let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
                        (*temporary_channel_id, tx, funding_outpoint)
@@ -1476,15 +1478,15 @@ pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, '
 
 pub fn do_check_spends<F: Fn(&bitcoin::blockdata::transaction::OutPoint) -> Option<TxOut>>(tx: &Transaction, get_output: F) {
        for outp in tx.output.iter() {
-               assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Spending tx output didn't meet dust limit");
+               assert!(outp.value >= outp.script_pubkey.dust_value(), "Spending tx output didn't meet dust limit");
        }
        let mut total_value_in = 0;
        for input in tx.input.iter() {
-               total_value_in += get_output(&input.previous_output).unwrap().value;
+               total_value_in += get_output(&input.previous_output).unwrap().value.to_sat();
        }
        let mut total_value_out = 0;
        for output in tx.output.iter() {
-               total_value_out += output.value;
+               total_value_out += output.value.to_sat();
        }
        let min_fee = (tx.weight().to_wu() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up)
        // Input amount - output amount = fee, so check that out + min_fee is smaller than input
@@ -1498,7 +1500,7 @@ macro_rules! check_spends {
                {
                        $(
                        for outp in $spends_txn.output.iter() {
-                               assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Input tx output didn't meet dust limit");
+                               assert!(outp.value >= outp.script_pubkey.dust_value(), "Input tx output didn't meet dust limit");
                        }
                        )*
                        let get_output = |out_point: &bitcoin::blockdata::transaction::OutPoint| {
@@ -2065,7 +2067,7 @@ macro_rules! get_payment_preimage_hash {
 /// Gets a route from the given sender to the node described in `payment_params`.
 pub fn get_route(send_node: &Node, route_params: &RouteParameters) -> Result<Route, msgs::LightningError> {
        let scorer = TestScorer::new();
-       let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
+       let keys_manager = TestKeysInterface::new(&[0u8; 32], Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
        router::get_route(
                &send_node.node.get_our_node_id(), route_params, &send_node.network_graph.read_only(),
@@ -2077,7 +2079,7 @@ pub fn get_route(send_node: &Node, route_params: &RouteParameters) -> Result<Rou
 /// Like `get_route` above, but adds a random CLTV offset to the final hop.
 pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result<Route, msgs::LightningError> {
        let scorer = TestScorer::new();
-       let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
+       let keys_manager = TestKeysInterface::new(&[0u8; 32], Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
        router::find_route(
                &send_node.node.get_our_node_id(), route_params, &send_node.network_graph,
@@ -2453,18 +2455,11 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
                        if let Some(chan_closed) = conditions.expected_blamed_chan_closed {
                                if let PathFailure::OnPath { network_update: Some(upd) } = failure {
                                        match upd {
-                                               NetworkUpdate::ChannelUpdateMessage { ref msg } if !chan_closed => {
-                                                       if let Some(scid) = conditions.expected_blamed_scid {
-                                                               assert_eq!(msg.contents.short_channel_id, scid);
-                                                       }
-                                                       const CHAN_DISABLED_FLAG: u8 = 2;
-                                                       assert_eq!(msg.contents.flags & CHAN_DISABLED_FLAG, 0);
-                                               },
-                                               NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } if chan_closed => {
+                                               NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } => {
                                                        if let Some(scid) = conditions.expected_blamed_scid {
                                                                assert_eq!(*short_channel_id, scid);
                                                        }
-                                                       assert!(is_permanent);
+                                                       assert_eq!(*is_permanent, chan_closed);
                                                },
                                                _ => panic!("Unexpected update type"),
                                        }
@@ -2716,18 +2711,12 @@ pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route
        (our_payment_preimage, our_payment_hash, our_payment_secret, payment_id)
 }
 
-pub fn do_claim_payment_along_route<'a, 'b, 'c>(
-       origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool,
-       our_payment_preimage: PaymentPreimage
-) -> u64 {
-       for path in expected_paths.iter() {
-               assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id());
+pub fn do_claim_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
+       for path in args.expected_paths.iter() {
+               assert_eq!(path.last().unwrap().node.get_our_node_id(), args.expected_paths[0].last().unwrap().node.get_our_node_id());
        }
-       expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage);
-       pass_claimed_payment_along_route(
-               ClaimAlongRouteArgs::new(origin_node, expected_paths, our_payment_preimage)
-                       .skip_last(skip_last)
-       )
+       args.expected_paths[0].last().unwrap().node.claim_funds(args.payment_preimage);
+       pass_claimed_payment_along_route(args)
 }
 
 pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
@@ -2737,6 +2726,7 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
        pub expected_min_htlc_overpay: Vec<u32>,
        pub skip_last: bool,
        pub payment_preimage: PaymentPreimage,
+       pub custom_tlvs: Vec<(u64, Vec<u8>)>,
        // Allow forwarding nodes to have taken 1 msat more fee than expected based on the downstream
        // fulfill amount.
        //
@@ -2755,7 +2745,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
                Self {
                        origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()],
                        expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage,
-                       allow_1_msat_fee_overpay: false,
+                       allow_1_msat_fee_overpay: false, custom_tlvs: vec![],
                }
        }
        pub fn skip_last(mut self, skip_last: bool) -> Self {
@@ -2774,12 +2764,16 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
                self.allow_1_msat_fee_overpay = true;
                self
        }
+       pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
+               self.custom_tlvs = custom_tlvs;
+               self
+       }
 }
 
-pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArgs) -> u64 {
+pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
        let ClaimAlongRouteArgs {
                origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
-               payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay,
+               payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, custom_tlvs,
        } = args;
        let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events();
        assert_eq!(claim_event.len(), 1);
@@ -2793,11 +2787,13 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
                                | PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(preimage), .. },
                        amount_msat,
                        ref htlcs,
+                       ref onion_fields,
                        ..
                } => {
                        assert_eq!(preimage, our_payment_preimage);
                        assert_eq!(htlcs.len(), expected_paths.len());  // One per path.
                        assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
+                       assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
                        expected_paths.iter().zip(htlcs).for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc));
                        fwd_amt_msat = amount_msat;
                },
@@ -2808,11 +2804,13 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
                        payment_hash,
                        amount_msat,
                        ref htlcs,
+                       ref onion_fields,
                        ..
                } => {
                        assert_eq!(&payment_hash.0, &Sha256::hash(&our_payment_preimage.0)[..]);
                        assert_eq!(htlcs.len(), expected_paths.len());  // One per path.
                        assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
+                       assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
                        expected_paths.iter().zip(htlcs).for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc));
                        fwd_amt_msat = amount_msat;
                }
@@ -2956,15 +2954,20 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
 
        expected_total_fee_msat
 }
-pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) {
-       let expected_total_fee_msat = do_claim_payment_along_route(origin_node, expected_paths, skip_last, our_payment_preimage);
+pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) {
+       let origin_node = args.origin_node;
+       let payment_preimage = args.payment_preimage;
+       let skip_last = args.skip_last;
+       let expected_total_fee_msat = do_claim_payment_along_route(args);
        if !skip_last {
-               expect_payment_sent!(origin_node, our_payment_preimage, Some(expected_total_fee_msat));
+               expect_payment_sent!(origin_node, payment_preimage, Some(expected_total_fee_msat));
        }
 }
 
 pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {
-       claim_payment_along_route(origin_node, &[expected_route], false, our_payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(origin_node, &[expected_route], our_payment_preimage)
+       );
 }
 
 pub const TEST_FINAL_CLTV: u32 = 70;
@@ -3249,30 +3252,34 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
 
        for i in 0..node_count {
                for j in (i+1)..node_count {
-                       let node_id_i = nodes[i].node.get_our_node_id();
-                       let node_id_j = nodes[j].node.get_our_node_id();
-
-                       let init_i = msgs::Init {
-                               features: nodes[i].init_features(&node_id_j),
-                               networks: None,
-                               remote_network_address: None,
-                       };
-                       let init_j = msgs::Init {
-                               features: nodes[j].init_features(&node_id_i),
-                               networks: None,
-                               remote_network_address: None,
-                       };
-
-                       nodes[i].node.peer_connected(&node_id_j, &init_j, true).unwrap();
-                       nodes[j].node.peer_connected(&node_id_i, &init_i, false).unwrap();
-                       nodes[i].onion_messenger.peer_connected(&node_id_j, &init_j, true).unwrap();
-                       nodes[j].onion_messenger.peer_connected(&node_id_i, &init_i, false).unwrap();
+                       connect_nodes(&nodes[i], &nodes[j]);
                }
        }
 
        nodes
 }
 
+fn connect_nodes<'a, 'b: 'a, 'c: 'b>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>) {
+       let node_id_a = node_a.node.get_our_node_id();
+       let node_id_b = node_b.node.get_our_node_id();
+
+       let init_a = msgs::Init {
+               features: node_a.init_features(&node_id_b),
+               networks: None,
+               remote_network_address: None,
+       };
+       let init_b = msgs::Init {
+               features: node_b.init_features(&node_id_a),
+               networks: None,
+               remote_network_address: None,
+       };
+
+       node_a.node.peer_connected(&node_id_b, &init_b, true).unwrap();
+       node_b.node.peer_connected(&node_id_a, &init_a, false).unwrap();
+       node_a.onion_messenger.peer_connected(&node_id_b, &init_b, true).unwrap();
+       node_b.onion_messenger.peer_connected(&node_id_a, &init_a, false).unwrap();
+}
+
 pub fn connect_dummy_node<'a, 'b: 'a, 'c: 'b>(node: &Node<'a, 'b, 'c>) {
        let node_id_dummy = PublicKey::from_slice(&[2; 33]).unwrap();
 
@@ -3633,13 +3640,8 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
                pending_cell_htlc_claims, pending_cell_htlc_fails, pending_raa,
                pending_responding_commitment_signed, pending_responding_commitment_signed_dup_monitor,
        } = args;
-       node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init {
-               features: node_b.node.init_features(), networks: None, remote_network_address: None
-       }, true).unwrap();
+       connect_nodes(node_a, node_b);
        let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b);
-       node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init {
-               features: node_a.node.init_features(), networks: None, remote_network_address: None
-       }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a);
 
        if send_channel_ready.0 {
@@ -3853,7 +3855,7 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>(
                                assert_eq!(channel_value_satoshis, event_channel_value_satoshis);
                                assert_eq!(user_channel_id, event_user_channel_id);
                                tx_outs.push(TxOut {
-                                       value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                                       value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(),
                                });
                        },
                        _ => panic!("Unexpected event"),
@@ -3863,7 +3865,7 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>(
 
        // Compose the batch funding transaction and give it to the ChannelManager.
        let tx = Transaction {
-               version: 2,
+               version: transaction::Version::TWO,
                lock_time: LockTime::ZERO,
                input: Vec::new(),
                output: tx_outs,
index 3f9e263fcf7c19a5bf460f7d7c12387b8407ec91..7cd0f376d2e431d1fe8fe56c5353d281dbf28e55 100644 (file)
@@ -42,9 +42,10 @@ use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::script::{Builder, ScriptBuf};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
-use bitcoin::{Sequence, Transaction, TxIn, TxOut, Witness};
+use bitcoin::network::Network;
+use bitcoin::{Amount, Sequence, Transaction, TxIn, TxOut, Witness};
 use bitcoin::OutPoint as BitcoinOutPoint;
+use bitcoin::transaction::Version;
 
 use bitcoin::secp256k1::Secp256k1;
 use bitcoin::secp256k1::{PublicKey,SecretKey};
@@ -711,7 +712,7 @@ fn test_update_fee_that_funder_cannot_afford() {
                //We made sure neither party's funds are below the dust limit and there are no HTLCs here
                assert_eq!(commitment_tx.output.len(), 2);
                let total_fee: u64 = commit_tx_fee_msat(feerate, 0, &channel_type_features) / 1000;
-               let mut actual_fee = commitment_tx.output.iter().fold(0, |acc, output| acc + output.value);
+               let mut actual_fee = commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat());
                actual_fee = channel_value - actual_fee;
                assert_eq!(total_fee, actual_fee);
        }
@@ -1325,9 +1326,9 @@ fn test_duplicate_htlc_different_direction_onchain() {
        assert_eq!(remote_txn[0].output.len(), 4); // 1 local, 1 remote, 1 htlc inbound, 1 htlc outbound
        let mut has_both_htlcs = 0; // check htlcs match ones committed
        for outp in remote_txn[0].output.iter() {
-               if outp.value == 800_000 / 1000 {
+               if outp.value.to_sat() == 800_000 / 1000 {
                        has_both_htlcs += 1;
-               } else if outp.value == 900_000 / 1000 {
+               } else if outp.value.to_sat() == 900_000 / 1000 {
                        has_both_htlcs += 1;
                }
        }
@@ -1356,12 +1357,12 @@ fn test_duplicate_htlc_different_direction_onchain() {
 
        assert_eq!(preimage_tx.input.len(), 1);
        assert_eq!(preimage_tx.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx
-       assert_eq!(remote_txn[0].output[preimage_tx.input[0].previous_output.vout as usize].value, 800);
+       assert_eq!(remote_txn[0].output[preimage_tx.input[0].previous_output.vout as usize].value.to_sat(), 800);
 
        assert_eq!(timeout_tx.input.len(), 1);
        assert_eq!(timeout_tx.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // HTLC 0 <--> 1, timeout tx
        check_spends!(timeout_tx, remote_txn[0]);
-       assert_eq!(remote_txn[0].output[timeout_tx.input[0].previous_output.vout as usize].value, 900);
+       assert_eq!(remote_txn[0].output[timeout_tx.input[0].previous_output.vout as usize].value.to_sat(), 900);
 
        let events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 3);
@@ -2302,7 +2303,8 @@ fn channel_monitor_network_test() {
        send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
 
        // Simple case with no pending HTLCs:
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors!(nodes[1], 1);
        check_closed_broadcast!(nodes[1], true);
        check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
@@ -2328,7 +2330,8 @@ fn channel_monitor_network_test() {
 
        // Simple case of one pending HTLC to HTLC-Timeout (note that the HTLC-Timeout is not
        // broadcasted until we reach the timelock time).
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[1], true);
        check_added_monitors!(nodes[1], 1);
        {
@@ -2368,7 +2371,8 @@ fn channel_monitor_network_test() {
 
        // nodes[3] gets the preimage, but nodes[2] already disconnected, resulting in a nodes[2]
        // HTLC-Timeout and a nodes[3] claim against it (+ its own announces)
-       nodes[2].node.force_close_broadcasting_latest_txn(&chan_3.2, &nodes[3].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[2].node.force_close_broadcasting_latest_txn(&chan_3.2, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors!(nodes[2], 1);
        check_closed_broadcast!(nodes[2], true);
        let node2_commitment_txid;
@@ -2678,8 +2682,8 @@ fn do_test_forming_justice_tx_from_monitor_updates(broadcast_initial_commitment:
                }
        });
        // On the first commitment, node[1]'s balance was below dust so it didn't have an output
-       let node1_channel_balance = if broadcast_initial_commitment { 0 } else { revoked_commitment_tx.output[0].value };
-       let expected_claimable_balance = node1_channel_balance + justice_tx.output[0].value;
+       let node1_channel_balance = if broadcast_initial_commitment { 0 } else { revoked_commitment_tx.output[0].value.to_sat() };
+       let expected_claimable_balance = node1_channel_balance + justice_tx.output[0].value.to_sat();
        assert_eq!(total_claimable_balance, expected_claimable_balance);
 }
 
@@ -2899,8 +2903,8 @@ fn test_htlc_on_chain_success() {
        check_spends!(node_txn[1], commitment_tx[0]);
        assert_eq!(node_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
        assert_eq!(node_txn[1].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
-       assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
-       assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
+       assert!(node_txn[0].output[0].script_pubkey.is_p2wsh()); // revokeable output
+       assert!(node_txn[1].output[0].script_pubkey.is_p2wsh()); // revokeable output
        assert_eq!(node_txn[0].lock_time, LockTime::ZERO);
        assert_eq!(node_txn[1].lock_time, LockTime::ZERO);
 
@@ -2992,13 +2996,13 @@ fn test_htlc_on_chain_success() {
                        if $htlc_offered {
                                assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
                                assert_eq!(node_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
-                               assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
-                               assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
+                               assert!(node_txn[0].output[0].script_pubkey.is_p2wsh()); // revokeable output
+                               assert!(node_txn[1].output[0].script_pubkey.is_p2wsh()); // revokeable output
                        } else {
                                assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
                                assert_eq!(node_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
-                               assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
-                               assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
+                               assert!(node_txn[0].output[0].script_pubkey.is_p2wpkh()); // direct payment
+                               assert!(node_txn[1].output[0].script_pubkey.is_p2wpkh()); // direct payment
                        }
                        node_txn.clear();
                } }
@@ -3040,7 +3044,7 @@ fn test_htlc_on_chain_success() {
        assert_eq!(commitment_spend.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
        assert_eq!(commitment_spend.input[1].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
        assert_eq!(commitment_spend.lock_time.to_consensus_u32(), nodes[1].best_block_info().1);
-       assert!(commitment_spend.output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
+       assert!(commitment_spend.output[0].script_pubkey.is_p2wpkh()); // direct payment
        // We don't bother to check that B can claim the HTLC output on its commitment tx here as
        // we already checked the same situation with A.
 
@@ -3595,9 +3599,9 @@ fn test_htlc_ignore_latest_remote_commitment() {
                return;
        }
        let funding_tx = create_announced_chan_between_nodes(&nodes, 0, 1).3;
-
+       let error_message = "Channel force-closed";
        route_payment(&nodes[0], &[&nodes[1]], 10000000);
-       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
        check_closed_broadcast!(nodes[0], true);
        check_added_monitors!(nodes[0], 1);
@@ -3660,8 +3664,8 @@ fn test_force_close_fail_back() {
        // nodes[2] now has the latest commitment transaction, but hasn't revoked its previous
        // state or updated nodes[1]' state. Now force-close and broadcast that commitment/HTLC
        // transaction and ensure nodes[1] doesn't fail-backwards (this was originally a bug!).
-
-       nodes[2].node.force_close_broadcasting_latest_txn(&payment_event.commitment_msg.channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[2].node.force_close_broadcasting_latest_txn(&payment_event.commitment_msg.channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[2], true);
        check_added_monitors!(nodes[2], 1);
        check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
@@ -3812,7 +3816,10 @@ fn test_simple_peer_disconnect() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_preimage_3);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage_3)
+                       .skip_last(true)
+       );
        fail_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_hash_5);
 
        let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
@@ -4539,7 +4546,8 @@ fn test_claim_sizeable_push_msat() {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000);
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[1], true);
        check_added_monitors!(nodes[1], 1);
        check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
@@ -4566,9 +4574,10 @@ fn test_claim_on_remote_sizeable_push_msat() {
        let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
        let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+       let error_message = "Channel force-closed";
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000);
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[0], true);
        check_added_monitors!(nodes[0], 1);
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
@@ -4943,7 +4952,7 @@ fn test_onchain_to_onchain_claim() {
        assert_eq!(c_txn.len(), 1);
        check_spends!(c_txn[0], commitment_tx[0]);
        assert_eq!(c_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
-       assert!(c_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
+       assert!(c_txn[0].output[0].script_pubkey.is_p2wsh()); // revokeable output
        assert_eq!(c_txn[0].lock_time, LockTime::ZERO); // Success tx
 
        // So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor
@@ -5004,7 +5013,7 @@ fn test_onchain_to_onchain_claim() {
        assert_eq!(b_txn.len(), 1);
        check_spends!(b_txn[0], commitment_tx[0]);
        assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
-       assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
+       assert!(b_txn[0].output[0].script_pubkey.is_p2wpkh()); // direct payment
        assert_eq!(b_txn[0].lock_time.to_consensus_u32(), nodes[1].best_block_info().1); // Success tx
 
        check_closed_broadcast!(nodes[1], true);
@@ -5091,9 +5100,9 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
                // (with value 900 sats) will be claimed in the below `claim_funds` call.
                if node_txn.len() > 2 {
                        assert_eq!(node_txn[2].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
-                       htlc_timeout_tx = if node_txn[2].output[0].value < 900 { node_txn[2].clone() } else { node_txn[0].clone() };
+                       htlc_timeout_tx = if node_txn[2].output[0].value.to_sat() < 900 { node_txn[2].clone() } else { node_txn[0].clone() };
                } else {
-                       htlc_timeout_tx = if node_txn[0].output[0].value < 900 { node_txn[1].clone() } else { node_txn[0].clone() };
+                       htlc_timeout_tx = if node_txn[0].output[0].value.to_sat() < 900 { node_txn[1].clone() } else { node_txn[0].clone() };
                }
        }
 
@@ -7477,8 +7486,8 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
 
        let mut penalty_sum = 0;
        for outp in revoked_txn[0].output.iter() {
-               if outp.script_pubkey.is_v0_p2wsh() {
-                       penalty_sum += outp.value;
+               if outp.script_pubkey.is_p2wsh() {
+                       penalty_sum += outp.value.to_sat();
                }
        }
 
@@ -7499,7 +7508,7 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
                assert_eq!(node_txn[0].input.len(), 3); // Penalty txn claims to_local, offered_htlc and received_htlc outputs
                assert_eq!(node_txn[0].output.len(), 1);
                check_spends!(node_txn[0], revoked_txn[0]);
-               let fee_1 = penalty_sum - node_txn[0].output[0].value;
+               let fee_1 = penalty_sum - node_txn[0].output[0].value.to_sat();
                feerate_1 = fee_1 * 1000 / node_txn[0].weight().to_wu();
                penalty_1 = node_txn[0].txid();
                node_txn.clear();
@@ -7519,7 +7528,7 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
                        penalty_2 = node_txn[0].txid();
                        // Verify new bumped tx is different from last claiming transaction, we don't want spurrious rebroadcast
                        assert_ne!(penalty_2, penalty_1);
-                       let fee_2 = penalty_sum - node_txn[0].output[0].value;
+                       let fee_2 = penalty_sum - node_txn[0].output[0].value.to_sat();
                        feerate_2 = fee_2 * 1000 / node_txn[0].weight().to_wu();
                        // Verify 25% bump heuristic
                        assert!(feerate_2 * 100 >= feerate_1 * 125);
@@ -7542,7 +7551,7 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
                        penalty_3 = node_txn[0].txid();
                        // Verify new bumped tx is different from last claiming transaction, we don't want spurrious rebroadcast
                        assert_ne!(penalty_3, penalty_2);
-                       let fee_3 = penalty_sum - node_txn[0].output[0].value;
+                       let fee_3 = penalty_sum - node_txn[0].output[0].value.to_sat();
                        feerate_3 = fee_3 * 1000 / node_txn[0].weight().to_wu();
                        // Verify 25% bump heuristic
                        assert!(feerate_3 * 100 >= feerate_2 * 125);
@@ -7761,7 +7770,7 @@ fn test_bump_penalty_txn_on_remote_commitment() {
 
                preimage = node_txn[0].txid();
                let index = node_txn[0].input[0].previous_output.vout;
-               let fee = remote_txn[0].output[index as usize].value - node_txn[0].output[0].value;
+               let fee = remote_txn[0].output[index as usize].value.to_sat() - node_txn[0].output[0].value.to_sat();
                feerate_preimage = fee * 1000 / node_txn[0].weight().to_wu();
 
                let (preimage_bump_tx, timeout_tx) = if node_txn[2].input[0].previous_output == node_txn[0].input[0].previous_output {
@@ -7776,7 +7785,7 @@ fn test_bump_penalty_txn_on_remote_commitment() {
 
                timeout = timeout_tx.txid();
                let index = timeout_tx.input[0].previous_output.vout;
-               let fee = remote_txn[0].output[index as usize].value - timeout_tx.output[0].value;
+               let fee = remote_txn[0].output[index as usize].value.to_sat() - timeout_tx.output[0].value.to_sat();
                feerate_timeout = fee * 1000 / timeout_tx.weight().to_wu();
 
                node_txn.clear();
@@ -7795,13 +7804,13 @@ fn test_bump_penalty_txn_on_remote_commitment() {
                check_spends!(preimage_bump, remote_txn[0]);
 
                let index = preimage_bump.input[0].previous_output.vout;
-               let fee = remote_txn[0].output[index as usize].value - preimage_bump.output[0].value;
+               let fee = remote_txn[0].output[index as usize].value.to_sat() - preimage_bump.output[0].value.to_sat();
                let new_feerate = fee * 1000 / preimage_bump.weight().to_wu();
                assert!(new_feerate * 100 > feerate_timeout * 125);
                assert_ne!(timeout, preimage_bump.txid());
 
                let index = node_txn[0].input[0].previous_output.vout;
-               let fee = remote_txn[0].output[index as usize].value - node_txn[0].output[0].value;
+               let fee = remote_txn[0].output[index as usize].value.to_sat() - node_txn[0].output[0].value.to_sat();
                let new_feerate = fee * 1000 / node_txn[0].weight().to_wu();
                assert!(new_feerate * 100 > feerate_preimage * 125);
                assert_ne!(preimage, node_txn[0].txid());
@@ -8077,8 +8086,8 @@ fn test_manually_accept_inbound_channel_request() {
                }
                _ => panic!("Unexpected event"),
        }
-
-       nodes[1].node.force_close_broadcasting_latest_txn(&temp_channel_id, &nodes[0].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[1].node.force_close_broadcasting_latest_txn(&temp_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
 
        let close_msg_ev = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(close_msg_ev.len(), 1);
@@ -8109,11 +8118,11 @@ fn test_manually_reject_inbound_channel_request() {
        // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before
        // rejecting the inbound channel request.
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
-
+       let error_message = "Channel force-closed";
        let events = nodes[1].node.get_and_clear_pending_events();
        match events[0] {
                Event::OpenChannelRequest { temporary_channel_id, .. } => {
-                       nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id()).unwrap();
+                       nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                }
                _ => panic!("Unexpected event"),
        }
@@ -8296,7 +8305,9 @@ fn test_onion_value_mpp_set_calculation() {
        let ev = remove_first_msg_event_to_node(&expected_paths[1][0].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_paths[1], 101_000, our_payment_hash.clone(), Some(our_payment_secret), ev, true, None);
 
-       claim_payment_along_route(&nodes[0], expected_paths, false, our_payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_paths, our_payment_preimage)
+       );
 }
 
 fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) {
@@ -8362,7 +8373,9 @@ fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) {
                pass_along_path(&nodes[src_idx], expected_path, amount_received, our_payment_hash.clone(), Some(our_payment_secret), ev, became_claimable_now, None);
        }
 
-       claim_payment_along_route(&nodes[src_idx], &expected_paths, false, our_payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[src_idx], &expected_paths, our_payment_preimage)
+       );
 }
 
 #[test]
@@ -8394,7 +8407,9 @@ fn test_simple_mpp() {
        route.paths[1].hops[0].short_channel_id = chan_2_id;
        route.paths[1].hops[1].short_channel_id = chan_4_id;
        send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, payment_secret);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+       );
 }
 
 #[test]
@@ -8837,7 +8852,8 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain
                force_closing_node = 1;
                counterparty_node = 0;
        }
-       nodes[force_closing_node].node.force_close_broadcasting_latest_txn(&chan_ab.2, &nodes[counterparty_node].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[force_closing_node].node.force_close_broadcasting_latest_txn(&chan_ab.2, &nodes[counterparty_node].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[force_closing_node], true);
        check_added_monitors!(nodes[force_closing_node], 1);
        check_closed_event!(nodes[force_closing_node], 1, ClosureReason::HolderForceClosed, [nodes[counterparty_node].node.get_our_node_id()], 100000);
@@ -9425,7 +9441,7 @@ fn test_invalid_funding_tx() {
        let wit_program_script: ScriptBuf = wit_program.into();
        for output in tx.output.iter_mut() {
                // Make the confirmed funding transaction have a bogus script_pubkey
-               output.script_pubkey = ScriptBuf::new_v0_p2wsh(&wit_program_script.wscript_hash());
+               output.script_pubkey = ScriptBuf::new_p2wsh(&wit_program_script.wscript_hash());
        }
 
        nodes[0].node.funding_transaction_generated_unchecked(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone(), 0).unwrap();
@@ -9463,7 +9479,7 @@ fn test_invalid_funding_tx() {
        // long the ChannelMonitor will try to read 32 bytes from the second-to-last element, panicing
        // as its not 32 bytes long.
        let mut spend_tx = Transaction {
-               version: 2i32, lock_time: LockTime::ZERO,
+               version: Version::TWO, lock_time: LockTime::ZERO,
                input: tx.output.iter().enumerate().map(|(idx, _)| TxIn {
                        previous_output: BitcoinOutPoint {
                                txid: tx.txid(),
@@ -9474,7 +9490,7 @@ fn test_invalid_funding_tx() {
                        witness: Witness::from_slice(&channelmonitor::deliberately_bogus_accepted_htlc_witness())
                }).collect(),
                output: vec![TxOut {
-                       value: 1000,
+                       value: Amount::from_sat(1000),
                        script_pubkey: ScriptBuf::new(),
                }]
        };
@@ -9570,8 +9586,8 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t
        let (_, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
        nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
        nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
-
-       nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[1], true);
        check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[2].node.get_our_node_id()], 100000);
        check_added_monitors!(nodes[1], 1);
@@ -9838,7 +9854,9 @@ fn test_inconsistent_mpp_params() {
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), true, None);
 
-       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
+       do_claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage)
+       );
        expect_payment_sent(&nodes[0], our_payment_preimage, Some(None), true, true);
 }
 
@@ -10263,8 +10281,8 @@ fn test_non_final_funding_tx() {
        let mut tx = match events[0] {
                Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => {
                        // Timelock the transaction _beyond_ the best client height + 1.
-                       Transaction { version: chan_id as i32, lock_time: LockTime::from_height(best_height + 2).unwrap(), input: vec![input], output: vec![TxOut {
-                               value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                       Transaction { version: Version(chan_id as i32), lock_time: LockTime::from_height(best_height + 2).unwrap(), input: vec![input], output: vec![TxOut {
+                               value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(),
                        }]}
                },
                _ => panic!("Unexpected event"),
@@ -10303,8 +10321,8 @@ fn test_non_final_funding_tx_within_headroom() {
        let mut tx = match events[0] {
                Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => {
                        // Timelock the transaction within a +1 headroom from the best block.
-                       Transaction { version: chan_id as i32, lock_time: LockTime::from_consensus(best_height + 1), input: vec![input], output: vec![TxOut {
-                               value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                       Transaction { version: Version(chan_id as i32), lock_time: LockTime::from_consensus(best_height + 1), input: vec![input], output: vec![TxOut {
+                               value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(),
                        }]}
                },
                _ => panic!("Unexpected event"),
@@ -10954,8 +10972,8 @@ fn test_close_in_funding_batch() {
        let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 };
        let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1);
        let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2);
-
-       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
 
        // The monitor should become closed.
        check_added_monitors(&nodes[0], 1);
@@ -11043,7 +11061,8 @@ fn test_batch_funding_close_after_funding_signed() {
        let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 };
        let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1);
        let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2);
-       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors(&nodes[0], 2);
        {
                let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap();
@@ -11112,12 +11131,12 @@ fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitmen
        } else {
                (&nodes[0], &nodes[1])
        };
-
-       closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id(), error_message.to_string()).unwrap();
        let mut msg_events = closing_node.node.get_and_clear_pending_msg_events();
        assert_eq!(msg_events.len(), 1);
        match msg_events.pop().unwrap() {
-               MessageSendEvent::HandleError { action: msgs::ErrorAction::DisconnectPeer { .. }, .. } => {},
+               MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { .. }, .. } => {},
                _ => panic!("Unexpected event"),
        }
        check_added_monitors(closing_node, 1);
index 60341620887b59dc3fcadd06e5d6b5d7f1f2b21b..17c6990508610c196574913171300e13003acb86 100644 (file)
@@ -11,9 +11,11 @@ use crate::io_extras::sink;
 use crate::prelude::*;
 use core::ops::Deref;
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
 use bitcoin::consensus::Encodable;
 use bitcoin::policy::MAX_STANDARD_TX_WEIGHT;
+use bitcoin::transaction::Version;
 use bitcoin::{
        absolute::LockTime as AbsoluteLockTime, OutPoint, ScriptBuf, Sequence, Transaction, TxIn,
        TxOut, Weight,
@@ -136,7 +138,7 @@ impl ConstructedTransaction {
                        .filter(|(serial_id, _)| {
                                !is_serial_id_valid_for_counterparty(context.holder_is_initiator, serial_id)
                        })
-                       .fold(0u64, |value, (_, input)| value.saturating_add(input.prev_output.value));
+                       .fold(0u64, |value, (_, input)| value.saturating_add(input.prev_output.value.to_sat()));
 
                let local_outputs_value_satoshis = context
                        .outputs
@@ -144,7 +146,7 @@ impl ConstructedTransaction {
                        .filter(|(serial_id, _)| {
                                !is_serial_id_valid_for_counterparty(context.holder_is_initiator, serial_id)
                        })
-                       .fold(0u64, |value, (_, output)| value.saturating_add(output.tx_out.value));
+                       .fold(0u64, |value, (_, output)| value.saturating_add(output.tx_out.value.to_sat()));
 
                Self {
                        holder_is_initiator: context.holder_is_initiator,
@@ -193,7 +195,7 @@ impl ConstructedTransaction {
                let output: Vec<TxOut> =
                        outputs.into_iter().map(|InteractiveTxOutput { tx_out, .. }| tx_out).collect();
 
-               Transaction { version: 2, lock_time: self.lock_time, input, output }
+               Transaction { version: Version::TWO, lock_time: self.lock_time, input, output }
        }
 }
 
@@ -210,11 +212,11 @@ struct NegotiationContext {
 }
 
 pub(crate) fn estimate_input_weight(prev_output: &TxOut) -> Weight {
-       Weight::from_wu(if prev_output.script_pubkey.is_v0_p2wpkh() {
+       Weight::from_wu(if prev_output.script_pubkey.is_p2wpkh() {
                P2WPKH_INPUT_WEIGHT_LOWER_BOUND
-       } else if prev_output.script_pubkey.is_v0_p2wsh() {
+       } else if prev_output.script_pubkey.is_p2wsh() {
                P2WSH_INPUT_WEIGHT_LOWER_BOUND
-       } else if prev_output.script_pubkey.is_v1_p2tr() {
+       } else if prev_output.script_pubkey.is_p2tr() {
                P2TR_INPUT_WEIGHT_LOWER_BOUND
        } else {
                UNKNOWN_SEGWIT_VERSION_INPUT_WEIGHT_LOWER_BOUND
@@ -243,7 +245,7 @@ impl NegotiationContext {
                        .iter()
                        .filter(|(serial_id, _)| self.is_serial_id_valid_for_counterparty(serial_id))
                        .fold(0u64, |acc, (_, InteractiveTxInput { prev_output, .. })| {
-                               acc.saturating_add(prev_output.value)
+                               acc.saturating_add(prev_output.value.to_sat())
                        })
        }
 
@@ -252,7 +254,7 @@ impl NegotiationContext {
                        .iter()
                        .filter(|(serial_id, _)| self.is_serial_id_valid_for_counterparty(serial_id))
                        .fold(0u64, |acc, (_, InteractiveTxOutput { tx_out, .. })| {
-                               acc.saturating_add(tx_out.value)
+                               acc.saturating_add(tx_out.value.to_sat())
                        })
        }
 
@@ -402,7 +404,7 @@ impl NegotiationContext {
                // bitcoin supply.
                let mut outputs_value: u64 = 0;
                for output in self.outputs.iter() {
-                       outputs_value = outputs_value.saturating_add(output.1.tx_out.value);
+                       outputs_value = outputs_value.saturating_add(output.1.tx_out.value.to_sat());
                }
                if outputs_value.saturating_add(msg.sats) > TOTAL_BITCOIN_SUPPLY_SATOSHIS {
                        // The receiving node:
@@ -423,8 +425,8 @@ impl NegotiationContext {
                //
                // TODO: The last check would be simplified when https://github.com/rust-bitcoin/rust-bitcoin/commit/1656e1a09a1959230e20af90d20789a4a8f0a31b
                // hits the next release of rust-bitcoin.
-               if !(msg.script.is_v0_p2wpkh()
-                       || msg.script.is_v0_p2wsh()
+               if !(msg.script.is_p2wpkh()
+                       || msg.script.is_p2wsh()
                        || (msg.script.is_witness_program()
                                && msg.script.witness_version().map(|v| v.to_num() >= 1).unwrap_or(false)))
                {
@@ -441,7 +443,10 @@ impl NegotiationContext {
                        hash_map::Entry::Vacant(entry) => {
                                entry.insert(InteractiveTxOutput {
                                        serial_id: msg.serial_id,
-                                       tx_out: TxOut { value: msg.sats, script_pubkey: msg.script.clone() },
+                                       tx_out: TxOut {
+                                               value: Amount::from_sat(msg.sats),
+                                               script_pubkey: msg.script.clone(),
+                                       },
                                });
                                Ok(())
                        },
@@ -488,7 +493,10 @@ impl NegotiationContext {
                        msg.serial_id,
                        InteractiveTxOutput {
                                serial_id: msg.serial_id,
-                               tx_out: TxOut { value: msg.sats, script_pubkey: msg.script.clone() },
+                               tx_out: TxOut {
+                                       value: Amount::from_sat(msg.sats),
+                                       script_pubkey: msg.script.clone(),
+                               },
                        },
                );
                Ok(())
@@ -941,7 +949,7 @@ impl InteractiveTxConstructor {
                        let msg = msgs::TxAddOutput {
                                channel_id: self.channel_id,
                                serial_id,
-                               sats: output.value,
+                               sats: output.value.to_sat(),
                                script: output.script_pubkey,
                        };
                        do_state_transition!(self, sent_tx_add_output, &msg)?;
@@ -1028,11 +1036,13 @@ mod tests {
        use crate::sign::EntropySource;
        use crate::util::atomic_counter::AtomicCounter;
        use crate::util::ser::TransactionU16LenLimited;
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::opcodes;
        use bitcoin::blockdata::script::Builder;
        use bitcoin::hashes::Hash;
        use bitcoin::key::UntweakedPublicKey;
-       use bitcoin::secp256k1::{KeyPair, Secp256k1};
+       use bitcoin::secp256k1::{Keypair, Secp256k1};
+       use bitcoin::transaction::Version;
        use bitcoin::{
                absolute::LockTime as AbsoluteLockTime, OutPoint, Sequence, Transaction, TxIn, TxOut,
        };
@@ -1236,17 +1246,17 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let (value, script_pubkey) = match output {
                        TestOutput::P2WPKH(value) => {
-                               (*value, ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::from_slice(&[1; 20]).unwrap()))
+                               (*value, ScriptBuf::new_p2wpkh(&WPubkeyHash::from_slice(&[1; 20]).unwrap()))
                        },
                        TestOutput::P2WSH(value) => {
-                               (*value, ScriptBuf::new_v0_p2wsh(&WScriptHash::from_slice(&[2; 32]).unwrap()))
+                               (*value, ScriptBuf::new_p2wsh(&WScriptHash::from_slice(&[2; 32]).unwrap()))
                        },
                        TestOutput::P2TR(value) => (
                                *value,
-                               ScriptBuf::new_v1_p2tr(
+                               ScriptBuf::new_p2tr(
                                        &secp_ctx,
                                        UntweakedPublicKey::from_keypair(
-                                               &KeyPair::from_seckey_slice(&secp_ctx, &[3; 32]).unwrap(),
+                                               &Keypair::from_seckey_slice(&secp_ctx, &[3; 32]).unwrap(),
                                        )
                                        .0,
                                        None,
@@ -1257,12 +1267,12 @@ mod tests {
                        },
                };
 
-               TxOut { value, script_pubkey }
+               TxOut { value: Amount::from_sat(value), script_pubkey }
        }
 
        fn generate_tx_with_locktime(outputs: &[TestOutput], locktime: u32) -> Transaction {
                Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: AbsoluteLockTime::from_height(locktime).unwrap(),
                        input: vec![TxIn { ..Default::default() }],
                        output: outputs.iter().map(generate_txout).collect(),
@@ -1288,11 +1298,11 @@ mod tests {
        }
 
        fn generate_p2wsh_script_pubkey() -> ScriptBuf {
-               Builder::new().push_opcode(opcodes::OP_TRUE).into_script().to_v0_p2wsh()
+               Builder::new().push_opcode(opcodes::OP_TRUE).into_script().to_p2wsh()
        }
 
        fn generate_p2wpkh_script_pubkey() -> ScriptBuf {
-               ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::from_slice(&[1; 20]).unwrap())
+               ScriptBuf::new_p2wpkh(&WPubkeyHash::from_slice(&[1; 20]).unwrap())
        }
 
        fn generate_outputs(outputs: &[TestOutput]) -> Vec<TxOut> {
@@ -1348,7 +1358,7 @@ mod tests {
        }
 
        fn generate_non_witness_output(value: u64) -> TxOut {
-               TxOut { value, script_pubkey: generate_p2sh_script_pubkey() }
+               TxOut { value: Amount::from_sat(value), script_pubkey: generate_p2sh_script_pubkey() }
        }
 
        #[test]
index 36fe098b9ee59a381b09663a79a8ceb09c9ba131..7bd605c9ddfeeeee275fb636b8ae38f8a1b4ff30 100644 (file)
@@ -84,7 +84,9 @@ fn large_payment_metadata() {
                .with_payment_secret(payment_secret)
                .with_payment_metadata(payment_metadata.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+       );
 
        // Check that the payment parameter for max path length will prevent us from routing past our
        // next-hop peer given the payment_metadata size.
@@ -133,7 +135,9 @@ fn large_payment_metadata() {
                .with_payment_secret(payment_secret_2)
                .with_payment_metadata(recipient_onion_allows_2_hops.payment_metadata.unwrap());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage_2);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage_2)
+       );
 }
 
 #[test]
@@ -201,7 +205,10 @@ fn one_hop_blinded_path_with_custom_tlv() {
                .with_payment_secret(payment_secret)
                .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[1], &[&[&nodes[2]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2]]], payment_preimage)
+                       .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
+       );
 
        // If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
        let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
@@ -226,9 +233,12 @@ fn one_hop_blinded_path_with_custom_tlv() {
        let path = &[&nodes[1], &nodes[2]];
        let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
                .with_payment_secret(payment_secret)
-               .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs);
+               .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+                       .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
+       );
 }
 
 #[test]
@@ -283,7 +293,10 @@ fn blinded_path_with_custom_tlv() {
                .with_payment_secret(payment_secret)
                .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[1], &[&[&nodes[2], &nodes[3]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2], &nodes[3]]], payment_preimage)
+                       .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
+       );
 
        // If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
        let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
@@ -320,7 +333,10 @@ fn blinded_path_with_custom_tlv() {
        let path = &[&nodes[1], &nodes[2], &nodes[3]];
        let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
                .with_payment_secret(payment_secret)
-               .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs);
+               .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], payment_preimage)
+                       .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
+       );
 }
index 5e2ae44c99810a5ddece06f6b5e028618d5d24c2..888044b7aea144e4d10dec49c4e6e377d5d9664f 100644 (file)
@@ -16,6 +16,7 @@ pub mod functional_test_utils;
 pub mod onion_payment;
 pub mod channelmanager;
 pub mod channel_keys;
+pub mod channel_state;
 pub mod inbound_payment;
 pub mod msgs;
 pub mod peer_handler;
index 761d4b5316c69b4a728c60f654733ccf5330ab3b..50858bb48aff5107b666dc11631dac1dc65e512c 100644 (file)
@@ -31,6 +31,7 @@ use bitcoin::blockdata::opcodes;
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::secp256k1::{Secp256k1, SecretKey};
 use bitcoin::sighash::{SighashCache, EcdsaSighashType};
+use bitcoin::transaction::Version;
 
 use crate::prelude::*;
 
@@ -359,16 +360,16 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                        },
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(),
                        },
                ],
@@ -535,8 +536,8 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
        check_spends!(b_broadcast_txn[1], remote_txn[0], coinbase_tx);
        assert_eq!(b_broadcast_txn[0].input.len(), if anchors { 2 } else { 1 });
        assert_eq!(b_broadcast_txn[1].input.len(), if anchors { 2 } else { 1 });
-       assert_eq!(remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value, 3_000);
-       assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000);
+       assert_eq!(remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value.to_sat(), 3_000);
+       assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value.to_sat(), 4_000);
 
        assert!(nodes[0].node.list_channels().is_empty());
        check_closed_broadcast!(nodes[0], true);
@@ -615,8 +616,8 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
        assert_ne!(a_broadcast_txn[0].input[0].previous_output.vout,
                   a_broadcast_txn[1].input[0].previous_output.vout);
        // a_broadcast_txn [0] and [1] should spend the HTLC outputs of the commitment tx
-       assert_eq!(remote_txn[0].output[a_broadcast_txn[0].input[0].previous_output.vout as usize].value, 3_000);
-       assert_eq!(remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000);
+       assert_eq!(remote_txn[0].output[a_broadcast_txn[0].input[0].previous_output.vout as usize].value.to_sat(), 3_000);
+       assert_eq!(remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value.to_sat(), 4_000);
 
        // Once the HTLC-Timeout transaction confirms, A will no longer consider the HTLC
        // "MaybeClaimable", but instead move it to "AwaitingConfirmations".
@@ -720,16 +721,16 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) {
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                        },
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(),
                        },
                ],
@@ -778,8 +779,9 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) {
 
        // First confirm the commitment transaction on nodes[0], which should leave us with three
        // claimable balances.
+       let error_message = "Channel force-closed";
        let node_a_commitment_claimable = nodes[0].best_block_info().1 + BREAKDOWN_TIMEOUT as u32;
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors!(nodes[0], 1);
        check_closed_broadcast!(nodes[0], true);
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 1000000);
@@ -1275,7 +1277,7 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_
        // Currently the revoked commitment is claimed in four transactions as the HTLCs all expire
        // quite soon.
        assert_eq!(claim_txn.len(), 4);
-       claim_txn.sort_unstable_by_key(|tx| tx.output.iter().map(|output| output.value).sum::<u64>());
+       claim_txn.sort_unstable_by_key(|tx| tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>());
 
        // The following constants were determined experimentally
        const BS_TO_SELF_CLAIM_EXP_WEIGHT: u64 = 483;
@@ -1434,16 +1436,16 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                        },
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(),
                        },
                ],
@@ -1465,9 +1467,9 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
        assert_eq!(revoked_local_txn[0].input.len(), 1);
        assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, funding_tx.txid());
        if anchors {
-               assert_eq!(revoked_local_txn[0].output[4].value, 11000); // to_self output
+               assert_eq!(revoked_local_txn[0].output[4].value.to_sat(), 11000); // to_self output
        } else {
-               assert_eq!(revoked_local_txn[0].output[2].value, 11000); // to_self output
+               assert_eq!(revoked_local_txn[0].output[2].value.to_sat(), 11000); // to_self output
        }
 
        // The to-be-revoked commitment tx should have two HTLCs, an output for each side, and an
@@ -1589,10 +1591,10 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
        if anchors {
                // With anchors, B can pay for revoked_htlc_success's fee with additional inputs, rather
                // than with the HTLC itself.
-               fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value,
+               fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value.to_sat(),
                        3_000 - as_revoked_htlc_success_claim_fee);
        } else {
-               fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value,
+               fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value.to_sat(),
                        3_000 - revoked_htlc_success_fee - as_revoked_htlc_success_claim_fee);
        }
 
@@ -1607,7 +1609,7 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
                }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2
                        amount_satoshis: 1_000,
                }, Balance::ClaimableAwaitingConfirmations {
-                       amount_satoshis: as_htlc_claim_tx[0].output[0].value,
+                       amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(),
                        confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1,
                }]),
                sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
@@ -1620,7 +1622,7 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
                }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2
                        amount_satoshis: 1_000,
                }, Balance::ClaimableAwaitingConfirmations {
-                       amount_satoshis: as_htlc_claim_tx[0].output[0].value,
+                       amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(),
                        confirmation_height: nodes[0].best_block_info().1 + 2,
                }]),
                sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
@@ -1689,7 +1691,7 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
                        // to_self output in B's revoked commitment
                        amount_satoshis: 11_000,
                }, Balance::ClaimableAwaitingConfirmations {
-                       amount_satoshis: revoked_htlc_timeout_claim.output[0].value,
+                       amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(),
                        confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1,
                }]),
                sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
@@ -1697,10 +1699,10 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) {
        mine_transaction(&nodes[0], &revoked_to_self_claim);
        assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations {
                        // to_self output in B's revoked commitment
-                       amount_satoshis: revoked_to_self_claim.output[0].value,
+                       amount_satoshis: revoked_to_self_claim.output[0].value.to_sat(),
                        confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1,
                }, Balance::ClaimableAwaitingConfirmations {
-                       amount_satoshis: revoked_htlc_timeout_claim.output[0].value,
+                       amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(),
                        confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 2,
                }]),
                sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
@@ -1746,11 +1748,11 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![TxOut {
-                       value: Amount::ONE_BTC.to_sat(),
+                       value: Amount::ONE_BTC,
                        script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                }],
        };
@@ -1943,7 +1945,7 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) {
                }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1
                        amount_satoshis: 4_000,
                }, Balance::ClaimableAwaitingConfirmations { // HTLC 2
-                       amount_satoshis: claim_txn_2[0].output[0].value,
+                       amount_satoshis: claim_txn_2[0].output[0].value.to_sat(),
                        confirmation_height: htlc_2_claim_maturity,
                }]),
                sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
@@ -1968,16 +1970,16 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) {
 
        if anchors {
                assert_eq!(vec![Balance::ClaimableAwaitingConfirmations {
-                               amount_satoshis: claim_txn_2[1].output[0].value,
+                               amount_satoshis: claim_txn_2[1].output[0].value.to_sat(),
                                confirmation_height: rest_claim_maturity,
                        }, Balance::ClaimableAwaitingConfirmations {
-                               amount_satoshis: revoked_to_self_claim.as_ref().unwrap().output[0].value,
+                               amount_satoshis: revoked_to_self_claim.as_ref().unwrap().output[0].value.to_sat(),
                                confirmation_height: rest_claim_maturity,
                        }],
                        nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
        } else {
                assert_eq!(vec![Balance::ClaimableAwaitingConfirmations {
-                               amount_satoshis: claim_txn_2[1].output[0].value,
+                               amount_satoshis: claim_txn_2[1].output[0].value.to_sat(),
                                confirmation_height: rest_claim_maturity,
                        }],
                        nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
@@ -2036,8 +2038,8 @@ fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool
        // ensures that the HTLC timeout package is held until we reach its expiration height.
        let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000);
        route_payment(&nodes[0], &[&nodes[1]], 10_000_000);
-
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors(&nodes[0], 1);
        check_closed_broadcast(&nodes[0], 1, true);
        check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, false,
@@ -2135,11 +2137,11 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) {
        check_added_monitors(&nodes[0], 1);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![TxOut { // UTXO to attach fees to `htlc_tx` on anchors
-                       value: Amount::ONE_BTC.to_sat(),
+                       value: Amount::ONE_BTC,
                        script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                }],
        };
@@ -2164,8 +2166,8 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) {
                                        assert_eq!(txn.len(), 1);
                                        let htlc_tx = txn.pop().unwrap();
                                        check_spends!(&htlc_tx, &commitment_txn[0], &coinbase_tx);
-                                       let htlc_tx_fee = HTLC_AMT_SAT + coinbase_tx.output[0].value -
-                                               htlc_tx.output.iter().map(|output| output.value).sum::<u64>();
+                                       let htlc_tx_fee = HTLC_AMT_SAT + coinbase_tx.output[0].value.to_sat() -
+                                               htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
                                        let htlc_tx_weight = htlc_tx.weight().to_wu();
                                        (htlc_tx, compute_feerate_sat_per_1000_weight(htlc_tx_fee, htlc_tx_weight))
                                }
@@ -2180,7 +2182,7 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) {
                        }
                        let htlc_tx = txn.pop().unwrap();
                        check_spends!(htlc_tx, commitment_txn[0]);
-                       let htlc_tx_fee = HTLC_AMT_SAT - htlc_tx.output[0].value;
+                       let htlc_tx_fee = HTLC_AMT_SAT - htlc_tx.output[0].value.to_sat();
                        let htlc_tx_weight = htlc_tx.weight().to_wu();
                        (htlc_tx, compute_feerate_sat_per_1000_weight(htlc_tx_fee, htlc_tx_weight))
                };
@@ -2291,11 +2293,11 @@ fn test_yield_anchors_events() {
        let (commitment_tx, anchor_tx) = match holder_events.pop().unwrap() {
                Event::BumpTransaction(event) => {
                        let coinbase_tx = Transaction {
-                               version: 2,
+                               version: Version::TWO,
                                lock_time: LockTime::ZERO,
                                input: vec![TxIn { ..Default::default() }],
                                output: vec![TxOut { // UTXO to attach fees to `anchor_tx`
-                                       value: Amount::ONE_BTC.to_sat(),
+                                       value: Amount::ONE_BTC,
                                        script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                                }],
                        };
@@ -2312,8 +2314,8 @@ fn test_yield_anchors_events() {
                _ => panic!("Unexpected event"),
        };
 
-       assert_eq!(commitment_tx.output[2].value, 1_000); // HTLC A -> B
-       assert_eq!(commitment_tx.output[3].value, 2_000); // HTLC B -> A
+       assert_eq!(commitment_tx.output[2].value.to_sat(), 1_000); // HTLC A -> B
+       assert_eq!(commitment_tx.output[3].value.to_sat(), 2_000); // HTLC B -> A
 
        mine_transactions(&nodes[0], &[&commitment_tx, &anchor_tx]);
        check_added_monitors!(nodes[0], 1);
@@ -2468,9 +2470,9 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
        let mut revoked_commitment_txs = Vec::with_capacity(events.len());
        let mut anchor_txs = Vec::with_capacity(events.len());
        for (idx, event) in events.into_iter().enumerate() {
-               let utxo_value = Amount::ONE_BTC.to_sat() * (idx + 1) as u64;
+               let utxo_value = Amount::ONE_BTC * (idx + 1) as u64;
                let coinbase_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::ZERO,
                        input: vec![TxIn { ..Default::default() }],
                        output: vec![TxOut { // UTXO to attach fees to `anchor_tx`
@@ -2545,18 +2547,18 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
        let htlc_tx = {
                let secret_key = SecretKey::from_slice(&[1; 32]).unwrap();
                let public_key = PublicKey::new(secret_key.public_key(&secp));
-               let fee_utxo_script = ScriptBuf::new_v0_p2wpkh(&public_key.wpubkey_hash().unwrap());
+               let fee_utxo_script = ScriptBuf::new_p2wpkh(&public_key.wpubkey_hash().unwrap());
                let coinbase_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::ZERO,
                        input: vec![TxIn { ..Default::default() }],
                        output: vec![TxOut { // UTXO to attach fees to `htlc_tx`
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: fee_utxo_script.clone(),
                        }],
                };
                let mut htlc_tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: LockTime::ZERO,
                        input: vec![TxIn { // Fee input
                                previous_output: bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 },
@@ -2593,7 +2595,7 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
                }
                let fee_utxo_sig = {
                        let witness_script = ScriptBuf::new_p2pkh(&public_key.pubkey_hash());
-                       let sighash = hash_to_message!(&SighashCache::new(&htlc_tx).segwit_signature_hash(
+                       let sighash = hash_to_message!(&SighashCache::new(&htlc_tx).p2wsh_signature_hash(
                                0, &witness_script, coinbase_tx.output[0].value, EcdsaSighashType::All
                        ).unwrap()[..]);
                        let sig = sign(&secp, &sighash, &secret_key);
@@ -2703,13 +2705,14 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c
        let secp = Secp256k1::new();
        let privkey = bitcoin::PrivateKey::from_slice(&[1; 32], bitcoin::Network::Testnet).unwrap();
        let pubkey = bitcoin::PublicKey::from_private_key(&secp, &privkey);
-       let p2wpkh_script = ScriptBuf::new_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap());
+       let p2wpkh_script = ScriptBuf::new_p2wpkh(&pubkey.wpubkey_hash().unwrap());
        get_monitor!(nodes[1], chan_id).set_counterparty_payment_script(p2wpkh_script.clone());
        assert_eq!(get_monitor!(nodes[1], chan_id).get_counterparty_payment_script(), p2wpkh_script);
 
        // Confirm the counterparty's commitment and reload the monitor (either before or after) such
        // that we arrive at the correct `counterparty_payment_script` after the reload.
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+       let error_message = "Channel force-closed";
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_added_monitors(&nodes[0], 1);
        check_closed_broadcast(&nodes[0], 1, true);
        check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, false,
@@ -2742,7 +2745,7 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c
        };
        check_closed_event!(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false,
                 [nodes[0].node.get_our_node_id()], 100000);
-       assert!(get_monitor!(nodes[1], chan_id).get_counterparty_payment_script().is_v0_p2wsh());
+       assert!(get_monitor!(nodes[1], chan_id).get_counterparty_payment_script().is_p2wsh());
 
        connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
        connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
@@ -2785,12 +2788,12 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let coinbase_tx = Transaction {
-               version: 2,
+               version: Version::TWO,
                lock_time: LockTime::ZERO,
                input: vec![TxIn { ..Default::default() }],
                output: vec![
                        TxOut {
-                               value: Amount::ONE_BTC.to_sat(),
+                               value: Amount::ONE_BTC,
                                script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
                        },
                ],
@@ -2896,7 +2899,9 @@ fn test_event_replay_causing_monitor_replay() {
 
        let payment_preimage = route_payment(&nodes[0], &[&nodes[1]], 1_000_000).0;
 
-       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage);
+       do_claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+       );
 
        // At this point the `PaymentSent` event has not been processed but the full commitment signed
        // dance has completed.
index 16f3d09fef0d7e9f1549154779d11cf488fec89a..3e0627aac233036361bda62971f704d6ea2718d6 100644 (file)
@@ -52,7 +52,7 @@ use core::fmt::Display;
 use crate::io::{self, Cursor, Read};
 use crate::io_extras::read_to_end;
 
-use crate::events::{EventsProvider, MessageSendEventsProvider};
+use crate::events::MessageSendEventsProvider;
 use crate::crypto::streams::ChaChaPolyReadAdapter;
 use crate::util::logger;
 use crate::util::ser::{BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, Writer};
@@ -1623,7 +1623,7 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
 }
 
 /// A handler for received [`OnionMessage`]s and for providing generated ones to send.
-pub trait OnionMessageHandler: EventsProvider {
+pub trait OnionMessageHandler {
        /// Handle an incoming `onion_message` message from the given peer.
        fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
 
@@ -3194,7 +3194,7 @@ impl_writeable_msg!(GossipTimestampFilter, {
 
 #[cfg(test)]
 mod tests {
-       use bitcoin::{Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut};
+       use bitcoin::{Amount, Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut};
        use hex::DisplayHex;
        use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
@@ -3206,12 +3206,13 @@ mod tests {
 
        use bitcoin::hashes::hex::FromHex;
        use bitcoin::address::Address;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::Builder;
        use bitcoin::blockdata::opcodes;
        use bitcoin::hash_types::Txid;
        use bitcoin::locktime::absolute::LockTime;
+       use bitcoin::transaction::Version;
 
        use bitcoin::secp256k1::{PublicKey,SecretKey};
        use bitcoin::secp256k1::{Secp256k1, Message};
@@ -3302,7 +3303,7 @@ mod tests {
        macro_rules! get_sig_on {
                ($privkey: expr, $ctx: expr, $string: expr) => {
                        {
-                               let sighash = Message::from_slice(&$string.into_bytes()[..]).unwrap();
+                               let sighash = Message::from_digest_slice(&$string.into_bytes()[..]).unwrap();
                                $ctx.sign_ecdsa(&sighash, &$privkey)
                        }
                }
@@ -3904,7 +3905,7 @@ mod tests {
                        channel_id: ChannelId::from_bytes([2; 32]),
                        serial_id: 4886718345,
                        prevtx: TransactionU16LenLimited::new(Transaction {
-                               version: 2,
+                               version: Version::TWO,
                                lock_time: LockTime::ZERO,
                                input: vec![TxIn {
                                        previous_output: OutPoint { txid: Txid::from_str("305bab643ee297b8b6b76b320792c8223d55082122cb606bf89382146ced9c77").unwrap(), index: 2 }.into_bitcoin_outpoint(),
@@ -3916,12 +3917,12 @@ mod tests {
                                }],
                                output: vec![
                                        TxOut {
-                                               value: 12704566,
-                                               script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().payload.script_pubkey(),
+                                               value: Amount::from_sat(12704566),
+                                               script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().payload().script_pubkey(),
                                        },
                                        TxOut {
-                                               value: 245148,
-                                               script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload.script_pubkey(),
+                                               value: Amount::from_sat(245148),
+                                               script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(),
                                        },
                                ],
                        }).unwrap(),
@@ -3939,7 +3940,7 @@ mod tests {
                        channel_id: ChannelId::from_bytes([2; 32]),
                        serial_id: 4886718345,
                        sats: 4886718345,
-                       script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload.script_pubkey(),
+                       script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(),
                };
                let encoded_value = tx_add_output.encode();
                let target_value = <Vec<u8>>::from_hex("0202020202020202020202020202020202020202020202020202020202020202000000012345678900000001234567890016001436ec78d514df462da95e6a00c24daa8915362d42").unwrap();
index 016afd32a09c209c8c2b81eb2ef2def3f3205417..c7fb5f8fd59b09fda9784f9474e066f5de11c28b 100644 (file)
 //! Nodes without channels are disconnected and connected as needed to ensure that deterministic
 //! blinded paths are used.
 
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::PublicKey;
 use core::time::Duration;
 use crate::blinded_path::{BlindedPath, IntroductionNode};
 use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
 use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose};
-use crate::ln::channelmanager::{PaymentId, RecentPaymentDetails, Retry, self};
+use crate::ln::channelmanager::{MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self};
 use crate::ln::functional_test_utils::*;
 use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement};
 use crate::offers::invoice::Bolt12Invoice;
@@ -274,7 +274,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
        announce_node_address(charlie, &[alice, bob, david, &nodes[4], &nodes[5]], tor.clone());
 
        let offer = bob.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
        assert_ne!(offer.signing_pubkey(), Some(bob_id));
@@ -290,7 +290,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
        announce_node_address(&nodes[5], &[alice, bob, charlie, david, &nodes[4]], tor.clone());
 
        let offer = bob.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
        assert_ne!(offer.signing_pubkey(), Some(bob_id));
@@ -341,7 +341,7 @@ fn prefers_more_connected_nodes_in_blinded_paths() {
        disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
 
        let offer = bob.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
        assert_ne!(offer.signing_pubkey(), Some(bob_id));
@@ -352,6 +352,124 @@ fn prefers_more_connected_nodes_in_blinded_paths() {
        }
 }
 
+/// Checks that blinded paths are compact for short-lived offers.
+#[test]
+fn creates_short_lived_offer() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+
+       let alice = &nodes[0];
+       let alice_id = alice.node.get_our_node_id();
+       let bob = &nodes[1];
+
+       let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
+       let offer = alice.node
+               .create_offer_builder(Some(absolute_expiry)).unwrap()
+               .build().unwrap();
+       assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
+       assert!(!offer.paths().is_empty());
+       for path in offer.paths() {
+               let introduction_node_id = resolve_introduction_node(bob, &path);
+               assert_eq!(introduction_node_id, alice_id);
+               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+       }
+}
+
+/// Checks that blinded paths are not compact for long-lived offers.
+#[test]
+fn creates_long_lived_offer() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+
+       let alice = &nodes[0];
+       let alice_id = alice.node.get_our_node_id();
+
+       let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY
+               + Duration::from_secs(1);
+       let offer = alice.node
+               .create_offer_builder(Some(absolute_expiry))
+               .unwrap()
+               .build().unwrap();
+       assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
+       assert!(!offer.paths().is_empty());
+       for path in offer.paths() {
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id));
+       }
+
+       let offer = alice.node
+               .create_offer_builder(None).unwrap()
+               .build().unwrap();
+       assert_eq!(offer.absolute_expiry(), None);
+       assert!(!offer.paths().is_empty());
+       for path in offer.paths() {
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id));
+       }
+}
+
+/// Checks that blinded paths are compact for short-lived refunds.
+#[test]
+fn creates_short_lived_refund() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+
+       let alice = &nodes[0];
+       let bob = &nodes[1];
+       let bob_id = bob.node.get_our_node_id();
+
+       let absolute_expiry = bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
+       let payment_id = PaymentId([1; 32]);
+       let refund = bob.node
+               .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
+               .unwrap()
+               .build().unwrap();
+       assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
+       assert!(!refund.paths().is_empty());
+       for path in refund.paths() {
+               let introduction_node_id = resolve_introduction_node(alice, &path);
+               assert_eq!(introduction_node_id, bob_id);
+               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+       }
+}
+
+/// Checks that blinded paths are not compact for long-lived refunds.
+#[test]
+fn creates_long_lived_refund() {
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+
+       let bob = &nodes[1];
+       let bob_id = bob.node.get_our_node_id();
+
+       let absolute_expiry = bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY
+               + Duration::from_secs(1);
+       let payment_id = PaymentId([1; 32]);
+       let refund = bob.node
+               .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
+               .unwrap()
+               .build().unwrap();
+       assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
+       assert!(!refund.paths().is_empty());
+       for path in refund.paths() {
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
+       }
+}
+
 /// Checks that an offer can be paid through blinded paths and that ephemeral pubkeys are used
 /// rather than exposing a node's pubkey.
 #[test]
@@ -391,16 +509,14 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
        disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
 
        let offer = alice.node
-               .create_offer_builder()
+               .create_offer_builder(None)
                .unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
        assert_ne!(offer.signing_pubkey(), Some(alice_id));
        assert!(!offer.paths().is_empty());
        for path in offer.paths() {
-               let introduction_node_id = resolve_introduction_node(david, &path);
-               assert_eq!(introduction_node_id, bob_id);
-               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
        }
 
        let payment_id = PaymentId([1; 32]);
@@ -427,11 +543,9 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
                        payer_note_truncated: None,
                },
        });
-       let introduction_node_id = resolve_introduction_node(alice, &reply_path);
        assert_eq!(invoice_request.amount_msats(), None);
        assert_ne!(invoice_request.payer_id(), david_id);
-       assert_eq!(introduction_node_id, charlie_id);
-       assert!(matches!(reply_path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+       assert_eq!(reply_path.introduction_node, IntroductionNode::NodeId(charlie_id));
 
        let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
        charlie.onion_messenger.handle_onion_message(&alice_id, &onion_message);
@@ -503,9 +617,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
        assert_ne!(refund.payer_id(), david_id);
        assert!(!refund.paths().is_empty());
        for path in refund.paths() {
-               let introduction_node_id = resolve_introduction_node(alice, &path);
-               assert_eq!(introduction_node_id, charlie_id);
-               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(charlie_id));
        }
        expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
 
@@ -555,15 +667,13 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
        let bob_id = bob.node.get_our_node_id();
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
        assert_ne!(offer.signing_pubkey(), Some(alice_id));
        assert!(!offer.paths().is_empty());
        for path in offer.paths() {
-               let introduction_node_id = resolve_introduction_node(bob, &path);
-               assert_eq!(introduction_node_id, alice_id);
-               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id));
        }
 
        let payment_id = PaymentId([1; 32]);
@@ -582,11 +692,9 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
                        payer_note_truncated: None,
                },
        });
-       let introduction_node_id = resolve_introduction_node(alice, &reply_path);
        assert_eq!(invoice_request.amount_msats(), None);
        assert_ne!(invoice_request.payer_id(), bob_id);
-       assert_eq!(introduction_node_id, bob_id);
-       assert!(matches!(reply_path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+       assert_eq!(reply_path.introduction_node, IntroductionNode::NodeId(bob_id));
 
        let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
        bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
@@ -634,9 +742,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
        assert_ne!(refund.payer_id(), bob_id);
        assert!(!refund.paths().is_empty());
        for path in refund.paths() {
-               let introduction_node_id = resolve_introduction_node(alice, &path);
-               assert_eq!(introduction_node_id, bob_id);
-               assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
+               assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
        }
        expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
 
@@ -681,7 +787,7 @@ fn pays_for_offer_without_blinded_paths() {
        let bob_id = bob.node.get_our_node_id();
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .clear_paths()
                .amount_msats(10_000_000)
                .build().unwrap();
@@ -769,7 +875,7 @@ fn fails_creating_offer_without_blinded_paths() {
 
        create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
 
-       match nodes[0].node.create_offer_builder() {
+       match nodes[0].node.create_offer_builder(None) {
                Ok(_) => panic!("Expected error"),
                Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
        }
@@ -798,6 +904,129 @@ fn fails_creating_refund_without_blinded_paths() {
        assert!(nodes[0].node.list_recent_payments().is_empty());
 }
 
+/// Fails creating or paying an offer when a blinded path cannot be created because no peers are
+/// connected.
+#[test]
+fn fails_creating_or_paying_for_offer_without_connected_peers() {
+       let chanmon_cfgs = create_chanmon_cfgs(6);
+       let node_cfgs = create_node_cfgs(6, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(6, &node_cfgs, &[None, None, None, None, None, None]);
+       let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
+
+       create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+       create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 4, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 5, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 2, 5, 10_000_000, 1_000_000_000);
+
+       let (alice, bob, charlie, david) = (&nodes[0], &nodes[1], &nodes[2], &nodes[3]);
+
+       disconnect_peers(alice, &[bob, charlie, david, &nodes[4], &nodes[5]]);
+       disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
+
+       let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
+       match alice.node.create_offer_builder(Some(absolute_expiry)) {
+               Ok(_) => panic!("Expected error"),
+               Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
+       }
+
+       let mut args = ReconnectArgs::new(alice, bob);
+       args.send_channel_ready = (true, true);
+       reconnect_nodes(args);
+
+       let offer = alice.node
+               .create_offer_builder(Some(absolute_expiry)).unwrap()
+               .amount_msats(10_000_000)
+               .build().unwrap();
+
+       let payment_id = PaymentId([1; 32]);
+
+       match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
+               Ok(_) => panic!("Expected error"),
+               Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
+       }
+
+       assert!(nodes[0].node.list_recent_payments().is_empty());
+
+       let mut args = ReconnectArgs::new(charlie, david);
+       args.send_channel_ready = (true, true);
+       reconnect_nodes(args);
+
+       assert!(
+               david.node.pay_for_offer(
+                       &offer, None, None, None, payment_id, Retry::Attempts(0), None
+               ).is_ok()
+       );
+
+       expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
+}
+
+/// Fails creating or sending an invoice for a refund when a blinded path cannot be created because
+/// no peers are connected.
+#[test]
+fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
+       let mut accept_forward_cfg = test_default_channel_config();
+       accept_forward_cfg.accept_forwards_to_priv_channels = true;
+
+       let mut features = channelmanager::provided_init_features(&accept_forward_cfg);
+       features.set_onion_messages_optional();
+       features.set_route_blinding_optional();
+
+       let chanmon_cfgs = create_chanmon_cfgs(6);
+       let node_cfgs = create_node_cfgs(6, &chanmon_cfgs);
+
+       *node_cfgs[1].override_init_features.borrow_mut() = Some(features);
+
+       let node_chanmgrs = create_node_chanmgrs(
+               6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None]
+       );
+       let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
+
+       create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
+       create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 4, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 5, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 10_000_000, 1_000_000_000);
+       create_announced_chan_between_nodes_with_value(&nodes, 2, 5, 10_000_000, 1_000_000_000);
+
+       let (alice, bob, charlie, david) = (&nodes[0], &nodes[1], &nodes[2], &nodes[3]);
+
+       disconnect_peers(alice, &[bob, charlie, david, &nodes[4], &nodes[5]]);
+       disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
+
+       let absolute_expiry = david.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
+       let payment_id = PaymentId([1; 32]);
+       match david.node.create_refund_builder(
+               10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
+       ) {
+               Ok(_) => panic!("Expected error"),
+               Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
+       }
+
+       let mut args = ReconnectArgs::new(charlie, david);
+       args.send_channel_ready = (true, true);
+       reconnect_nodes(args);
+
+       let refund = david.node
+               .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
+               .unwrap()
+               .build().unwrap();
+
+       match alice.node.request_refund_payment(&refund) {
+               Ok(_) => panic!("Expected error"),
+               Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
+       }
+
+       let mut args = ReconnectArgs::new(alice, bob);
+       args.send_channel_ready = (true, true);
+       reconnect_nodes(args);
+
+       assert!(alice.node.request_refund_payment(&refund).is_ok());
+}
+
 /// Fails creating an invoice request when the offer contains an unsupported chain.
 #[test]
 fn fails_creating_invoice_request_for_unsupported_chain() {
@@ -812,7 +1041,7 @@ fn fails_creating_invoice_request_for_unsupported_chain() {
        let bob = &nodes[1];
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .clear_chains()
                .chain(Network::Signet)
                .build().unwrap();
@@ -872,7 +1101,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() {
        disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
 
@@ -906,7 +1135,7 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() {
        disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]);
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
 
@@ -992,7 +1221,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
        disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
 
        let offer = alice.node
-               .create_offer_builder().unwrap()
+               .create_offer_builder(None).unwrap()
                .amount_msats(10_000_000)
                .build().unwrap();
 
index c5ce3e051fd42ef3b5bcd82af241fd31a8298d55..02109c888f5f16dda8bd09137e0cb989c3765d57 100644 (file)
@@ -180,11 +180,6 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(
                if expected_channel_update.is_some() {
                        match network_update {
                                Some(update) => match update {
-                                       &NetworkUpdate::ChannelUpdateMessage { .. } => {
-                                               if let NetworkUpdate::ChannelUpdateMessage { .. } = expected_channel_update.unwrap() {} else {
-                                                       panic!("channel_update not found!");
-                                               }
-                                       },
                                        &NetworkUpdate::ChannelFailure { ref short_channel_id, ref is_permanent } => {
                                                if let NetworkUpdate::ChannelFailure { short_channel_id: ref expected_short_channel_id, is_permanent: ref expected_is_permanent } = expected_channel_update.unwrap() {
                                                        assert!(*short_channel_id == *expected_short_channel_id);
@@ -300,12 +295,13 @@ fn test_fee_failures() {
        claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_success);
 
        // If the hop gives fee_insufficient but enough fees were provided, then the previous hop
-       // malleated the payment before forwarding, taking funds when they shouldn't have.
+       // malleated the payment before forwarding, taking funds when they shouldn't have. However,
+       // because we ignore channel update contents, we will still blame the 2nd channel.
        let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
-       let short_channel_id = channels[0].0.contents.short_channel_id;
+       let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
                msg.amount_msat -= 1;
-       }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id));
+       }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id));
 
        // In an earlier version, we spuriously failed to forward payments if the expected feerate
        // changed between the channel open and the payment.
@@ -478,7 +474,9 @@ fn test_onion_failure() {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
                let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data);
-       }, ||{}, true, Some(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: chan_update.clone()}), Some(short_channel_id));
+       }, ||{}, true, Some(UPDATE|7),
+       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+       Some(short_channel_id));
 
        // Check we can still handle onion failures that include channel updates without a type prefix
        let err_data_without_type = chan_update.encode_with_len();
@@ -488,7 +486,9 @@ fn test_onion_failure() {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
                let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data_without_type);
-       }, ||{}, true, Some(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: chan_update}), Some(short_channel_id));
+       }, ||{}, true, Some(UPDATE|7),
+       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+       Some(short_channel_id));
 
        let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test_with_fail_intercept("permanent_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
@@ -523,7 +523,9 @@ fn test_onion_failure() {
        let mut bogus_route = route.clone();
        let route_len = bogus_route.paths[0].hops.len();
        bogus_route.paths[0].hops[route_len-1].fee_msat = amt_to_forward;
-       run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(UPDATE|11), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id));
+       run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(UPDATE|11),
+               Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+               Some(short_channel_id));
 
        // Clear pending payments so that the following positive test has the correct payment hash.
        for node in nodes.iter() {
@@ -535,16 +537,18 @@ fn test_onion_failure() {
        let preimage = send_along_route(&nodes[0], bogus_route, &[&nodes[1], &nodes[2]], amt_to_forward+1).0;
        claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], preimage);
 
-       let short_channel_id = channels[0].0.contents.short_channel_id;
+       // We ignore channel update contents in onion errors, so will blame the 2nd channel even though
+       // the first node is the one that messed up.
+       let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
                msg.amount_msat -= 1;
-       }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id));
+       }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id));
 
-       let short_channel_id = channels[0].0.contents.short_channel_id;
+       let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test("incorrect_cltv_expiry", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
                // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value
                msg.cltv_expiry -= 1;
-       }, || {}, true, Some(UPDATE|13), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id));
+       }, || {}, true, Some(UPDATE|13), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id));
 
        let short_channel_id = channels[1].0.contents.short_channel_id;
        run_onion_failure_test("expiry_too_soon", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
@@ -552,7 +556,9 @@ fn test_onion_failure() {
                connect_blocks(&nodes[0], height - nodes[0].best_block_info().1);
                connect_blocks(&nodes[1], height - nodes[1].best_block_info().1);
                connect_blocks(&nodes[2], height - nodes[2].best_block_info().1);
-       }, ||{}, true, Some(UPDATE|14), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id));
+       }, ||{}, true, Some(UPDATE|14),
+       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+       Some(short_channel_id));
 
        run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
                nodes[2].node.fail_htlc_backwards(&payment_hash);
@@ -596,7 +602,9 @@ fn test_onion_failure() {
                // disconnect event to the channel between nodes[1] ~ nodes[2]
                nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
                nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
-       }, true, Some(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id));
+       }, true, Some(UPDATE|7),
+       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+       Some(short_channel_id));
        run_onion_failure_test("channel_disabled", 0, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
                // disconnect event to the channel between nodes[1] ~ nodes[2]
                for _ in 0..DISABLE_GOSSIP_TICKS + 1 {
@@ -605,7 +613,9 @@ fn test_onion_failure() {
                }
                nodes[1].node.get_and_clear_pending_msg_events();
                nodes[2].node.get_and_clear_pending_msg_events();
-       }, true, Some(UPDATE|20), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id));
+       }, true, Some(UPDATE|20),
+       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
+       Some(short_channel_id));
        reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[2]));
 
        run_onion_failure_test("expiry_too_far", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
@@ -844,9 +854,9 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) {
        // We'll be attempting to route payments using the default ChannelUpdate for channels. This will
        // lead to onion failures at the first hop once we update the ChannelConfig for the
        // second hop.
-       let expect_onion_failure = |name: &str, error_code: u16, channel_update: &msgs::ChannelUpdate| {
+       let expect_onion_failure = |name: &str, error_code: u16| {
                let short_channel_id = channel_to_update.1;
-               let network_update = NetworkUpdate::ChannelUpdateMessage { msg: channel_update.clone() };
+               let network_update = NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false };
                run_onion_failure_test(
                        name, 0, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {}, true,
                        Some(error_code), Some(network_update), Some(short_channel_id),
@@ -878,7 +888,7 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) {
        // Connect a block, which should expire the previous config, leading to a failure when
        // forwarding the HTLC.
        expire_prev_config();
-       expect_onion_failure("fee_insufficient", UPDATE|12, &msg);
+       expect_onion_failure("fee_insufficient", UPDATE|12);
 
        // Redundant updates should not trigger a new ChannelUpdate.
        assert!(update_and_get_channel_update(&config, false, None, false).is_none());
@@ -891,15 +901,15 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) {
        // new ChannelUpdate.
        config.forwarding_fee_base_msat = default_config.forwarding_fee_base_msat;
        config.cltv_expiry_delta = u16::max_value();
-       let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap();
-       expect_onion_failure("incorrect_cltv_expiry", UPDATE|13, &msg);
+       assert!(update_and_get_channel_update(&config, true, Some(&msg), true).is_some());
+       expect_onion_failure("incorrect_cltv_expiry", UPDATE|13);
 
        // Reset the proportional fee and increase the CLTV expiry delta which should trigger a new
        // ChannelUpdate.
        config.cltv_expiry_delta = default_config.cltv_expiry_delta;
        config.forwarding_fee_proportional_millionths = u32::max_value();
-       let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap();
-       expect_onion_failure("fee_insufficient", UPDATE|12, &msg);
+       assert!(update_and_get_channel_update(&config, true, Some(&msg), true).is_some());
+       expect_onion_failure("fee_insufficient", UPDATE|12);
 
        // To test persistence of the updated config, we'll re-initialize the ChannelManager.
        let config_after_restart = {
@@ -1530,10 +1540,10 @@ fn do_test_phantom_dust_exposure_failure(multiplier_dust_limit: bool) {
        err_data.extend_from_slice(&channel.1.encode());
 
        let mut fail_conditions = PaymentFailedConditions::new()
-               .blamed_scid(channel.0.contents.short_channel_id)
+               .blamed_scid(route.paths[0].hops.last().as_ref().unwrap().short_channel_id)
                .blamed_chan_closed(false)
                .expected_htlc_error_data(0x1000 | 7, &err_data);
-               expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions);
+       expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions);
 }
 
 #[test]
index 9a207c9e52d1dd1805592bf039dd9ff84387a6b4..fab73cf73ec4320cfbe499a29d947ce168b5ad41 100644 (file)
@@ -15,7 +15,6 @@ use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
 use crate::ln::features::{ChannelFeatures, NodeFeatures};
 use crate::ln::msgs;
 use crate::ln::types::{PaymentHash, PaymentPreimage};
-use crate::ln::wire::Encode;
 use crate::routing::gossip::NetworkUpdate;
 use crate::routing::router::{Path, RouteHop, RouteParameters};
 use crate::sign::NodeSigner;
@@ -806,106 +805,16 @@ where
                        {
                                let update_len =
                                        u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
-                               if let Some(mut update_slice) = err_packet
+                               if err_packet
                                        .failuremsg
                                        .get(debug_field_size + 4..debug_field_size + 4 + update_len)
+                                       .is_some()
                                {
-                                       // Historically, the BOLTs were unclear if the message type
-                                       // bytes should be included here or not. The BOLTs have now
-                                       // been updated to indicate that they *are* included, but many
-                                       // nodes still send messages without the type bytes, so we
-                                       // support both here.
-                                       // TODO: Switch to hard require the type prefix, as the current
-                                       // permissiveness introduces the (although small) possibility
-                                       // that we fail to decode legitimate channel updates that
-                                       // happen to start with ChannelUpdate::TYPE, i.e., [0x01, 0x02].
-                                       if update_slice.len() > 2
-                                               && update_slice[0..2] == msgs::ChannelUpdate::TYPE.to_be_bytes()
-                                       {
-                                               update_slice = &update_slice[2..];
-                                       } else {
-                                               log_trace!(logger, "Failure provided features a channel update without type prefix. Deprecated, but allowing for now.");
-                                       }
-                                       let update_opt = msgs::ChannelUpdate::read(&mut Cursor::new(&update_slice));
-                                       if update_opt.is_ok() || update_slice.is_empty() {
-                                               // if channel_update should NOT have caused the failure:
-                                               // MAY treat the channel_update as invalid.
-                                               let is_chan_update_invalid = match error_code & 0xff {
-                                                       7 => false,
-                                                       11 => {
-                                                               update_opt.is_ok()
-                                                                       && amt_to_forward
-                                                                               > update_opt.as_ref().unwrap().contents.htlc_minimum_msat
-                                                       },
-                                                       12 => {
-                                                               update_opt.is_ok()
-                                                                       && amt_to_forward
-                                                                               .checked_mul(
-                                                                                       update_opt
-                                                                                               .as_ref()
-                                                                                               .unwrap()
-                                                                                               .contents
-                                                                                               .fee_proportional_millionths as u64,
-                                                                               )
-                                                                               .map(|prop_fee| prop_fee / 1_000_000)
-                                                                               .and_then(|prop_fee| {
-                                                                                       prop_fee.checked_add(
-                                                                                               update_opt.as_ref().unwrap().contents.fee_base_msat
-                                                                                                       as u64,
-                                                                                       )
-                                                                               })
-                                                                               .map(|fee_msats| route_hop.fee_msat >= fee_msats)
-                                                                               .unwrap_or(false)
-                                                       },
-                                                       13 => {
-                                                               update_opt.is_ok()
-                                                                       && route_hop.cltv_expiry_delta as u16
-                                                                               >= update_opt.as_ref().unwrap().contents.cltv_expiry_delta
-                                                       },
-                                                       14 => false, // expiry_too_soon; always valid?
-                                                       20 => update_opt.as_ref().unwrap().contents.flags & 2 == 0,
-                                                       _ => false, // unknown error code; take channel_update as valid
-                                               };
-                                               if is_chan_update_invalid {
-                                                       // This probably indicates the node which forwarded
-                                                       // to the node in question corrupted something.
-                                                       network_update = Some(NetworkUpdate::ChannelFailure {
-                                                               short_channel_id: route_hop.short_channel_id,
-                                                               is_permanent: true,
-                                                       });
-                                               } else {
-                                                       if let Ok(chan_update) = update_opt {
-                                                               // Make sure the ChannelUpdate contains the expected
-                                                               // short channel id.
-                                                               if failing_route_hop.short_channel_id
-                                                                       == chan_update.contents.short_channel_id
-                                                               {
-                                                                       short_channel_id = Some(failing_route_hop.short_channel_id);
-                                                               } else {
-                                                                       log_info!(logger, "Node provided a channel_update for which it was not authoritative, ignoring.");
-                                                               }
-                                                               network_update =
-                                                                       Some(NetworkUpdate::ChannelUpdateMessage { msg: chan_update })
-                                                       } else {
-                                                               // The node in question intentionally encoded a 0-length channel update. This is
-                                                               // likely due to https://github.com/ElementsProject/lightning/issues/6200.
-                                                               short_channel_id = Some(failing_route_hop.short_channel_id);
-                                                               network_update = Some(NetworkUpdate::ChannelFailure {
-                                                                       short_channel_id: failing_route_hop.short_channel_id,
-                                                                       is_permanent: false,
-                                                               });
-                                                       }
-                                               };
-                                       } else {
-                                               // If the channel_update had a non-zero length (i.e. was
-                                               // present) but we couldn't read it, treat it as a total
-                                               // node failure.
-                                               log_info!(
-                                                       logger,
-                                                       "Failed to read a channel_update of len {} in an onion",
-                                                       update_slice.len()
-                                               );
-                                       }
+                                       network_update = Some(NetworkUpdate::ChannelFailure {
+                                               short_channel_id: failing_route_hop.short_channel_id,
+                                               is_permanent: false,
+                                       });
+                                       short_channel_id = Some(failing_route_hop.short_channel_id);
                                }
                        }
                        if network_update.is_none() {
index b08a1e8a9bb1e3a565fcaf9c43492a9f22167c65..2a9e52c83c7b21341610994536c94788259dd6bf 100644 (file)
@@ -16,7 +16,8 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
 use crate::sign::{EntropySource, NodeSigner, Recipient};
 use crate::events::{self, PaymentFailureReason};
 use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret};
-use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId};
+use crate::ln::channel_state::ChannelDetails;
+use crate::ln::channelmanager::{EventCompletionAction, HTLCSource, PaymentId};
 use crate::ln::onion_utils;
 use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
 use crate::offers::invoice::Bolt12Invoice;
@@ -1850,7 +1851,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
 
 #[cfg(test)]
 mod tests {
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
 
        use core::time::Duration;
index 2fc21eb23853612aa4518c09cc81b49cf3098d45..487fb83c158f8f2a2c364467ac57a0c982eba37d 100644 (file)
@@ -34,7 +34,7 @@ use crate::util::string::UntrustedString;
 
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::{Secp256k1, SecretKey};
 
 use crate::prelude::*;
@@ -160,7 +160,9 @@ fn mpp_retry() {
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+       );
 }
 
 #[test]
@@ -351,7 +353,9 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) {
                        nodes[3].node.timer_tick_occurred();
                }
 
-               claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+               claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+               );
        }
 }
 
@@ -466,7 +470,9 @@ fn test_mpp_keysend() {
        let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
        pass_along_path(&nodes[0], expected_route[1], recv_value, payment_hash.clone(),
                Some(payment_secret), ev.clone(), true, Some(payment_preimage));
-       claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage)
+       );
 }
 
 #[test]
@@ -817,7 +823,9 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
-       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       do_claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+       );
        expect_payment_sent!(nodes[0], payment_preimage, Some(new_route.paths[0].hops[0].fee_msat));
 }
 
@@ -1048,11 +1056,12 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
+       let error_message = "Channel force-closed";
 
        // Route a payment, but force-close the channel before the HTLC fulfill message arrives at
        // nodes[0].
        let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000);
-       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[0], true);
        check_added_monitors!(nodes[0], 1);
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
@@ -1245,7 +1254,9 @@ fn get_ldk_payment_preimage() {
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
        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);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+       );
 }
 
 #[test]
@@ -1579,7 +1590,9 @@ fn claimed_send_payment_idempotent() {
        // Claim the payment backwards, but note that the PaymentSent event is still pending and has
        // not been seen by the user. At this point, from the user perspective nothing has changed, so
        // we must remain just as idempotent as we were before.
-       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, first_payment_preimage);
+       do_claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], first_payment_preimage)
+       );
 
        for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
                nodes[0].node.timer_tick_occurred();
@@ -1980,7 +1993,9 @@ fn do_test_intercepted_payment(test: InterceptTest) {
 
                let payment_preimage = nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
                expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, Some(payment_preimage), nodes[2].node.get_our_node_id());
-               do_claim_payment_along_route(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, payment_preimage);
+               do_claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+               );
                let events = nodes[0].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 2);
                match events[0] {
@@ -2270,7 +2285,9 @@ fn do_automatic_retries(test: AutoRetry) {
                let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(msg_events.len(), 1);
                pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None);
-               claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+               claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+               );
        } else if test == AutoRetry::Spontaneous {
                nodes[0].node.send_spontaneous_payment_with_retry(Some(payment_preimage),
                        RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params,
@@ -2287,7 +2304,9 @@ fn do_automatic_retries(test: AutoRetry) {
                let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(msg_events.len(), 1);
                pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, None, msg_events.pop().unwrap(), true, Some(payment_preimage));
-               claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+               claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+               );
        } else if test == AutoRetry::FailAttempts {
                // Ensure ChannelManager will not retry a payment if it has run out of payment attempts.
                nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
@@ -3581,6 +3600,7 @@ fn do_claim_from_closed_chan(fail_payment: bool) {
        // height.
        connect_blocks(&nodes[3], final_cltv - HTLC_FAIL_BACK_BUFFER - nodes[3].best_block_info().1
                - if fail_payment { 0 } else { 2 });
+       let error_message = "Channel force-closed";
        if fail_payment {
                // We fail the HTLC on the A->B->D path first as it expires 4 blocks earlier. We go ahead
                // and expire both immediately, though, by connecting another 4 blocks.
@@ -3590,7 +3610,7 @@ fn do_claim_from_closed_chan(fail_payment: bool) {
                expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[3], [reason]);
                pass_failed_payment_back(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash, PaymentFailureReason::RecipientRejected);
        } else {
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id()).unwrap();
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed, false,
                        [nodes[3].node.get_our_node_id()], 1000000);
                check_closed_broadcast(&nodes[1], 1, true);
@@ -3714,11 +3734,17 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) {
        match (known_tlvs, even_tlvs) {
                (true, _) => {
                        nodes[1].node.claim_funds_with_known_custom_tlvs(our_payment_preimage);
-                       let expected_total_fee_msat = pass_claimed_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage));
+                       let expected_total_fee_msat = pass_claimed_payment_along_route(
+                               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage)
+                                       .with_custom_tlvs(custom_tlvs)
+                       );
                        expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat));
                },
                (false, false) => {
-                       claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
+                       claim_payment_along_route(
+                               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage)
+                                       .with_custom_tlvs(custom_tlvs)
+                       );
                },
                (false, true) => {
                        nodes[1].node.claim_funds(our_payment_preimage);
@@ -3805,9 +3831,12 @@ fn test_retry_custom_tlvs() {
        let path = &[&nodes[1], &nodes[2]];
        let args = PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap())
                .with_payment_secret(payment_secret)
-               .with_custom_tlvs(custom_tlvs);
+               .with_custom_tlvs(custom_tlvs.clone());
        do_pass_along_path(args);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       claim_payment_along_route(
+               ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+                       .with_custom_tlvs(custom_tlvs)
+       );
 }
 
 #[test]
@@ -3938,8 +3967,10 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec<u8>)>, second_tlvs:
                        _ => panic!("Unexpected event"),
                }
 
-               do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]],
-                       false, our_payment_preimage);
+               do_claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage)
+                               .with_custom_tlvs(expected_tlvs)
+               );
                expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true, true);
        } else {
                // Expect fail back
@@ -4102,7 +4133,9 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) {
        } else {
                expect_pending_htlcs_forwardable!(nodes[3]);
                expect_payment_claimable!(nodes[3], payment_hash, payment_secret, amt_msat);
-               claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+               claim_payment_along_route(
+                       ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+               );
        }
 }
 
index f31a8e131e0469d49273713fd3c9d2b32e0319e3..448dd213dad553ba8143e15b9d32cbea2fb1464c 100644 (file)
@@ -19,11 +19,11 @@ use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
 
 use crate::sign::{NodeSigner, Recipient};
-use crate::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
+use crate::events::{MessageSendEvent, MessageSendEventsProvider};
 use crate::ln::types::ChannelId;
 use crate::ln::features::{InitFeatures, NodeFeatures};
 use crate::ln::msgs;
-use crate::ln::msgs::{ChannelMessageHandler, LightningError, SocketAddress, OnionMessageHandler, RoutingMessageHandler};
+use crate::ln::msgs::{ChannelMessageHandler, Init, LightningError, SocketAddress, OnionMessageHandler, RoutingMessageHandler};
 use crate::util::ser::{VecWriter, Writeable, Writer};
 use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE};
 use crate::ln::wire;
@@ -79,6 +79,16 @@ pub trait CustomMessageHandler: wire::CustomMessageReader {
        /// connection to the node exists, then the message is simply not sent.
        fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)>;
 
+       /// Indicates a peer disconnected.
+       fn peer_disconnected(&self, their_node_id: &PublicKey);
+
+       /// Handle a peer connecting.
+       ///
+       /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
+       /// with us. Implementors should be somewhat conservative about doing so, however, as other
+       /// message handlers may still wish to communicate with this peer.
+       fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init, inbound: bool) -> Result<(), ()>;
+
        /// Gets the node feature flags which this handler itself supports. All available handlers are
        /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`]
        /// which are broadcasted in our [`NodeAnnouncement`] message.
@@ -97,9 +107,6 @@ pub trait CustomMessageHandler: wire::CustomMessageReader {
 /// A dummy struct which implements `RoutingMessageHandler` without storing any routing information
 /// or doing any processing. You can provide one of these as the route_handler in a MessageHandler.
 pub struct IgnoringMessageHandler{}
-impl EventsProvider for IgnoringMessageHandler {
-       fn process_pending_events<H: Deref>(&self, _handler: H) where H::Target: EventHandler {}
-}
 impl MessageSendEventsProvider for IgnoringMessageHandler {
        fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent> { Vec::new() }
 }
@@ -193,6 +200,10 @@ impl CustomMessageHandler for IgnoringMessageHandler {
 
        fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { Vec::new() }
 
+       fn peer_disconnected(&self, _their_node_id: &PublicKey) {}
+
+       fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
+
        fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
 
        fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
@@ -723,8 +734,6 @@ pub trait APeerManager {
        type NS: Deref<Target=Self::NST>;
        /// Gets a reference to the underlying [`PeerManager`].
        fn as_ref(&self) -> &PeerManager<Self::Descriptor, Self::CM, Self::RM, Self::OM, Self::L, Self::CMH, Self::NS>;
-       /// Returns the peer manager's [`OnionMessageHandler`].
-       fn onion_message_handler(&self) -> &Self::OMT;
 }
 
 impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CMH: Deref, NS: Deref>
@@ -750,9 +759,6 @@ APeerManager for PeerManager<Descriptor, CM, RM, OM, L, CMH, NS> where
        type NST = <NS as Deref>::Target;
        type NS = NS;
        fn as_ref(&self) -> &PeerManager<Descriptor, CM, RM, OM, L, CMH, NS> { self }
-       fn onion_message_handler(&self) -> &Self::OMT {
-               self.message_handler.onion_message_handler.deref()
-       }
 }
 
 /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
@@ -1654,12 +1660,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                        let our_features = self.init_features(&their_node_id);
                        if msg.features.requires_unknown_bits_from(&our_features) {
-                               log_debug!(logger, "Peer requires features unknown to us");
+                               log_debug!(logger, "Peer {} requires features unknown to us: {:?}",
+                                       log_pubkey!(their_node_id), msg.features.required_unknown_bits_from(&our_features));
                                return Err(PeerHandleError { }.into());
                        }
 
                        if our_features.requires_unknown_bits_from(&msg.features) {
-                               log_debug!(logger, "We require features unknown to our peer");
+                               log_debug!(logger, "We require features unknown to our peer {}: {:?}",
+                                       log_pubkey!(their_node_id), our_features.required_unknown_bits_from(&msg.features));
                                return Err(PeerHandleError { }.into());
                        }
 
@@ -1686,6 +1694,10 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                log_debug!(logger, "Onion Message Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
                                return Err(PeerHandleError { }.into());
                        }
+                       if let Err(()) = self.message_handler.custom_message_handler.peer_connected(&their_node_id, &msg, peer_lock.inbound_connection) {
+                               log_debug!(logger, "Custom Message Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
+                               return Err(PeerHandleError { }.into());
+                       }
 
                        peer_lock.awaiting_pong_timer_tick_intervals = 0;
                        peer_lock.their_features = Some(msg.features);
@@ -2436,6 +2448,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        log_trace!(WithContext::from(&self.logger, Some(node_id), None, None), "Disconnecting peer with id {} due to {}", node_id, reason);
                        self.message_handler.chan_handler.peer_disconnected(&node_id);
                        self.message_handler.onion_message_handler.peer_disconnected(&node_id);
+                       self.message_handler.custom_message_handler.peer_disconnected(&node_id);
                }
                descriptor.disconnect_socket();
        }
@@ -2458,6 +2471,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        if !peer.handshake_complete() { return; }
                                        self.message_handler.chan_handler.peer_disconnected(&node_id);
                                        self.message_handler.onion_message_handler.peer_disconnected(&node_id);
+                                       self.message_handler.custom_message_handler.peer_disconnected(&node_id);
                                }
                        }
                };
@@ -2686,7 +2700,7 @@ mod tests {
        use crate::ln::peer_channel_encryptor::PeerChannelEncryptor;
        use crate::ln::peer_handler::{CustomMessageHandler, PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler, filter_addresses, ErroringMessageHandler, MAX_BUFFER_DRAIN_TICK_INTERVALS_PER_PEER};
        use crate::ln::{msgs, wire};
-       use crate::ln::msgs::{LightningError, SocketAddress};
+       use crate::ln::msgs::{Init, LightningError, SocketAddress};
        use crate::util::test_utils;
 
        use bitcoin::Network;
@@ -2753,6 +2767,11 @@ mod tests {
 
                fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { Vec::new() }
 
+
+               fn peer_disconnected(&self, _their_node_id: &PublicKey) {}
+
+               fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
+
                fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
 
                fn provided_init_features(&self, _: &PublicKey) -> InitFeatures {
index fba97eae382905d8d28f544b6afc65897f440ecc..f677b292e92cc795bc3685ce908543208e3442ea 100644 (file)
@@ -31,7 +31,7 @@ use crate::prelude::*;
 use crate::ln::functional_test_utils::*;
 
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 
 #[test]
 fn test_priv_forwarding_rejection() {
@@ -754,6 +754,7 @@ fn test_0conf_close_no_early_chan_update() {
 
        let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(chan_config)]);
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+       let error_message = "Channel force-closed";
 
        // This is the default but we force it on anyway
        chan_config.channel_handshake_config.announced_channel = true;
@@ -762,7 +763,7 @@ fn test_0conf_close_no_early_chan_update() {
        // We can use the channel immediately, but won't generate a channel_update until we get confs
        send_payment(&nodes[0], &[&nodes[1]], 100_000);
 
-       nodes[0].node.force_close_all_channels_broadcasting_latest_txn();
+       nodes[0].node.force_close_all_channels_broadcasting_latest_txn(error_message.to_string());
        check_added_monitors!(nodes[0], 1);
        check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
        let _ = get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id());
index 36b620c6bab7bb21317ee04cf5e42174463c5a1b..4c32a0bd0700730f3046c2976cb1ab617e58d5ef 100644 (file)
@@ -628,9 +628,10 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool,
                        std::mem::forget(nodes);
                }
        } else {
+               let error_message = "Channel force-closed";
                assert!(!not_stale, "We only care about the stale case when not testing panicking");
 
-               nodes[0].node.force_close_without_broadcasting_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
+               nodes[0].node.force_close_without_broadcasting_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_added_monitors!(nodes[0], 1);
                check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 1000000);
                {
@@ -642,8 +643,8 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool,
                        if let MessageSendEvent::BroadcastChannelUpdate { .. } = msg {
                        } else if let MessageSendEvent::HandleError { ref action, .. } = msg {
                                match action {
-                                       &ErrorAction::DisconnectPeer { ref msg } => {
-                                               assert_eq!(msg.as_ref().unwrap().data, "Channel force-closed");
+                                       &ErrorAction::SendErrorMessage { ref msg } => {
+                                               assert_eq!(&msg.data, "Channel force-closed");
                                        },
                                        _ => panic!("Unexpected event!"),
                                }
@@ -1025,8 +1026,9 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht
        assert!(nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
 
        let _ = nodes[2].node.get_and_clear_pending_msg_events();
+       let error_message = "Channel force-closed";
 
-       nodes[2].node.force_close_broadcasting_latest_txn(&chan_id_2, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[2].node.force_close_broadcasting_latest_txn(&chan_id_2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        let cs_commitment_tx = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
        assert_eq!(cs_commitment_tx.len(), if claim_htlc { 2 } else { 1 });
 
index 571521291b69c7ab533c284408013c82ef7d6967..efc07588be20f9cfc293ad12435bd2b3b82074db 100644 (file)
@@ -200,7 +200,7 @@ fn test_counterparty_revoked_reorg() {
        let mut unrevoked_local_txn = get_local_commitment_txn!(nodes[0], chan.2);
        assert_eq!(unrevoked_local_txn.len(), 3); // commitment + 2 HTLC txn
        // Sort the unrevoked transactions in reverse order, ie commitment tx, then HTLC 1 then HTLC 3
-       unrevoked_local_txn.sort_unstable_by_key(|tx| 1_000_000 - tx.output.iter().map(|outp| outp.value).sum::<u64>());
+       unrevoked_local_txn.sort_unstable_by_key(|tx| 1_000_000 - tx.output.iter().map(|outp| outp.value.to_sat()).sum::<u64>());
 
        // Now mine A's old commitment transaction, which should close the channel, but take no action
        // on any of the HTLCs, at least until we get six confirmations (which we won't get).
@@ -637,15 +637,16 @@ fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reor
 
        // Route an HTLC which we will claim onchain with the preimage.
        let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       let error_message = "Channel force-closed";
 
        // Force close with the latest counterparty commitment, confirm it, and reorg it with the latest
        // holder commitment.
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast(&nodes[0], 1, true);
        check_added_monitors(&nodes[0], 1);
        check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
 
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast(&nodes[1], 1, true);
        check_added_monitors(&nodes[1], 1);
        check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000);
@@ -720,9 +721,10 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa
        // commitment is still valid (unrevoked).
        nodes[1].node().handle_update_fee(&nodes[0].node.get_our_node_id(), &update_fee);
        let _last_revoke_and_ack = commitment_signed_dance!(nodes[1], nodes[0], commit_sig, false, true, false, true);
+       let error_message = "Channel force-closed";
 
        // Force close with the latest commitment, confirm it, and reorg it with the previous commitment.
-       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast(&nodes[0], 1, true);
        check_added_monitors(&nodes[0], 1);
        check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
@@ -785,6 +787,7 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c
 
        // Route a payment so we have an HTLC to claim as well.
        let _ = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       let error_message = "Channel force-closed";
 
        if revoked_counterparty_commitment {
                // Trigger a fee update such that we advance the state. We will have B broadcast its state
@@ -827,7 +830,7 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c
        };
 
        // B will also broadcast its own commitment.
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast(&nodes[1], 1, true);
        check_added_monitors(&nodes[1], 1);
        check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100_000);
index 1909eb0c5f7df5f347ea0484bfbdd08fa8a239f8..ef75bb581b48b61ba4b63f4f5695989697981823 100644 (file)
@@ -1,11 +1,10 @@
 //! Abstractions for scripts used in the Lightning Network.
 
+use bitcoin::{WitnessProgram, WPubkeyHash, WScriptHash};
 use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0 as SEGWIT_V0;
 use bitcoin::blockdata::script::{Script, ScriptBuf};
 use bitcoin::hashes::Hash;
-use bitcoin::hash_types::{WPubkeyHash, WScriptHash};
 use bitcoin::secp256k1::PublicKey;
-use bitcoin::address::WitnessProgram;
 
 use crate::ln::channelmanager;
 use crate::ln::features::InitFeatures;
@@ -67,12 +66,12 @@ impl ShutdownScript {
 
        /// Generates a P2WPKH script pubkey from the given [`WPubkeyHash`].
        pub fn new_p2wpkh(pubkey_hash: &WPubkeyHash) -> Self {
-               Self(ShutdownScriptImpl::Bolt2(ScriptBuf::new_v0_p2wpkh(pubkey_hash)))
+               Self(ShutdownScriptImpl::Bolt2(ScriptBuf::new_p2wpkh(pubkey_hash)))
        }
 
        /// Generates a P2WSH script pubkey from the given [`WScriptHash`].
        pub fn new_p2wsh(script_hash: &WScriptHash) -> Self {
-               Self(ShutdownScriptImpl::Bolt2(ScriptBuf::new_v0_p2wsh(script_hash)))
+               Self(ShutdownScriptImpl::Bolt2(ScriptBuf::new_p2wsh(script_hash)))
        }
 
        /// Generates a witness script pubkey from the given segwit version and program.
@@ -114,7 +113,7 @@ impl ShutdownScript {
 /// Check if a given script is compliant with BOLT 2's shutdown script requirements for the given
 /// counterparty features.
 pub(crate) fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bool {
-       if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wpkh() || script.is_v0_p2wsh() {
+       if script.is_p2pkh() || script.is_p2sh() || script.is_p2wpkh() || script.is_p2wsh() {
                true
        } else if features.supports_shutdown_anysegwit() {
                script.is_witness_program() && script.as_bytes()[0] != SEGWIT_V0.to_u8()
@@ -151,7 +150,7 @@ impl Into<ScriptBuf> for ShutdownScript {
        fn into(self) -> ScriptBuf {
                match self.0 {
                        ShutdownScriptImpl::Legacy(pubkey) =>
-                               ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pubkey.serialize())),
+                               ScriptBuf::new_p2wpkh(&WPubkeyHash::hash(&pubkey.serialize())),
                        ShutdownScriptImpl::Bolt2(script_pubkey) => script_pubkey,
                }
        }
@@ -170,7 +169,7 @@ impl core::fmt::Display for ShutdownScript{
 mod shutdown_script_tests {
        use super::ShutdownScript;
 
-       use bitcoin::address::{WitnessProgram, WitnessVersion};
+       use bitcoin::{WitnessProgram, WitnessVersion};
        use bitcoin::blockdata::opcodes;
        use bitcoin::blockdata::script::{Builder, ScriptBuf};
        use bitcoin::secp256k1::Secp256k1;
@@ -206,7 +205,7 @@ mod shutdown_script_tests {
        fn generates_p2wpkh_from_pubkey() {
                let pubkey = pubkey();
                let pubkey_hash = pubkey.wpubkey_hash().unwrap();
-               let p2wpkh_script = ScriptBuf::new_v0_p2wpkh(&pubkey_hash);
+               let p2wpkh_script = ScriptBuf::new_p2wpkh(&pubkey_hash);
 
                let shutdown_script = ShutdownScript::new_p2wpkh_from_pubkey(pubkey.inner);
                assert!(shutdown_script.is_compatible(&any_segwit_features()));
@@ -217,7 +216,7 @@ mod shutdown_script_tests {
        #[test]
        fn generates_p2wpkh_from_pubkey_hash() {
                let pubkey_hash = pubkey().wpubkey_hash().unwrap();
-               let p2wpkh_script = ScriptBuf::new_v0_p2wpkh(&pubkey_hash);
+               let p2wpkh_script = ScriptBuf::new_p2wpkh(&pubkey_hash);
 
                let shutdown_script = ShutdownScript::new_p2wpkh(&pubkey_hash);
                assert!(shutdown_script.is_compatible(&any_segwit_features()));
@@ -229,7 +228,7 @@ mod shutdown_script_tests {
        #[test]
        fn generates_p2wsh_from_script_hash() {
                let script_hash = redeem_script().wscript_hash();
-               let p2wsh_script = ScriptBuf::new_v0_p2wsh(&script_hash);
+               let p2wsh_script = ScriptBuf::new_p2wsh(&script_hash);
 
                let shutdown_script = ShutdownScript::new_p2wsh(&script_hash);
                assert!(shutdown_script.is_compatible(&any_segwit_features()));
index 12421ce9c3f6323e31747173d4064572f5ae1198..0e03fd8db139353001f8fe1b0f12e717a213e49b 100644 (file)
@@ -14,7 +14,8 @@ use crate::sign::{EntropySource, SignerProvider};
 use crate::chain::ChannelMonitorUpdateStatus;
 use crate::chain::transaction::OutPoint;
 use crate::events::{Event, MessageSendEvent, HTLCDestination, MessageSendEventsProvider, ClosureReason};
-use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry, ChannelShutdownState, ChannelDetails};
+use crate::ln::channel_state::{ChannelDetails, ChannelShutdownState};
+use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry};
 use crate::routing::router::{PaymentParameters, get_route, RouteParameters};
 use crate::ln::msgs;
 use crate::ln::types::ChannelId;
@@ -28,12 +29,13 @@ use crate::util::config::UserConfig;
 use crate::util::string::UntrustedString;
 use crate::prelude::*;
 
-use bitcoin::{Transaction, TxOut};
+use bitcoin::{Transaction, TxOut, WitnessProgram, WitnessVersion};
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::script::Builder;
 use bitcoin::blockdata::opcodes;
-use bitcoin::network::constants::Network;
-use bitcoin::address::{WitnessProgram, WitnessVersion};
+use bitcoin::network::Network;
+use bitcoin::transaction::Version;
 
 use crate::ln::functional_test_utils::*;
 
@@ -300,11 +302,12 @@ fn expect_channel_shutdown_state_with_force_closure() {
        let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
        let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+       let error_message = "Channel force-closed";
 
        expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown);
        expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown);
 
-       nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
        check_closed_broadcast!(nodes[1], true);
        check_added_monitors!(nodes[1], 1);
 
@@ -1169,17 +1172,17 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) {
        assert_eq!(txn[0].output.len(), 2);
 
        if timeout_step != TimeoutStep::NoTimeout {
-               assert!((txn[0].output[0].script_pubkey.is_v0_p2wpkh() &&
-                        txn[0].output[1].script_pubkey.is_v0_p2wsh()) ||
-                       (txn[0].output[1].script_pubkey.is_v0_p2wpkh() &&
-                        txn[0].output[0].script_pubkey.is_v0_p2wsh()));
+               assert!((txn[0].output[0].script_pubkey.is_p2wpkh() &&
+                        txn[0].output[1].script_pubkey.is_p2wsh()) ||
+                       (txn[0].output[1].script_pubkey.is_p2wpkh() &&
+                        txn[0].output[0].script_pubkey.is_p2wsh()));
                check_closed_broadcast!(nodes[1], true);
                check_added_monitors!(nodes[1], 1);
                check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "closing_signed negotiation failed to finish within two timer ticks".to_string() }
                        , [nodes[0].node.get_our_node_id()], 100000);
        } else {
-               assert!(txn[0].output[0].script_pubkey.is_v0_p2wpkh());
-               assert!(txn[0].output[1].script_pubkey.is_v0_p2wpkh());
+               assert!(txn[0].output[0].script_pubkey.is_p2wpkh());
+               assert!(txn[0].output[1].script_pubkey.is_p2wpkh());
 
                let events = nodes[1].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@ -1409,12 +1412,12 @@ fn batch_funding_failure() {
        assert_eq!(events.len(), 2);
        // Build a transaction which only has the output for one of the two channels we're trying to
        // confirm. Previously this led to a deadlock in channel closure handling.
-       let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+       let mut tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
        let mut chans = Vec::new();
        for (idx, ev) in events.iter().enumerate() {
                if let Event::FundingGenerationReady { temporary_channel_id, counterparty_node_id, output_script, .. } = ev {
                        if idx == 0 {
-                               tx.output.push(TxOut { value: 1_000_000, script_pubkey: output_script.clone() });
+                               tx.output.push(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: output_script.clone() });
                        }
                        chans.push((temporary_channel_id, counterparty_node_id));
                } else { panic!(); }
index 5966b37116479abad227d5c896784ca2c028584f..c6fa5986764d4ec717ebc3b7489bf0da343d5724 100644 (file)
@@ -162,8 +162,7 @@ impl From<PaymentPreimage> for PaymentHash {
 #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd)]
 pub struct PaymentSecret(pub [u8; 32]);
 
-use bitcoin::bech32;
-use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5};
+use bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5};
 
 impl FromBase32 for PaymentSecret {
        type Err = bech32::Error;
index ecb0c80061ba3851b3975373b099111f9eb4ebf0..5482e6f83ea48e4139beb6b1d367aba55e5851eb 100644 (file)
@@ -21,7 +21,7 @@
 //! extern crate lightning;
 //!
 //! use bitcoin::hashes::Hash;
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use core::convert::TryFrom;
 //! use lightning::offers::invoice::UnsignedBolt12Invoice;
 //! use lightning::offers::invoice_request::InvoiceRequest;
@@ -39,7 +39,7 @@
 //! let payment_paths = create_payment_paths();
 //! let payment_hash = create_payment_hash();
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
 //! let pubkey = PublicKey::from(keys);
 //! let wpubkey_hash = bitcoin::key::PublicKey::new(pubkey).wpubkey_hash().unwrap();
 //! let mut buffer = Vec::new();
@@ -71,7 +71,7 @@
 //! # let payment_paths = create_payment_paths();
 //! # let payment_hash = create_payment_hash();
 //! # let secp_ctx = Secp256k1::new();
-//! # let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
+//! # let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
 //! # let pubkey = PublicKey::from(keys);
 //! # let wpubkey_hash = bitcoin::key::PublicKey::new(pubkey).wpubkey_hash().unwrap();
 //! # let mut buffer = Vec::new();
 //!
 //! ```
 
+use bitcoin::{WitnessProgram, Network, WitnessVersion, WPubkeyHash, WScriptHash};
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::hash_types::{WPubkeyHash, WScriptHash};
-use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self};
 use bitcoin::secp256k1::schnorr::Signature;
-use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion};
+use bitcoin::address::{Address, Payload};
 use bitcoin::key::TweakedPublicKey;
 use core::time::Duration;
 use core::hash::{Hash, Hasher};
@@ -201,7 +200,7 @@ pub struct ExplicitSigningPubkey {}
 /// [`Bolt12Invoice::signing_pubkey`] was derived.
 ///
 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
-pub struct DerivedSigningPubkey(KeyPair);
+pub struct DerivedSigningPubkey(Keypair);
 
 impl SigningPubkeyStrategy for ExplicitSigningPubkey {}
 impl SigningPubkeyStrategy for DerivedSigningPubkey {}
@@ -268,7 +267,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
        #[cfg_attr(c_bindings, allow(dead_code))]
        pub(super) fn for_offer_using_keys(
                invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
-               created_at: Duration, payment_hash: PaymentHash, keys: KeyPair
+               created_at: Duration, payment_hash: PaymentHash, keys: Keypair
        ) -> Result<Self, Bolt12SemanticError> {
                let amount_msats = Self::amount_msats(invoice_request)?;
                let signing_pubkey = keys.public_key();
@@ -285,7 +284,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
        #[cfg_attr(c_bindings, allow(dead_code))]
        pub(super) fn for_refund_using_keys(
                refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration,
-               payment_hash: PaymentHash, keys: KeyPair,
+               payment_hash: PaymentHash, keys: Keypair,
        ) -> Result<Self, Bolt12SemanticError> {
                let amount_msats = refund.amount_msats();
                let signing_pubkey = keys.public_key();
@@ -1094,8 +1093,8 @@ impl InvoiceContents {
                                Err(_) => return None,
                        };
 
-                       let program = &address.program;
-                       let witness_program = match WitnessProgram::new(version, program.clone()) {
+                       let program = address.program.clone();
+                       let witness_program = match WitnessProgram::new(version, program) {
                                Ok(witness_program) => witness_program,
                                Err(_) => return None,
                        };
@@ -1474,12 +1473,13 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
 mod tests {
        use super::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, FallbackAddress, FullInvoiceTlvStreamRef, InvoiceTlvStreamRef, SIGNATURE_TAG, UnsignedBolt12Invoice};
 
+       use bitcoin::{WitnessProgram, WitnessVersion};
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::ScriptBuf;
        use bitcoin::hashes::Hash;
-       use bitcoin::network::constants::Network;
-       use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey, XOnlyPublicKey, self};
-       use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion};
+       use bitcoin::network::Network;
+       use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey, self};
+       use bitcoin::address::{Address, Payload};
        use bitcoin::key::TweakedPublicKey;
 
        use core::time::Duration;
@@ -1567,7 +1567,7 @@ mod tests {
                assert!(!unsigned_invoice.is_expired());
                assert_eq!(unsigned_invoice.payment_hash(), payment_hash);
                assert_eq!(unsigned_invoice.amount_msats(), 1000);
-               assert_eq!(unsigned_invoice.fallbacks(), vec![]);
+               assert!(unsigned_invoice.fallbacks().is_empty());
                assert_eq!(unsigned_invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
                assert_eq!(unsigned_invoice.signing_pubkey(), recipient_pubkey());
 
@@ -1611,14 +1611,14 @@ mod tests {
                assert!(!invoice.is_expired());
                assert_eq!(invoice.payment_hash(), payment_hash);
                assert_eq!(invoice.amount_msats(), 1000);
-               assert_eq!(invoice.fallbacks(), vec![]);
+               assert!(invoice.fallbacks().is_empty());
                assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
                assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
 
                let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
                assert!(merkle::verify_signature(&invoice.signature, &message, recipient_pubkey()).is_ok());
 
-               let digest = Message::from_slice(&invoice.signable_hash()).unwrap();
+               let digest = Message::from_digest(invoice.signable_hash());
                let pubkey = recipient_pubkey().into();
                let secp_ctx = Secp256k1::verification_only();
                assert!(secp_ctx.verify_schnorr(&invoice.signature, &digest, &pubkey).is_ok());
@@ -1709,7 +1709,7 @@ mod tests {
                assert!(!invoice.is_expired());
                assert_eq!(invoice.payment_hash(), payment_hash);
                assert_eq!(invoice.amount_msats(), 1000);
-               assert_eq!(invoice.fallbacks(), vec![]);
+               assert!(invoice.fallbacks().is_empty());
                assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
                assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
 
@@ -2402,7 +2402,7 @@ mod tests {
 
                let blinded_node_id_sign = |message: &UnsignedBolt12Invoice| {
                        let secp_ctx = Secp256k1::new();
-                       let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap());
+                       let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap());
                        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
                };
 
index f243ea693f2f019be1e0dddf214a599751213e1a..cdf94a2e80d5bee168deea35fdb03c817718cdc7 100644 (file)
@@ -23,8 +23,8 @@
 //! extern crate bitcoin;
 //! extern crate lightning;
 //!
-//! use bitcoin::network::constants::Network;
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::network::Network;
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use lightning::ln::features::OfferFeatures;
 //! use lightning::offers::invoice_request::UnsignedInvoiceRequest;
 //! use lightning::offers::offer::Offer;
@@ -32,7 +32,7 @@
 //!
 //! # fn parse() -> Result<(), lightning::offers::parse::Bolt12ParseError> {
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
 //! let pubkey = PublicKey::from(keys);
 //! let mut buffer = Vec::new();
 //!
@@ -58,8 +58,8 @@
 //! ```
 
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
+use bitcoin::network::Network;
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self};
 use bitcoin::secp256k1::schnorr::Signature;
 use core::ops::Deref;
 use crate::sign::EntropySource;
@@ -303,7 +303,7 @@ macro_rules! invoice_request_builder_methods { (
        }
 
        fn build_with_checks($($self_mut)* $self: $self_type) -> Result<
-               (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>),
+               (UnsignedInvoiceRequest, Option<Keypair>, Option<&'b Secp256k1<$secp_context>>),
                Bolt12SemanticError
        > {
                #[cfg(feature = "std")] {
@@ -334,7 +334,7 @@ macro_rules! invoice_request_builder_methods { (
        }
 
        fn build_without_checks($($self_mut)* $self: $self_type) ->
-               (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>)
+               (UnsignedInvoiceRequest, Option<Keypair>, Option<&'b Secp256k1<$secp_context>>)
        {
                // Create the metadata for stateless verification of a Bolt12Invoice.
                let mut keys = None;
@@ -622,7 +622,7 @@ pub struct VerifiedInvoiceRequest {
        /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
        /// [`respond_using_derived_keys`]: Self::respond_using_derived_keys
        /// [`respond_with`]: Self::respond_with
-       pub keys: Option<KeyPair>,
+       pub keys: Option<Keypair>,
 }
 
 /// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
@@ -1204,8 +1204,8 @@ mod tests {
        use super::{InvoiceRequest, InvoiceRequestFields, InvoiceRequestTlvStreamRef, PAYER_NOTE_LIMIT, SIGNATURE_TAG, UnsignedInvoiceRequest};
 
        use bitcoin::blockdata::constants::ChainHash;
-       use bitcoin::network::constants::Network;
-       use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey, self};
+       use bitcoin::network::Network;
+       use bitcoin::secp256k1::{Keypair, Secp256k1, SecretKey, self};
        use core::num::NonZeroU64;
        #[cfg(feature = "std")]
        use core::time::Duration;
@@ -2245,7 +2245,7 @@ mod tests {
        #[test]
        fn fails_parsing_invoice_request_with_extra_tlv_records() {
                let secp_ctx = Secp256k1::new();
-               let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let invoice_request = OfferBuilder::new(keys.public_key())
                        .amount_msats(1000)
                        .build().unwrap()
index d8d1a90e3fdd4ef5157f37e49811b2e08efbd70a..11f1d971330c7f1c3f7447aa2f2b7ee5a5f5ddd7 100644 (file)
@@ -54,7 +54,7 @@ impl TaggedHash {
        ) -> Self {
                let tag_hash = sha256::Hash::hash(tag.as_bytes());
                let merkle_root = root_hash(tlv_stream);
-               let digest = Message::from_slice(tagged_hash(tag_hash, merkle_root).as_byte_array()).unwrap();
+               let digest = Message::from_digest(tagged_hash(tag_hash, merkle_root).to_byte_array());
                Self {
                        tag,
                        merkle_root,
@@ -305,7 +305,7 @@ mod tests {
 
        use bitcoin::hashes::{Hash, sha256};
        use bitcoin::hashes::hex::FromHex;
-       use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey};
+       use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey};
        use bitcoin::secp256k1::schnorr::Signature;
        use crate::offers::offer::{Amount, OfferBuilder};
        use crate::offers::invoice_request::{InvoiceRequest, UnsignedInvoiceRequest};
@@ -338,11 +338,11 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let recipient_pubkey = {
                        let secret_key = SecretKey::from_slice(&<Vec<u8>>::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap()).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key()
+                       Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
                };
                let payer_keys = {
                        let secret_key = SecretKey::from_slice(&<Vec<u8>>::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key)
+                       Keypair::from_secret_key(&secp_ctx, &secret_key)
                };
 
                // BOLT 12 test vectors
@@ -384,8 +384,7 @@ mod tests {
                 let tagged_hash = unsigned_invoice_request.as_ref();
                 let expected_digest = unsigned_invoice_request.as_ref().as_digest();
                 let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes());
-                let actual_digest = Message::from_slice(super::tagged_hash(tag, tagged_hash.merkle_root()).as_byte_array())
-                        .unwrap();
+                let actual_digest = Message::from_digest(super::tagged_hash(tag, tagged_hash.merkle_root()).to_byte_array());
                 assert_eq!(*expected_digest, actual_digest);
         }
 
@@ -394,11 +393,11 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let recipient_pubkey = {
                        let secret_key = SecretKey::from_slice(&[41; 32]).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key()
+                       Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
                };
                let payer_keys = {
                        let secret_key = SecretKey::from_slice(&[42; 32]).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key)
+                       Keypair::from_secret_key(&secp_ctx, &secret_key)
                };
 
                let invoice_request = OfferBuilder::new(recipient_pubkey)
@@ -426,11 +425,11 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let recipient_pubkey = {
                        let secret_key = SecretKey::from_slice(&[41; 32]).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key()
+                       Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
                };
                let payer_keys = {
                        let secret_key = SecretKey::from_slice(&[42; 32]).unwrap();
-                       KeyPair::from_secret_key(&secp_ctx, &secret_key)
+                       Keypair::from_secret_key(&secp_ctx, &secret_key)
                };
 
                let invoice_request = OfferBuilder::new(recipient_pubkey)
index 439fcddb1814e65d1e632229fd4cce3552ef6c4d..db910b5e1bba361d977448bd6bd53a706cd92cab 100644 (file)
@@ -24,7 +24,7 @@
 //! use core::num::NonZeroU64;
 //! use core::time::Duration;
 //!
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use lightning::offers::offer::{Offer, OfferBuilder, Quantity};
 //! use lightning::offers::parse::Bolt12ParseError;
 //! use lightning::util::ser::{Readable, Writeable};
@@ -39,7 +39,7 @@
 //! # #[cfg(feature = "std")]
 //! # fn build() -> Result<(), Bolt12ParseError> {
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
 //! let pubkey = PublicKey::from(keys);
 //!
 //! let expiration = SystemTime::now() + Duration::from_secs(24 * 60 * 60);
@@ -78,8 +78,8 @@
 //! [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder
 
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
+use bitcoin::network::Network;
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self};
 use core::hash::{Hash, Hasher};
 use core::num::NonZeroU64;
 use core::ops::Deref;
@@ -909,7 +909,7 @@ impl OfferContents {
        /// Verifies that the offer metadata was produced from the offer in the TLV stream.
        pub(super) fn verify<T: secp256k1::Signing>(
                &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1<T>
-       ) -> Result<(OfferId, Option<KeyPair>), ()> {
+       ) -> Result<(OfferId, Option<Keypair>), ()> {
                match self.metadata() {
                        Some(metadata) => {
                                let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
@@ -966,6 +966,13 @@ impl OfferContents {
        }
 }
 
+impl Readable for Offer {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let bytes: WithoutLength<Vec<u8>> = Readable::read(reader)?;
+               Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
+       }
+}
+
 impl Writeable for Offer {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                WithoutLength(&self.bytes).write(writer)
@@ -1140,7 +1147,7 @@ mod tests {
        };
 
        use bitcoin::blockdata::constants::ChainHash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::Secp256k1;
        use core::num::NonZeroU64;
        use core::time::Duration;
index 3b9b04a5c06f8f00d898cec70aec46f6be600e3e..472e44f6220f1aed6b2c77c71252a49a1b7aff3b 100644 (file)
@@ -9,7 +9,6 @@
 
 //! Parsing and formatting for bech32 message encoding.
 
-use bitcoin::bech32;
 use bitcoin::secp256k1;
 use crate::io;
 use crate::ln::msgs::DecodeError;
@@ -25,8 +24,7 @@ pub(super) use sealed::Bech32Encode;
 pub use sealed::Bech32Encode;
 
 mod sealed {
-       use bitcoin::bech32;
-       use bitcoin::bech32::{FromBase32, ToBase32};
+       use bech32::{FromBase32, ToBase32};
        use core::fmt;
        use super::Bolt12ParseError;
 
@@ -277,7 +275,6 @@ mod bolt12_tests {
 #[cfg(test)]
 mod tests {
        use super::Bolt12ParseError;
-       use bitcoin::bech32;
        use crate::ln::msgs::DecodeError;
        use crate::offers::offer::Offer;
 
index 1988a92aaa7450262f0a04d1c2ba00d8545beec3..624036d195742879930cd25041d416561d3eee34 100644 (file)
@@ -28,8 +28,8 @@
 //! use core::convert::TryFrom;
 //! use core::time::Duration;
 //!
-//! use bitcoin::network::constants::Network;
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::network::Network;
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use lightning::offers::parse::Bolt12ParseError;
 //! use lightning::offers::refund::{Refund, RefundBuilder};
 //! use lightning::util::ser::{Readable, Writeable};
@@ -44,7 +44,7 @@
 //! # #[cfg(feature = "std")]
 //! # fn build() -> Result<(), Bolt12ParseError> {
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
 //! let pubkey = PublicKey::from(keys);
 //!
 //! let expiration = SystemTime::now() + Duration::from_secs(24 * 60 * 60);
@@ -83,7 +83,7 @@
 //! [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder
 
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::{PublicKey, Secp256k1, self};
 use core::hash::{Hash, Hasher};
 use core::ops::Deref;
@@ -103,7 +103,7 @@ use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef};
 use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
 use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef};
 use crate::offers::signer::{Metadata, MetadataMaterial, self};
-use crate::util::ser::{SeekReadable, WithoutLength, Writeable, Writer};
+use crate::util::ser::{SeekReadable, Readable, WithoutLength, Writeable, Writer};
 use crate::util::string::PrintableString;
 
 #[cfg(not(c_bindings))]
@@ -769,6 +769,13 @@ impl RefundContents {
        }
 }
 
+impl Readable for Refund {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let bytes: WithoutLength<Vec<u8>> = Readable::read(reader)?;
+               Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
+       }
+}
+
 impl Writeable for Refund {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                WithoutLength(&self.bytes).write(writer)
@@ -920,8 +927,8 @@ mod tests {
        };
 
        use bitcoin::blockdata::constants::ChainHash;
-       use bitcoin::network::constants::Network;
-       use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey};
+       use bitcoin::network::Network;
+       use bitcoin::secp256k1::{Keypair, Secp256k1, SecretKey};
 
        use core::time::Duration;
 
@@ -1506,7 +1513,7 @@ mod tests {
        #[test]
        fn fails_parsing_refund_with_extra_tlv_records() {
                let secp_ctx = Secp256k1::new();
-               let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let refund = RefundBuilder::new(vec![1; 32], keys.public_key(), 1000).unwrap()
                        .build().unwrap();
 
index c5a96cbf18491e3f22eb830c879eb4d274e9abc3..fff0514564ca34253d8a2b958e95ba1a9e8f4549 100644 (file)
@@ -13,7 +13,7 @@ use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::cmp::fixed_time_eq;
 use bitcoin::hashes::hmac::{Hmac, HmacEngine};
 use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey, self};
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self};
 use core::fmt;
 use crate::ln::channelmanager::PaymentId;
 use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
@@ -102,7 +102,7 @@ impl Metadata {
 
        pub fn derive_from<W: Writeable, T: secp256k1::Signing>(
                self, tlv_stream: W, secp_ctx: Option<&Secp256k1<T>>
-       ) -> (Self, Option<KeyPair>) {
+       ) -> (Self, Option<Keypair>) {
                match self {
                        Metadata::Bytes(_) => (self, None),
                        Metadata::Derived(mut metadata_material) => {
@@ -188,7 +188,7 @@ impl MetadataMaterial {
 
        fn derive_metadata_and_keys<T: secp256k1::Signing>(
                mut self, secp_ctx: &Secp256k1<T>
-       ) -> (Vec<u8>, KeyPair) {
+       ) -> (Vec<u8>, Keypair) {
                self.hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT);
                self.maybe_include_encrypted_payment_id();
 
@@ -197,7 +197,7 @@ impl MetadataMaterial {
 
                let hmac = Hmac::from_engine(self.hmac);
                let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();
-               let keys = KeyPair::from_secret_key(secp_ctx, &privkey);
+               let keys = Keypair::from_secret_key(secp_ctx, &privkey);
 
                (bytes, keys)
        }
@@ -213,12 +213,12 @@ impl MetadataMaterial {
        }
 }
 
-pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> KeyPair {
+pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> Keypair {
        const IV_BYTES: &[u8; IV_LEN] = b"LDK Invoice ~~~~";
        let secp_ctx = Secp256k1::new();
        let hmac = Hmac::from_engine(expanded_key.hmac_for_offer(nonce, IV_BYTES));
        let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();
-       KeyPair::from_secret_key(&secp_ctx, &privkey)
+       Keypair::from_secret_key(&secp_ctx, &privkey)
 }
 
 /// Verifies data given in a TLV stream was used to produce the given metadata, consisting of:
@@ -265,12 +265,12 @@ pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>(
 /// If the latter is not included in the metadata, the TLV stream is used to check if the given
 /// `signing_pubkey` can be derived from it.
 ///
-/// Returns the [`KeyPair`] for signing the invoice, if it can be derived from the metadata.
+/// Returns the [`Keypair`] for signing the invoice, if it can be derived from the metadata.
 pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>(
        metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
        signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator<Item = TlvRecord<'a>>,
        secp_ctx: &Secp256k1<T>
-) -> Result<Option<KeyPair>, ()> {
+) -> Result<Option<Keypair>, ()> {
        let mut hmac = hmac_for_message(metadata, expanded_key, iv_bytes, tlv_stream)?;
        hmac.input(WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT);
 
@@ -279,9 +279,9 @@ pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>(
 
 fn verify_metadata<T: secp256k1::Signing>(
        metadata: &[u8], hmac: Hmac<Sha256>, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>
-) -> Result<Option<KeyPair>, ()> {
+) -> Result<Option<Keypair>, ()> {
        if metadata.len() == Nonce::LENGTH {
-               let derived_keys = KeyPair::from_secret_key(
+               let derived_keys = Keypair::from_secret_key(
                        secp_ctx, &SecretKey::from_slice(hmac.as_byte_array()).unwrap()
                );
                if fixed_time_eq(&signing_pubkey.serialize(), &derived_keys.public_key().serialize()) {
index ee8cf3a7c1764e018bfd7d096218c8e67aff09c4..0c35ee2859878a7bb98171481b5c1fc4132fed2b 100644 (file)
@@ -9,7 +9,7 @@
 
 //! Utilities for testing BOLT 12 Offers interfaces
 
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 use bitcoin::secp256k1::schnorr::Signature;
 
 use core::time::Duration;
@@ -27,14 +27,14 @@ pub(crate) fn fail_sign<T: AsRef<TaggedHash>>(_message: &T) -> Result<Signature,
        Err(())
 }
 
-pub(crate) fn payer_keys() -> KeyPair {
+pub(crate) fn payer_keys() -> Keypair {
        let secp_ctx = Secp256k1::new();
-       KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
+       Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
 }
 
 pub(crate) fn payer_sign<T: AsRef<TaggedHash>>(message: &T) -> Result<Signature, ()> {
        let secp_ctx = Secp256k1::new();
-       let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+       let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
 }
 
@@ -42,14 +42,14 @@ pub(crate) fn payer_pubkey() -> PublicKey {
        payer_keys().public_key()
 }
 
-pub(crate) fn recipient_keys() -> KeyPair {
+pub(crate) fn recipient_keys() -> Keypair {
        let secp_ctx = Secp256k1::new();
-       KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap())
+       Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap())
 }
 
 pub(crate) fn recipient_sign<T: AsRef<TaggedHash>>(message: &T) -> Result<Signature, ()> {
        let secp_ctx = Secp256k1::new();
-       let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap());
+       let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap());
        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
 }
 
index 029038a9fe769cc258088cbac6e9230c6477e827..08be1b2c5027d64bdf599faca92f0b2ed510ef5c 100644 (file)
@@ -19,11 +19,11 @@ use crate::routing::test_utils::{add_channel, add_or_update_node};
 use crate::sign::{NodeSigner, Recipient};
 use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
 use crate::util::test_utils;
-use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError};
+use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
 use super::offers::{OffersMessage, OffersMessageHandler};
 use super::packet::{OnionMessageContents, Packet};
 
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::secp256k1::{All, PublicKey, Secp256k1, SecretKey};
 
@@ -81,20 +81,20 @@ impl OffersMessageHandler for TestOffersMessageHandler {
 
 #[derive(Clone, Debug, PartialEq)]
 enum TestCustomMessage {
-       Request,
-       Response,
+       Ping,
+       Pong,
 }
 
-const CUSTOM_REQUEST_MESSAGE_TYPE: u64 = 4242;
-const CUSTOM_RESPONSE_MESSAGE_TYPE: u64 = 4343;
-const CUSTOM_REQUEST_MESSAGE_CONTENTS: [u8; 32] = [42; 32];
-const CUSTOM_RESPONSE_MESSAGE_CONTENTS: [u8; 32] = [43; 32];
+const CUSTOM_PING_MESSAGE_TYPE: u64 = 4242;
+const CUSTOM_PONG_MESSAGE_TYPE: u64 = 4343;
+const CUSTOM_PING_MESSAGE_CONTENTS: [u8; 32] = [42; 32];
+const CUSTOM_PONG_MESSAGE_CONTENTS: [u8; 32] = [43; 32];
 
 impl OnionMessageContents for TestCustomMessage {
        fn tlv_type(&self) -> u64 {
                match self {
-                       TestCustomMessage::Request => CUSTOM_REQUEST_MESSAGE_TYPE,
-                       TestCustomMessage::Response => CUSTOM_RESPONSE_MESSAGE_TYPE,
+                       TestCustomMessage::Ping => CUSTOM_PING_MESSAGE_TYPE,
+                       TestCustomMessage::Pong => CUSTOM_PONG_MESSAGE_TYPE,
                }
        }
        fn msg_type(&self) -> &'static str {
@@ -105,23 +105,46 @@ impl OnionMessageContents for TestCustomMessage {
 impl Writeable for TestCustomMessage {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                match self {
-                       TestCustomMessage::Request => Ok(CUSTOM_REQUEST_MESSAGE_CONTENTS.write(w)?),
-                       TestCustomMessage::Response => Ok(CUSTOM_RESPONSE_MESSAGE_CONTENTS.write(w)?),
+                       TestCustomMessage::Ping => Ok(CUSTOM_PING_MESSAGE_CONTENTS.write(w)?),
+                       TestCustomMessage::Pong => Ok(CUSTOM_PONG_MESSAGE_CONTENTS.write(w)?),
                }
        }
 }
 
 struct TestCustomMessageHandler {
-       expected_messages: Mutex<VecDeque<TestCustomMessage>>,
+       expectations: Mutex<VecDeque<OnHandleCustomMessage>>,
+}
+
+struct OnHandleCustomMessage {
+       expect: TestCustomMessage,
+       include_reply_path: bool,
 }
 
 impl TestCustomMessageHandler {
        fn new() -> Self {
-               Self { expected_messages: Mutex::new(VecDeque::new()) }
+               Self { expectations: Mutex::new(VecDeque::new()) }
        }
 
        fn expect_message(&self, message: TestCustomMessage) {
-               self.expected_messages.lock().unwrap().push_back(message);
+               self.expectations.lock().unwrap().push_back(
+                       OnHandleCustomMessage {
+                               expect: message,
+                               include_reply_path: false,
+                       }
+               );
+       }
+
+       fn expect_message_and_response(&self, message: TestCustomMessage) {
+               self.expectations.lock().unwrap().push_back(
+                       OnHandleCustomMessage {
+                               expect: message,
+                               include_reply_path: true,
+                       }
+               );
+       }
+
+       fn get_next_expectation(&self) -> OnHandleCustomMessage {
+               self.expectations.lock().unwrap().pop_front().expect("No expectations remaining")
        }
 }
 
@@ -132,38 +155,45 @@ impl Drop for TestCustomMessageHandler {
                                return;
                        }
                }
-               assert!(self.expected_messages.lock().unwrap().is_empty());
+               assert!(self.expectations.lock().unwrap().is_empty());
        }
 }
 
 impl CustomOnionMessageHandler for TestCustomMessageHandler {
        type CustomMessage = TestCustomMessage;
        fn handle_custom_message(&self, msg: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
-               match self.expected_messages.lock().unwrap().pop_front() {
-                       Some(expected_msg) => assert_eq!(expected_msg, msg),
-                       None => panic!("Unexpected message: {:?}", msg),
-               }
-               let response_option = match msg {
-                       TestCustomMessage::Request => Some(TestCustomMessage::Response),
-                       TestCustomMessage::Response => None,
+               let expectation = self.get_next_expectation();
+               assert_eq!(msg, expectation.expect);
+
+               let response = match msg {
+                       TestCustomMessage::Ping => TestCustomMessage::Pong,
+                       TestCustomMessage::Pong => TestCustomMessage::Ping,
                };
-               if let (Some(response), Some(responder)) = (response_option, responder) {
-                       responder.respond(response)
-               } else {
-                       ResponseInstruction::NoResponse
+
+               // Sanity check: expecting to include reply path when responder is absent should panic.
+               if expectation.include_reply_path && responder.is_none() {
+                       panic!("Expected to include a reply_path, but the responder was absent.")
+               }
+
+               match responder {
+                       Some(responder) if expectation.include_reply_path => {
+                               responder.respond_with_reply_path(response)
+                       },
+                       Some(responder) => responder.respond(response),
+                       None => ResponseInstruction::NoResponse,
                }
        }
        fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, DecodeError> where Self: Sized {
                match message_type {
-                       CUSTOM_REQUEST_MESSAGE_TYPE => {
+                       CUSTOM_PING_MESSAGE_TYPE => {
                                let buf = read_to_end(buffer)?;
-                               assert_eq!(buf, CUSTOM_REQUEST_MESSAGE_CONTENTS);
-                               Ok(Some(TestCustomMessage::Request))
+                               assert_eq!(buf, CUSTOM_PING_MESSAGE_CONTENTS);
+                               Ok(Some(TestCustomMessage::Ping))
                        },
-                       CUSTOM_RESPONSE_MESSAGE_TYPE => {
+                       CUSTOM_PONG_MESSAGE_TYPE => {
                                let buf = read_to_end(buffer)?;
-                               assert_eq!(buf, CUSTOM_RESPONSE_MESSAGE_CONTENTS);
-                               Ok(Some(TestCustomMessage::Response))
+                               assert_eq!(buf, CUSTOM_PONG_MESSAGE_CONTENTS);
+                               Ok(Some(TestCustomMessage::Pong))
                        },
                        _ => Ok(None),
                }
@@ -298,18 +328,18 @@ fn pass_along_path(path: &Vec<MessengerNode>) {
 #[test]
 fn one_unblinded_hop() {
        let nodes = create_nodes(2);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let destination = Destination::Node(nodes[1].node_id);
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
-       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 }
 
 #[test]
 fn two_unblinded_hops() {
        let nodes = create_nodes(3);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let path = OnionMessagePath {
                intermediate_nodes: vec![nodes[1].node_id],
@@ -318,27 +348,27 @@ fn two_unblinded_hops() {
        };
 
        nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap();
-       nodes[2].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[2].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 }
 
 #[test]
 fn one_blinded_hop() {
        let nodes = create_nodes(2);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
        let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
-       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 }
 
 #[test]
 fn two_unblinded_two_blinded() {
        let nodes = create_nodes(5);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[3].node_id, short_channel_id: None }];
@@ -350,14 +380,14 @@ fn two_unblinded_two_blinded() {
        };
 
        nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap();
-       nodes[4].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[4].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 }
 
 #[test]
 fn three_blinded_hops() {
        let nodes = create_nodes(4);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [
@@ -368,15 +398,117 @@ fn three_blinded_hops() {
        let destination = Destination::BlindedPath(blinded_path);
 
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
-       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Pong);
+       pass_along_path(&nodes);
+}
+
+#[test]
+fn async_response_over_one_blinded_hop() {
+       // Simulate an asynchronous interaction between two nodes, Alice and Bob.
+
+       // 1. Set up the network with two nodes: Alice and Bob.
+       let nodes = create_nodes(2);
+       let alice = &nodes[0];
+       let bob = &nodes[1];
+
+       // 2. Define the message sent from Bob to Alice.
+       let message = TestCustomMessage::Ping;
+       let path_id = Some([2; 32]);
+
+       // 3. Simulate the creation of a Blinded Reply path provided by Bob.
+       let secp_ctx = Secp256k1::new();
+       let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+
+       // 4. Create a responder using the reply path for Alice.
+       let responder = Some(Responder::new(reply_path, path_id));
+
+       // 5. Expect Alice to receive the message and create a response instruction for it.
+       alice.custom_message_handler.expect_message(message.clone());
+       let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder);
+
+       // 6. Simulate Alice asynchronously responding back to Bob with a response.
+       assert_eq!(
+               nodes[0].messenger.handle_onion_message_response(response_instruction),
+               Ok(Some(SendSuccess::Buffered)),
+       );
+
+       bob.custom_message_handler.expect_message(TestCustomMessage::Pong);
+
+       pass_along_path(&nodes);
+}
+
+#[test]
+fn async_response_with_reply_path_succeeds() {
+       // Simulate an asynchronous interaction between two nodes, Alice and Bob.
+       // Create a channel between the two nodes to establish them as announced nodes,
+       // which allows the creation of the reply_path for successful communication.
+
+       let mut nodes = create_nodes(2);
+       let alice = &nodes[0];
+       let bob = &nodes[1];
+       let secp_ctx = Secp256k1::new();
+
+       add_channel_to_graph(alice, bob, &secp_ctx, 24);
+
+       // Alice receives a message from Bob with an added reply_path for responding back.
+       let message = TestCustomMessage::Ping;
+       let path_id = Some([2; 32]);
+       let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+
+       // Alice asynchronously responds to Bob, expecting a response back from him.
+       let responder = Responder::new(reply_path, path_id);
+       alice.custom_message_handler.expect_message_and_response(message.clone());
+       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
+
+       assert_eq!(
+               alice.messenger.handle_onion_message_response(response_instruction),
+               Ok(Some(SendSuccess::Buffered)),
+       );
+
+       // Set Bob's expectation and pass the Onion Message along the path.
+       bob.custom_message_handler.expect_message(TestCustomMessage::Pong);
+       pass_along_path(&nodes);
+
+       // Bob responds back to Alice using the reply_path she included with the OnionMessage.
+       // Set Alice's expectation and reverse the path for the response.
+       alice.custom_message_handler.expect_message(TestCustomMessage::Ping);
+       nodes.reverse();
        pass_along_path(&nodes);
 }
 
+#[test]
+fn async_response_with_reply_path_fails() {
+       // Simulate an asynchronous interaction between two unannounced nodes, Alice and Bob.
+       // Since the nodes are unannounced, attempting to respond using a reply_path
+       // will fail, leading to an expected failure in communication.
+
+       let nodes = create_nodes(2);
+       let alice = &nodes[0];
+       let bob = &nodes[1];
+       let secp_ctx = Secp256k1::new();
+
+       // Alice receives a message from Bob with an added reply_path for responding back.
+       let message = TestCustomMessage::Ping;
+       let path_id = Some([2; 32]);
+       let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+
+       // Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced.
+       // Therefore, the reply_path cannot be used for the response.
+       let responder = Responder::new(reply_path, path_id);
+       alice.custom_message_handler.expect_message_and_response(message.clone());
+       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
+
+       assert_eq!(
+               alice.messenger.handle_onion_message_response(response_instruction),
+               Err(SendError::PathNotFound),
+       );
+}
+
 #[test]
 fn too_big_packet_error() {
        // Make sure we error as expected if a packet is too big to send.
        let nodes = create_nodes(2);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let hop_node_id = nodes[1].node_id;
        let hops = vec![hop_node_id; 400];
@@ -394,7 +526,7 @@ fn we_are_intro_node() {
        // If we are sending straight to a blinded path and we are the introduction node, we need to
        // advance the blinded path by 1 hop so the second hop is the new introduction node.
        let mut nodes = create_nodes(3);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [
@@ -405,7 +537,7 @@ fn we_are_intro_node() {
        let destination = Destination::BlindedPath(blinded_path);
 
        nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
-       nodes[2].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[2].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 
        // Try with a two-hop blinded path where we are the introduction node.
@@ -413,7 +545,7 @@ fn we_are_intro_node() {
        let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
-       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
        nodes.remove(2);
        pass_along_path(&nodes);
 }
@@ -422,7 +554,7 @@ fn we_are_intro_node() {
 fn invalid_blinded_path_error() {
        // Make sure we error as expected if a provided blinded path has 0 hops.
        let nodes = create_nodes(3);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
@@ -436,7 +568,7 @@ fn invalid_blinded_path_error() {
 #[test]
 fn reply_path() {
        let mut nodes = create_nodes(4);
-       let test_msg = TestCustomMessage::Request;
+       let test_msg = TestCustomMessage::Ping;
        let secp_ctx = Secp256k1::new();
 
        // Destination::Node
@@ -451,10 +583,10 @@ fn reply_path() {
        ];
        let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
        nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap();
-       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request);
+       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
        pass_along_path(&nodes);
        // Make sure the last node successfully decoded the reply path.
-       nodes[0].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[0].custom_message_handler.expect_message(TestCustomMessage::Pong);
        nodes.reverse();
        pass_along_path(&nodes);
 
@@ -472,11 +604,11 @@ fn reply_path() {
        let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
 
        nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
-       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request);
+       nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
        pass_along_path(&nodes);
 
        // Make sure the last node successfully decoded the reply path.
-       nodes[0].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[0].custom_message_handler.expect_message(TestCustomMessage::Pong);
        nodes.reverse();
        pass_along_path(&nodes);
 }
@@ -510,7 +642,7 @@ fn invalid_custom_message_type() {
 #[test]
 fn peer_buffer_full() {
        let nodes = create_nodes(2);
-       let test_msg = TestCustomMessage::Request;
+       let test_msg = TestCustomMessage::Ping;
        let destination = Destination::Node(nodes[1].node_id);
        for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
                nodes[0].messenger.send_onion_message(test_msg.clone(), destination.clone(), None).unwrap();
@@ -525,7 +657,7 @@ fn many_hops() {
        // of size [`crate::onion_message::packet::BIG_PACKET_HOP_DATA_LEN`].
        let num_nodes: usize = 25;
        let nodes = create_nodes(num_nodes as u8);
-       let test_msg = TestCustomMessage::Response;
+       let test_msg = TestCustomMessage::Pong;
 
        let mut intermediate_nodes = vec![];
        for i in 1..(num_nodes-1) {
@@ -538,14 +670,14 @@ fn many_hops() {
                first_node_addresses: None,
        };
        nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap();
-       nodes[num_nodes-1].custom_message_handler.expect_message(TestCustomMessage::Response);
+       nodes[num_nodes-1].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&nodes);
 }
 
 #[test]
 fn requests_peer_connection_for_buffered_messages() {
        let nodes = create_nodes(3);
-       let message = TestCustomMessage::Request;
+       let message = TestCustomMessage::Ping;
        let secp_ctx = Secp256k1::new();
        add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
 
@@ -583,7 +715,7 @@ fn requests_peer_connection_for_buffered_messages() {
 #[test]
 fn drops_buffered_messages_waiting_for_peer_connection() {
        let nodes = create_nodes(3);
-       let message = TestCustomMessage::Request;
+       let message = TestCustomMessage::Ping;
        let secp_ctx = Secp256k1::new();
        add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
 
@@ -635,7 +767,7 @@ fn intercept_offline_peer_oms() {
                }
        }
 
-       let message = TestCustomMessage::Response;
+       let message = TestCustomMessage::Pong;
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
        let blinded_path = BlindedPath::new_for_message(
@@ -675,7 +807,7 @@ fn intercept_offline_peer_oms() {
        }
 
        nodes[1].messenger.forward_onion_message(onion_message, &final_node_vec[0].node_id).unwrap();
-       final_node_vec[0].custom_message_handler.expect_message(TestCustomMessage::Response);
+       final_node_vec[0].custom_message_handler.expect_message(TestCustomMessage::Pong);
        pass_along_path(&vec![nodes.remove(1), final_node_vec.remove(0)]);
 }
 
index fc3eead1e4fac6a53e16f165ea39e7ff2f129710..ee49d00e99dea2de48c8a9c2fa76e92c2c2b9b27 100644 (file)
@@ -47,6 +47,70 @@ use {
 
 pub(super) const MAX_TIMER_TICKS: usize = 2;
 
+/// A trivial trait which describes any [`OnionMessenger`].
+///
+/// This is not exported to bindings users as general cover traits aren't useful in other
+/// languages.
+pub trait AOnionMessenger {
+       /// A type implementing [`EntropySource`]
+       type EntropySource: EntropySource + ?Sized;
+       /// A type that may be dereferenced to [`Self::EntropySource`]
+       type ES: Deref<Target = Self::EntropySource>;
+       /// A type implementing [`NodeSigner`]
+       type NodeSigner: NodeSigner + ?Sized;
+       /// A type that may be dereferenced to [`Self::NodeSigner`]
+       type NS: Deref<Target = Self::NodeSigner>;
+       /// A type implementing [`Logger`]
+       type Logger: Logger + ?Sized;
+       /// A type that may be dereferenced to [`Self::Logger`]
+       type L: Deref<Target = Self::Logger>;
+       /// A type implementing [`NodeIdLookUp`]
+       type NodeIdLookUp: NodeIdLookUp + ?Sized;
+       /// A type that may be dereferenced to [`Self::NodeIdLookUp`]
+       type NL: Deref<Target = Self::NodeIdLookUp>;
+       /// A type implementing [`MessageRouter`]
+       type MessageRouter: MessageRouter + ?Sized;
+       /// A type that may be dereferenced to [`Self::MessageRouter`]
+       type MR: Deref<Target = Self::MessageRouter>;
+       /// A type implementing [`OffersMessageHandler`]
+       type OffersMessageHandler: OffersMessageHandler + ?Sized;
+       /// A type that may be dereferenced to [`Self::OffersMessageHandler`]
+       type OMH: Deref<Target = Self::OffersMessageHandler>;
+       /// A type implementing [`CustomOnionMessageHandler`]
+       type CustomOnionMessageHandler: CustomOnionMessageHandler + ?Sized;
+       /// A type that may be dereferenced to [`Self::CustomOnionMessageHandler`]
+       type CMH: Deref<Target = Self::CustomOnionMessageHandler>;
+       /// Returns a reference to the actual [`OnionMessenger`] object.
+       fn get_om(&self) -> &OnionMessenger<Self::ES, Self::NS, Self::L, Self::NL, Self::MR, Self::OMH, Self::CMH>;
+}
+
+impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref> AOnionMessenger
+for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
+       ES::Target: EntropySource,
+       NS::Target: NodeSigner,
+       L::Target: Logger,
+       NL::Target: NodeIdLookUp,
+       MR::Target: MessageRouter,
+       OMH::Target: OffersMessageHandler,
+       CMH::Target: CustomOnionMessageHandler,
+{
+       type EntropySource = ES::Target;
+       type ES = ES;
+       type NodeSigner = NS::Target;
+       type NS = NS;
+       type Logger = L::Target;
+       type L = L;
+       type NodeIdLookUp = NL::Target;
+       type NL = NL;
+       type MessageRouter = MR::Target;
+       type MR = MR;
+       type OffersMessageHandler = OMH::Target;
+       type OMH = OMH;
+       type CustomOnionMessageHandler = CMH::Target;
+       type CMH = CMH;
+       fn get_om(&self) -> &OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> { self }
+}
+
 /// A sender, receiver and forwarder of [`OnionMessage`]s.
 ///
 /// # Handling Messages
@@ -98,7 +162,7 @@ pub(super) const MAX_TIMER_TICKS: usize = 2;
 /// #         })
 /// #     }
 /// #     fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-/// #         &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>
+/// #         &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
 /// #     ) -> Result<Vec<BlindedPath>, ()> {
 /// #         unreachable!()
 /// #     }
@@ -181,7 +245,12 @@ where
        offers_handler: OMH,
        custom_handler: CMH,
        intercept_messages_for_offline_peers: bool,
-       pending_events: Mutex<Vec<Event>>,
+       pending_events: Mutex<PendingEvents>,
+}
+
+struct PendingEvents {
+       intercepted_msgs: Vec<Event>,
+       peer_connecteds: Vec<Event>,
 }
 
 /// [`OnionMessage`]s buffered to be sent.
@@ -264,14 +333,16 @@ pub struct Responder {
 
 impl Responder {
        /// Creates a new [`Responder`] instance with the provided reply path.
-       fn new(reply_path: BlindedPath, path_id: Option<[u8; 32]>) -> Self {
+       pub(super) fn new(reply_path: BlindedPath, path_id: Option<[u8; 32]>) -> Self {
                Responder {
                        reply_path,
                        path_id,
                }
        }
 
-       /// Creates the appropriate [`ResponseInstruction`] for a given response.
+       /// Creates a [`ResponseInstruction::WithoutReplyPath`] for a given response.
+       ///
+       /// Use when the recipient doesn't need to send back a reply to us.
        pub fn respond<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
                ResponseInstruction::WithoutReplyPath(OnionMessageResponse {
                        message: response,
@@ -279,6 +350,17 @@ impl Responder {
                        path_id: self.path_id,
                })
        }
+
+       /// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
+       ///
+       /// Use when the recipient needs to send back a reply to us.
+       pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
+               ResponseInstruction::WithReplyPath(OnionMessageResponse {
+                       message: response,
+                       reply_path: self.reply_path,
+                       path_id: self.path_id,
+               })
+       }
 }
 
 /// This struct contains the information needed to reply to a received message.
@@ -290,6 +372,9 @@ pub struct OnionMessageResponse<T: OnionMessageContents> {
 
 /// `ResponseInstruction` represents instructions for responding to received messages.
 pub enum ResponseInstruction<T: OnionMessageContents> {
+       /// Indicates that a response should be sent including a reply path for
+       /// the recipient to respond back.
+       WithReplyPath(OnionMessageResponse<T>),
        /// Indicates that a response should be sent without including a reply path
        /// for the recipient to respond back.
        WithoutReplyPath(OnionMessageResponse<T>),
@@ -341,11 +426,43 @@ pub trait MessageRouter {
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()>;
+
+       /// Creates compact [`BlindedPath`]s to the `recipient` node. The nodes in `peers` are assumed
+       /// to be direct peers with the `recipient`.
+       ///
+       /// Compact blinded paths use short channel ids instead of pubkeys for a smaller serialization,
+       /// which is beneficial when a QR code is used to transport the data. The SCID is passed using a
+       /// [`ForwardNode`] but may be `None` for graceful degradation.
+       ///
+       /// Implementations using additional intermediate nodes are responsible for using a
+       /// [`ForwardNode`] with `Some` short channel id, if possible. Similarly, implementations should
+       /// call [`BlindedPath::use_compact_introduction_node`].
+       ///
+       /// The provided implementation simply delegates to [`MessageRouter::create_blinded_paths`],
+       /// ignoring the short channel ids.
+       fn create_compact_blinded_paths<
+               T: secp256k1::Signing + secp256k1::Verification
+       >(
+               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               let peers = peers
+                       .into_iter()
+                       .map(|ForwardNode { node_id, short_channel_id: _ }| node_id)
+                       .collect();
+               self.create_blinded_paths(recipient, peers, secp_ctx)
+       }
 }
 
 /// A [`MessageRouter`] that can only route to a directly connected [`Destination`].
+///
+/// # Privacy
+///
+/// Creating [`BlindedPath`]s may affect privacy since, if a suitable path cannot be found, it will
+/// create a one-hop path using the recipient as the introduction node if it is a announced node.
+/// Otherwise, there is no way to find a path to the introduction node in order to send a message,
+/// and thus an `Err` is returned.
 pub struct DefaultMessageRouter<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref>
 where
        L::Target: Logger,
@@ -364,51 +481,12 @@ where
        pub fn new(network_graph: G, entropy_source: ES) -> Self {
                Self { network_graph, entropy_source }
        }
-}
-
-impl<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref> MessageRouter for DefaultMessageRouter<G, L, ES>
-where
-       L::Target: Logger,
-       ES::Target: EntropySource,
-{
-       fn find_path(
-               &self, sender: PublicKey, peers: Vec<PublicKey>, mut destination: Destination
-       ) -> Result<OnionMessagePath, ()> {
-               let network_graph = self.network_graph.deref().read_only();
-               destination.resolve(&network_graph);
-
-               let first_node = match destination.first_node() {
-                       Some(first_node) => first_node,
-                       None => return Err(()),
-               };
-
-               if peers.contains(&first_node) || sender == first_node {
-                       Ok(OnionMessagePath {
-                               intermediate_nodes: vec![], destination, first_node_addresses: None
-                       })
-               } else {
-                       let node_announcement = network_graph
-                               .node(&NodeId::from_pubkey(&first_node))
-                               .and_then(|node_info| node_info.announcement_info.as_ref())
-                               .and_then(|announcement_info| announcement_info.announcement_message.as_ref())
-                               .map(|node_announcement| &node_announcement.contents);
-
-                       match node_announcement {
-                               Some(node_announcement) if node_announcement.features.supports_onion_messages() => {
-                                       let first_node_addresses = Some(node_announcement.addresses.clone());
-                                       Ok(OnionMessagePath {
-                                               intermediate_nodes: vec![], destination, first_node_addresses
-                                       })
-                               },
-                               _ => Err(()),
-                       }
-               }
-       }
 
-       fn create_blinded_paths<
+       fn create_blinded_paths_from_iter<
+               I: Iterator<Item = ForwardNode>,
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
        ) -> Result<Vec<BlindedPath>, ()> {
                // Limit the number of blinded paths that are computed.
                const MAX_PATHS: usize = 3;
@@ -421,7 +499,7 @@ where
                let is_recipient_announced =
                        network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
 
-               let mut peer_info = peers.into_iter()
+               let mut peer_info = peers
                        // Limit to peers with announced channels
                        .filter_map(|peer|
                                network_graph
@@ -456,14 +534,75 @@ where
                                }
                        },
                }?;
-               for path in &mut paths {
-                       path.use_compact_introduction_node(&network_graph);
+
+               if compact_paths {
+                       for path in &mut paths {
+                               path.use_compact_introduction_node(&network_graph);
+                       }
                }
 
                Ok(paths)
        }
 }
 
+impl<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref> MessageRouter for DefaultMessageRouter<G, L, ES>
+where
+       L::Target: Logger,
+       ES::Target: EntropySource,
+{
+       fn find_path(
+               &self, sender: PublicKey, peers: Vec<PublicKey>, mut destination: Destination
+       ) -> Result<OnionMessagePath, ()> {
+               let network_graph = self.network_graph.deref().read_only();
+               destination.resolve(&network_graph);
+
+               let first_node = match destination.first_node() {
+                       Some(first_node) => first_node,
+                       None => return Err(()),
+               };
+
+               if peers.contains(&first_node) || sender == first_node {
+                       Ok(OnionMessagePath {
+                               intermediate_nodes: vec![], destination, first_node_addresses: None
+                       })
+               } else {
+                       let node_details = network_graph
+                               .node(&NodeId::from_pubkey(&first_node))
+                               .and_then(|node_info| node_info.announcement_info.as_ref())
+                               .map(|announcement_info| (announcement_info.features(), announcement_info.addresses()));
+
+                       match node_details {
+                               Some((features, addresses)) if features.supports_onion_messages() && addresses.len() > 0 => {
+                                       let first_node_addresses = Some(addresses.clone());
+                                       Ok(OnionMessagePath {
+                                               intermediate_nodes: vec![], destination, first_node_addresses
+                                       })
+                               },
+                               _ => Err(()),
+                       }
+               }
+       }
+
+       fn create_blinded_paths<
+               T: secp256k1::Signing + secp256k1::Verification
+       >(
+               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               let peers = peers
+                       .into_iter()
+                       .map(|node_id| ForwardNode { node_id, short_channel_id: None });
+               self.create_blinded_paths_from_iter(recipient, peers, secp_ctx, false)
+       }
+
+       fn create_compact_blinded_paths<
+               T: secp256k1::Signing + secp256k1::Verification
+       >(
+               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               self.create_blinded_paths_from_iter(recipient, peers.into_iter(), secp_ctx, true)
+       }
+}
+
 /// A path for sending an [`OnionMessage`].
 #[derive(Clone)]
 pub struct OnionMessagePath {
@@ -564,7 +703,11 @@ pub enum SendError {
        TooFewBlindedHops,
        /// The first hop is not a peer and doesn't have a known [`SocketAddress`].
        InvalidFirstHop(PublicKey),
-       /// A path from the sender to the destination could not be found by the [`MessageRouter`].
+       /// Indicates that a path could not be found by the [`MessageRouter`].
+       ///
+       /// This occurs when either:
+       /// - No path from the sender to the destination was found to send the onion message
+       /// - No reply path to the sender could be created when responding to an onion message
        PathNotFound,
        /// Onion message contents must have a TLV type >= 64.
        InvalidMessage,
@@ -909,7 +1052,10 @@ where
                        offers_handler,
                        custom_handler,
                        intercept_messages_for_offline_peers,
-                       pending_events: Mutex::new(Vec::new()),
+                       pending_events: Mutex::new(PendingEvents {
+                               intercepted_msgs: Vec::new(),
+                               peer_connecteds: Vec::new(),
+                       }),
                }
        }
 
@@ -981,6 +1127,24 @@ where
                        .map_err(|_| SendError::PathNotFound)
        }
 
+       fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
+               let recipient = self.node_signer
+                       .get_node_id(Recipient::Node)
+                       .map_err(|_| SendError::GetNodeIdFailed)?;
+               let secp_ctx = &self.secp_ctx;
+
+               let peers = self.message_recipients.lock().unwrap()
+                       .iter()
+                       .filter(|(_, peer)| matches!(peer, OnionMessageRecipient::ConnectedPeer(_)))
+                       .map(|(node_id, _ )| *node_id)
+                       .collect::<Vec<_>>();
+
+               self.message_router
+                       .create_blinded_paths(recipient, peers, secp_ctx)
+                       .and_then(|paths| paths.into_iter().next().ok_or(()))
+                       .map_err(|_| SendError::PathNotFound)
+       }
+
        fn enqueue_onion_message<T: OnionMessageContents>(
                &self, path: OnionMessagePath, contents: T, reply_path: Option<BlindedPath>,
                log_suffix: fmt::Arguments
@@ -1053,20 +1217,48 @@ where
                )
        }
 
-       fn handle_onion_message_response<T: OnionMessageContents>(
+       /// Handles the response to an [`OnionMessage`] based on its [`ResponseInstruction`],
+       /// enqueueing any response for sending.
+       ///
+       /// This function is useful for asynchronous handling of [`OnionMessage`]s.
+       /// Handlers have the option to return [`ResponseInstruction::NoResponse`], indicating that
+       /// no immediate response should be sent. Then, they can transfer the associated [`Responder`]
+       /// to another task responsible for generating the response asynchronously. Subsequently, when
+       /// the response is prepared and ready for sending, that task can invoke this method to enqueue
+       /// the response for delivery.
+       pub fn handle_onion_message_response<T: OnionMessageContents>(
                &self, response: ResponseInstruction<T>
-       ) {
-               if let ResponseInstruction::WithoutReplyPath(response) = response {
-                       let message_type = response.message.msg_type();
-                       let _ = self.find_path_and_enqueue_onion_message(
-                               response.message, Destination::BlindedPath(response.reply_path), None,
-                               format_args!(
-                                       "when responding with {} to an onion message with path_id {:02x?}",
-                                       message_type,
-                                       response.path_id
-                               )
-                       );
-               }
+       ) -> Result<Option<SendSuccess>, SendError> {
+               let (response, create_reply_path) = match response {
+                       ResponseInstruction::WithReplyPath(response) => (response, true),
+                       ResponseInstruction::WithoutReplyPath(response) => (response, false),
+                       ResponseInstruction::NoResponse => return Ok(None),
+               };
+
+               let message_type = response.message.msg_type();
+               let reply_path = if create_reply_path {
+                       match self.create_blinded_path() {
+                               Ok(reply_path) => Some(reply_path),
+                               Err(err) => {
+                                       log_trace!(
+                                               self.logger,
+                                               "Failed to create reply path when responding with {} to an onion message \
+                                               with path_id {:02x?}: {:?}",
+                                               message_type, response.path_id, err
+                                       );
+                                       return Err(err);
+                               }
+                       }
+               } else { None };
+
+               self.find_path_and_enqueue_onion_message(
+                       response.message, Destination::BlindedPath(response.reply_path), reply_path,
+                       format_args!(
+                               "when responding with {} to an onion message with path_id {:02x?}",
+                               message_type,
+                               response.path_id
+                       )
+               ).map(|result| Some(result))
        }
 
        #[cfg(test)]
@@ -1081,18 +1273,61 @@ where
                msgs
        }
 
-       fn enqueue_event(&self, event: Event) {
+       fn enqueue_intercepted_event(&self, event: Event) {
                const MAX_EVENTS_BUFFER_SIZE: usize = (1 << 10) * 256;
                let mut pending_events = self.pending_events.lock().unwrap();
-               let total_buffered_bytes: usize = pending_events
-                       .iter()
-                       .map(|ev| ev.serialized_length())
-                       .sum();
+               let total_buffered_bytes: usize =
+                       pending_events.intercepted_msgs.iter().map(|ev| ev.serialized_length()).sum();
                if total_buffered_bytes >= MAX_EVENTS_BUFFER_SIZE {
                        log_trace!(self.logger, "Dropping event {:?}: buffer full", event);
                        return
                }
-               pending_events.push(event);
+               pending_events.intercepted_msgs.push(event);
+       }
+
+       /// Processes any events asynchronously using the given handler.
+       ///
+       /// Note that the event handler is called in the order each event was generated, however
+       /// futures are polled in parallel for some events to allow for parallelism where events do not
+       /// have an ordering requirement.
+       ///
+       /// See the trait-level documentation of [`EventsProvider`] for requirements.
+       pub async fn process_pending_events_async<Future: core::future::Future<Output = ()> + core::marker::Unpin, H: Fn(Event) -> Future>(
+               &self, handler: H
+       ) {
+               let mut intercepted_msgs = Vec::new();
+               let mut peer_connecteds = Vec::new();
+               {
+                       let mut pending_events = self.pending_events.lock().unwrap();
+                       core::mem::swap(&mut pending_events.intercepted_msgs, &mut intercepted_msgs);
+                       core::mem::swap(&mut pending_events.peer_connecteds, &mut peer_connecteds);
+               }
+
+               let mut futures = Vec::with_capacity(intercepted_msgs.len());
+               for (node_id, recipient) in self.message_recipients.lock().unwrap().iter_mut() {
+                       if let OnionMessageRecipient::PendingConnection(_, addresses, _) = recipient {
+                               if let Some(addresses) = addresses.take() {
+                                       futures.push(Some(handler(Event::ConnectionNeeded { node_id: *node_id, addresses })));
+                               }
+                       }
+               }
+
+               for ev in intercepted_msgs {
+                       if let Event::OnionMessageIntercepted { .. } = ev {} else { debug_assert!(false); }
+                       futures.push(Some(handler(ev)));
+               }
+               // Let the `OnionMessageIntercepted` events finish before moving on to peer_connecteds
+               crate::util::async_poll::MultiFuturePoller(futures).await;
+
+               if peer_connecteds.len() <= 1 {
+                       for event in peer_connecteds { handler(event).await; }
+               } else {
+                       let mut futures = Vec::new();
+                       for event in peer_connecteds {
+                               futures.push(Some(handler(event)));
+                       }
+                       crate::util::async_poll::MultiFuturePoller(futures).await;
+               }
        }
 }
 
@@ -1139,7 +1374,20 @@ where
                        }
                }
                let mut events = Vec::new();
-               core::mem::swap(&mut *self.pending_events.lock().unwrap(), &mut events);
+               {
+                       let mut pending_events = self.pending_events.lock().unwrap();
+                       #[cfg(debug_assertions)] {
+                               for ev in pending_events.intercepted_msgs.iter() {
+                                       if let Event::OnionMessageIntercepted { .. } = ev {} else { panic!(); }
+                               }
+                               for ev in pending_events.peer_connecteds.iter() {
+                                       if let Event::OnionMessagePeerConnected { .. } = ev {} else { panic!(); }
+                               }
+                       }
+                       core::mem::swap(&mut pending_events.intercepted_msgs, &mut events);
+                       events.append(&mut pending_events.peer_connecteds);
+                       pending_events.peer_connecteds.shrink_to(10); // Limit total heap usage
+               }
                for ev in events {
                        handler.handle_event(ev);
                }
@@ -1172,14 +1420,14 @@ where
                                                        |reply_path| Responder::new(reply_path, path_id)
                                                );
                                                let response_instructions = self.offers_handler.handle_message(msg, responder);
-                                               self.handle_onion_message_response(response_instructions);
+                                               let _ = self.handle_onion_message_response(response_instructions);
                                        },
                                        ParsedOnionMessageContents::Custom(msg) => {
                                                let responder = reply_path.map(
                                                        |reply_path| Responder::new(reply_path, path_id)
                                                );
                                                let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
-                                               self.handle_onion_message_response(response_instructions);
+                                               let _ = self.handle_onion_message_response(response_instructions);
                                        },
                                }
                        },
@@ -1217,7 +1465,7 @@ where
                                                log_trace!(logger, "Forwarding an onion message to peer {}", next_node_id);
                                        },
                                        _ if self.intercept_messages_for_offline_peers => {
-                                               self.enqueue_event(
+                                               self.enqueue_intercepted_event(
                                                        Event::OnionMessageIntercepted {
                                                                peer_node_id: next_node_id, message: onion_message
                                                        }
@@ -1245,7 +1493,7 @@ where
                                .or_insert_with(|| OnionMessageRecipient::ConnectedPeer(VecDeque::new()))
                                .mark_connected();
                        if self.intercept_messages_for_offline_peers {
-                               self.enqueue_event(
+                               self.pending_events.lock().unwrap().peer_connecteds.push(
                                        Event::OnionMessagePeerConnected { peer_node_id: *their_node_id }
                                );
                        }
index b169b356f3f28101e3f521bd18a67e96657babe0..c7908d0040c1283347155b32ee7bcd95d8db0720 100644 (file)
@@ -9,41 +9,42 @@
 
 //! The [`NetworkGraph`] stores the network gossip and [`P2PGossipSync`] fetches it from peers
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 
+use bitcoin::secp256k1;
 use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
-use bitcoin::secp256k1::{PublicKey, Verification};
 use bitcoin::secp256k1::Secp256k1;
-use bitcoin::secp256k1;
+use bitcoin::secp256k1::{PublicKey, Verification};
 
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 
 use crate::events::{MessageSendEvent, MessageSendEventsProvider};
-use crate::ln::types::ChannelId;
-use crate::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
-use crate::ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, SocketAddress, MAX_VALUE_MSAT};
-use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter};
-use crate::ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
+use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use crate::ln::msgs;
+use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, GossipTimestampFilter, NodeAnnouncement};
+use crate::ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, SocketAddress, MAX_VALUE_MSAT};
+use crate::ln::msgs::{QueryChannelRange, QueryShortChannelIds, ReplyChannelRange, ReplyShortChannelIdsEnd};
+use crate::ln::types::ChannelId;
 use crate::routing::utxo::{self, UtxoLookup, UtxoResolver};
-use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable};
-use crate::util::logger::{Logger, Level};
+use crate::util::indexed_map::{Entry as IndexedMapEntry, IndexedMap};
+use crate::util::logger::{Level, Logger};
 use crate::util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
+use crate::util::ser::{MaybeReadable, Readable, ReadableArgs, RequiredWrapper, Writeable, Writer};
 use crate::util::string::PrintableString;
-use crate::util::indexed_map::{IndexedMap, Entry as IndexedMapEntry};
 
 use crate::io;
 use crate::io_extras::{copy, sink};
 use crate::prelude::*;
-use core::{cmp, fmt};
-use crate::sync::{RwLock, RwLockReadGuard, LockTestExt};
-#[cfg(feature = "std")]
-use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::Mutex;
+use crate::sync::{LockTestExt, RwLock, RwLockReadGuard};
 use core::ops::{Bound, Deref};
 use core::str::FromStr;
+#[cfg(feature = "std")]
+use core::sync::atomic::{AtomicUsize, Ordering};
+use core::{cmp, fmt};
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -218,12 +219,6 @@ pub struct ReadOnlyNetworkGraph<'a> {
 /// [BOLT #4]: https://github.com/lightning/bolts/blob/master/04-onion-routing.md
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum NetworkUpdate {
-       /// An error indicating a `channel_update` messages should be applied via
-       /// [`NetworkGraph::update_channel`].
-       ChannelUpdateMessage {
-               /// The update to apply via [`NetworkGraph::update_channel`].
-               msg: ChannelUpdate,
-       },
        /// An error indicating that a channel failed to route a payment, which should be applied via
        /// [`NetworkGraph::channel_failed_permanent`] if permanent.
        ChannelFailure {
@@ -244,19 +239,69 @@ pub enum NetworkUpdate {
        }
 }
 
-impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
-       (0, ChannelUpdateMessage) => {
-               (0, msg, required),
-       },
-       (2, ChannelFailure) => {
-               (0, short_channel_id, required),
-               (2, is_permanent, required),
-       },
-       (4, NodeFailure) => {
-               (0, node_id, required),
-               (2, is_permanent, required),
-       },
-);
+impl Writeable for NetworkUpdate {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               match self {
+                       Self::ChannelFailure { short_channel_id, is_permanent } => {
+                               2u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, short_channel_id, required),
+                                       (2, is_permanent, required),
+                               });
+                       },
+                       Self::NodeFailure { node_id, is_permanent } => {
+                               4u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, node_id, required),
+                                       (2, is_permanent, required),
+                               });
+                       }
+               }
+               Ok(())
+       }
+}
+
+impl MaybeReadable for NetworkUpdate {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, DecodeError> {
+               let id: u8 = Readable::read(reader)?;
+               match id {
+                       0 => {
+                               // 0 was previously used for network updates containing a channel update, subsequently
+                               // removed in LDK version 0.0.124.
+                               let mut msg: RequiredWrapper<ChannelUpdate> = RequiredWrapper(None);
+                               read_tlv_fields!(reader, {
+                                       (0, msg, required),
+                               });
+                               Ok(Some(Self::ChannelFailure {
+                                       short_channel_id: msg.0.unwrap().contents.short_channel_id,
+                                       is_permanent: false
+                               }))
+                       },
+                       2 => {
+                               _init_and_read_len_prefixed_tlv_fields!(reader, {
+                                       (0, short_channel_id, required),
+                                       (2, is_permanent, required),
+                               });
+                               Ok(Some(Self::ChannelFailure {
+                                       short_channel_id: short_channel_id.0.unwrap(),
+                                       is_permanent: is_permanent.0.unwrap(),
+                               }))
+                       },
+                       4 => {
+                               _init_and_read_len_prefixed_tlv_fields!(reader, {
+                                       (0, node_id, required),
+                                       (2, is_permanent, required),
+                               });
+                               Ok(Some(Self::NodeFailure {
+                                       node_id: node_id.0.unwrap(),
+                                       is_permanent: is_permanent.0.unwrap(),
+                               }))
+                       }
+                       t if t % 2 == 0 => Err(DecodeError::UnknownRequiredFeature),
+                       _ => Ok(None),
+               }
+       }
+}
 
 /// Receives and validates network updates from peers,
 /// stores authentic and relevant data as a network graph.
@@ -353,19 +398,10 @@ where U::Target: UtxoLookup, L::Target: Logger
 
 impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        /// Handles any network updates originating from [`Event`]s.
-       //
-       /// Note that this will skip applying any [`NetworkUpdate::ChannelUpdateMessage`] to avoid
-       /// leaking possibly identifying information of the sender to the public network.
        ///
        /// [`Event`]: crate::events::Event
        pub fn handle_network_update(&self, network_update: &NetworkUpdate) {
                match *network_update {
-                       NetworkUpdate::ChannelUpdateMessage { ref msg } => {
-                               let short_channel_id = msg.contents.short_channel_id;
-                               let is_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
-                               let status = if is_enabled { "enabled" } else { "disabled" };
-                               log_debug!(self.logger, "Skipping application of a channel update from a payment failure. Channel {} is {}.", short_channel_id, status);
-                       },
                        NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } => {
                                if is_permanent {
                                        log_debug!(self.logger, "Removing channel graph entry for {} due to a payment failure.", short_channel_id);
@@ -504,8 +540,8 @@ where U::Target: UtxoLookup, L::Target: Logger
                        };
                for (_, ref node) in iter {
                        if let Some(node_info) = node.announcement_info.as_ref() {
-                               if let Some(msg) = node_info.announcement_message.clone() {
-                                       return Some(msg);
+                               if let NodeAnnouncementInfo::Relayed(announcement) = node_info {
+                                       return Some(announcement.clone());
                                }
                        }
                }
@@ -1134,45 +1170,136 @@ impl_writeable_tlv_based!(RoutingFees, {
 });
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-/// Information received in the latest node_announcement from this node.
-pub struct NodeAnnouncementInfo {
+/// Non-relayable information received in the latest node_announcement from this node.
+pub struct NodeAnnouncementDetails {
        /// Protocol features the node announced support for
        pub features: NodeFeatures,
+
        /// When the last known update to the node state was issued.
        /// Value is opaque, as set in the announcement.
        pub last_update: u32,
+
        /// Color assigned to the node
        pub rgb: [u8; 3],
+
        /// Moniker assigned to the node.
        /// May be invalid or malicious (eg control chars),
        /// should not be exposed to the user.
        pub alias: NodeAlias,
+
+       /// Internet-level addresses via which one can connect to the node
+       pub addresses: Vec<SocketAddress>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+/// Information received in the latest node_announcement from this node.
+pub enum NodeAnnouncementInfo {
        /// An initial announcement of the node
-       /// Mostly redundant with the data we store in fields explicitly.
        /// Everything else is useful only for sending out for initial routing sync.
        /// Not stored if contains excess data to prevent DoS.
-       pub announcement_message: Option<NodeAnnouncement>
+       Relayed(NodeAnnouncement),
+
+       /// Non-relayable information received in the latest node_announcement from this node.
+       Local(NodeAnnouncementDetails),
 }
 
 impl NodeAnnouncementInfo {
+
+       /// Protocol features the node announced support for
+       pub fn features(&self) -> &NodeFeatures {
+               match self {
+                       NodeAnnouncementInfo::Relayed(relayed) => {
+                               &relayed.contents.features
+                       }
+                       NodeAnnouncementInfo::Local(local) => {
+                               &local.features
+                       }
+               }
+       }
+
+       /// When the last known update to the node state was issued.
+       ///
+       /// Value may or may not be a timestamp, depending on the policy of the origin node.
+       pub fn last_update(&self) -> u32 {
+               match self {
+                       NodeAnnouncementInfo::Relayed(relayed) => {
+                               relayed.contents.timestamp
+                       }
+                       NodeAnnouncementInfo::Local(local) => {
+                               local.last_update
+                       }
+               }
+       }
+
+       /// Color assigned to the node
+       pub fn rgb(&self) -> [u8; 3] {
+               match self {
+                       NodeAnnouncementInfo::Relayed(relayed) => {
+                               relayed.contents.rgb
+                       }
+                       NodeAnnouncementInfo::Local(local) => {
+                               local.rgb
+                       }
+               }
+       }
+
+       /// Moniker assigned to the node.
+       ///
+       /// May be invalid or malicious (eg control chars), should not be exposed to the user.
+       pub fn alias(&self) -> &NodeAlias {
+               match self {
+                       NodeAnnouncementInfo::Relayed(relayed) => {
+                               &relayed.contents.alias
+                       }
+                       NodeAnnouncementInfo::Local(local) => {
+                               &local.alias
+                       }
+               }
+       }
+
        /// Internet-level addresses via which one can connect to the node
-       pub fn addresses(&self) -> &[SocketAddress] {
-               self.announcement_message.as_ref()
-                       .map(|msg| msg.contents.addresses.as_slice())
-                       .unwrap_or_default()
+       pub fn addresses(&self) -> &Vec<SocketAddress> {
+               match self {
+                       NodeAnnouncementInfo::Relayed(relayed) => {
+                               &relayed.contents.addresses
+                       }
+                       NodeAnnouncementInfo::Local(local) => {
+                               &local.addresses
+                       }
+               }
+       }
+
+       /// An initial announcement of the node
+       ///
+       /// Not stored if contains excess data to prevent DoS.
+       pub fn announcement_message(&self) -> Option<&NodeAnnouncement> {
+               match self {
+                       NodeAnnouncementInfo::Relayed(announcement) => {
+                               Some(announcement)
+                       }
+                       NodeAnnouncementInfo::Local(_) => {
+                               None
+                       }
+               }
        }
 }
 
 impl Writeable for NodeAnnouncementInfo {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
-               let empty_addresses = Vec::<SocketAddress>::new();
+               let features = self.features();
+               let last_update = self.last_update();
+               let rgb = self.rgb();
+               let alias = self.alias();
+               let addresses = self.addresses();
+               let announcement_message = self.announcement_message();
+
                write_tlv_fields!(writer, {
-                       (0, self.features, required),
-                       (2, self.last_update, required),
-                       (4, self.rgb, required),
-                       (6, self.alias, required),
-                       (8, self.announcement_message, option),
-                       (10, empty_addresses, required_vec), // Versions prior to 0.0.115 require this field
+                       (0, features, required),
+                       (2, last_update, required),
+                       (4, rgb, required),
+                       (6, alias, required),
+                       (8, announcement_message, option),
+                       (10, *addresses, required_vec), // Versions 0.0.115 through 0.0.123 only serialized an empty vec
                });
                Ok(())
        }
@@ -1186,11 +1313,19 @@ impl Readable for NodeAnnouncementInfo {
                        (4, rgb, required),
                        (6, alias, required),
                        (8, announcement_message, option),
-                       (10, _addresses, optional_vec), // deprecated, not used anymore
+                       (10, addresses, required_vec),
                });
-               let _: Option<Vec<SocketAddress>> = _addresses;
-               Ok(Self { features: features.0.unwrap(), last_update: last_update.0.unwrap(), rgb: rgb.0.unwrap(),
-                       alias: alias.0.unwrap(), announcement_message })
+               if let Some(announcement) = announcement_message {
+                       Ok(Self::Relayed(announcement))
+               } else {
+                       Ok(Self::Local(NodeAnnouncementDetails {
+                               features: features.0.unwrap(),
+                               last_update: last_update.0.unwrap(),
+                               rgb: rgb.0.unwrap(),
+                               alias: alias.0.unwrap(),
+                               addresses,
+                       }))
+               }
        }
 }
 
@@ -1492,24 +1627,29 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                        // The timestamp field is somewhat of a misnomer - the BOLTs use it to order
                                        // updates to ensure you always have the latest one, only vaguely suggesting
                                        // that it be at least the current time.
-                                       if node_info.last_update  > msg.timestamp {
+                                       if node_info.last_update()  > msg.timestamp {
                                                return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
-                                       } else if node_info.last_update  == msg.timestamp {
+                                       } else if node_info.last_update()  == msg.timestamp {
                                                return Err(LightningError{err: "Update had the same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
                                        }
                                }
 
                                let should_relay =
                                        msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
-                                       msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
-                                       msg.excess_data.len() + msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY;
-                               node.announcement_info = Some(NodeAnnouncementInfo {
-                                       features: msg.features.clone(),
-                                       last_update: msg.timestamp,
-                                       rgb: msg.rgb,
-                                       alias: msg.alias,
-                                       announcement_message: if should_relay { full_msg.cloned() } else { None },
-                               });
+                                               msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
+                                               msg.excess_data.len() + msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY;
+
+                               node.announcement_info = if let (Some(signed_announcement), true) = (full_msg, should_relay) {
+                                       Some(NodeAnnouncementInfo::Relayed(signed_announcement.clone()))
+                               } else {
+                                       Some(NodeAnnouncementInfo::Local(NodeAnnouncementDetails {
+                                               features: msg.features.clone(),
+                                               last_update: msg.timestamp,
+                                               rgb: msg.rgb,
+                                               alias: msg.alias,
+                                               addresses: msg.addresses.clone(),
+                                       }))
+                               };
 
                                Ok(())
                        }
@@ -1589,7 +1729,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                self.add_channel_between_nodes(short_channel_id, channel_info, None)
        }
 
-       fn add_channel_between_nodes(&self, short_channel_id: u64, channel_info: ChannelInfo, utxo_value: Option<u64>) -> Result<(), LightningError> {
+       fn add_channel_between_nodes(&self, short_channel_id: u64, channel_info: ChannelInfo, utxo_value: Option<Amount>) -> Result<(), LightningError> {
                let mut channels = self.channels.write().unwrap();
                let mut nodes = self.nodes.write().unwrap();
 
@@ -1718,7 +1858,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                        one_to_two: None,
                        node_two: msg.node_id_2,
                        two_to_one: None,
-                       capacity_sats: utxo_value,
+                       capacity_sats: utxo_value.map(|a| a.to_sat()),
                        announcement_message: if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY
                                { full_msg.cloned() } else { None },
                        announcement_received_time,
@@ -2131,7 +2271,8 @@ pub(crate) mod tests {
        use bitcoin::hashes::sha256d::Hash as Sha256dHash;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::hex::FromHex;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::ScriptBuf;
        use bitcoin::blockdata::transaction::TxOut;
@@ -2224,7 +2365,7 @@ pub(crate) mod tests {
                let node_1_btckey = SecretKey::from_slice(&[40; 32]).unwrap();
                let node_2_btckey = SecretKey::from_slice(&[39; 32]).unwrap();
                make_funding_redeemscript(&PublicKey::from_secret_key(secp_ctx, &node_1_btckey),
-                       &PublicKey::from_secret_key(secp_ctx, &node_2_btckey)).to_v0_p2wsh()
+                       &PublicKey::from_secret_key(secp_ctx, &node_2_btckey)).to_p2wsh()
        }
 
        pub(crate) fn get_signed_channel_update<F: Fn(&mut UnsignedChannelUpdate)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelUpdate {
@@ -2357,7 +2498,7 @@ pub(crate) mod tests {
 
                // Now test if the transaction is found in the UTXO set and the script is correct.
                *chain_source.utxo_ret.lock().unwrap() =
-                       UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script.clone() }));
+                       UtxoResult::Sync(Ok(TxOut { value: Amount::ZERO, script_pubkey: good_script.clone() }));
                let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| {
                        unsigned_announcement.short_channel_id += 2;
                }, node_1_privkey, node_2_privkey, &secp_ctx);
@@ -2376,7 +2517,7 @@ pub(crate) mod tests {
                // If we receive announcement for the same channel, once we've validated it against the
                // chain, we simply ignore all new (duplicate) announcements.
                *chain_source.utxo_ret.lock().unwrap() =
-                       UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script }));
+                       UtxoResult::Sync(Ok(TxOut { value: Amount::ZERO, script_pubkey: good_script }));
                match gossip_sync.handle_channel_announcement(&valid_announcement) {
                        Ok(_) => panic!(),
                        Err(e) => assert_eq!(e.err, "Already have chain-validated channel")
@@ -2453,7 +2594,7 @@ pub(crate) mod tests {
                let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
                let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
 
-               let amount_sats = 1000_000;
+               let amount_sats = Amount::from_sat(1000_000);
                let short_channel_id;
 
                {
@@ -2517,7 +2658,7 @@ pub(crate) mod tests {
                };
 
                let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| {
-                       unsigned_channel_update.htlc_maximum_msat = amount_sats * 1000 + 1;
+                       unsigned_channel_update.htlc_maximum_msat = amount_sats.to_sat() * 1000 + 1;
                        unsigned_channel_update.timestamp += 110;
                }, node_1_privkey, &secp_ctx);
                match gossip_sync.handle_channel_update(&valid_channel_update) {
@@ -2575,8 +2716,7 @@ pub(crate) mod tests {
 
                let short_channel_id;
                {
-                       // Check we won't apply an update via `handle_network_update` for privacy reasons, but
-                       // can continue fine if we manually apply it.
+                       // Check that we can manually apply a channel update.
                        let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
                        short_channel_id = valid_channel_announcement.contents.short_channel_id;
                        let chain_source: Option<&test_utils::TestChainSource> = None;
@@ -2584,14 +2724,10 @@ pub(crate) mod tests {
                        assert!(network_graph.read_only().channels().get(&short_channel_id).is_some());
 
                        let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx);
-                       assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
-
-                       network_graph.handle_network_update(&NetworkUpdate::ChannelUpdateMessage {
-                               msg: valid_channel_update.clone(),
-                       });
 
                        assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
                        network_graph.update_channel(&valid_channel_update).unwrap();
+                       assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some());
                }
 
                // Non-permanent failure doesn't touch the channel at all
@@ -3452,13 +3588,7 @@ pub(crate) mod tests {
                // 1. Check we can read a valid NodeAnnouncementInfo and fail on an invalid one
                let announcement_message = <Vec<u8>>::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000122013413a7031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f2020201010101010101010101010101010101010101010101010101010101010101010000701fffefdfc2607").unwrap();
                let announcement_message = NodeAnnouncement::read(&mut announcement_message.as_slice()).unwrap();
-               let valid_node_ann_info = NodeAnnouncementInfo {
-                       features: channelmanager::provided_node_features(&UserConfig::default()),
-                       last_update: 0,
-                       rgb: [0u8; 3],
-                       alias: NodeAlias([0u8; 32]),
-                       announcement_message: Some(announcement_message)
-               };
+               let valid_node_ann_info = NodeAnnouncementInfo::Relayed(announcement_message);
 
                let mut encoded_valid_node_ann_info = Vec::new();
                assert!(valid_node_ann_info.write(&mut encoded_valid_node_ann_info).is_ok());
@@ -3491,8 +3621,8 @@ pub(crate) mod tests {
                let old_ann_info_with_addresses = <Vec<u8>>::from_hex("3f0009000708a000080a51220204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014104d2").unwrap();
                let ann_info_with_addresses = NodeAnnouncementInfo::read(&mut old_ann_info_with_addresses.as_slice())
                                .expect("to be able to read an old NodeAnnouncementInfo with addresses");
-               // This serialized info has an address field but no announcement_message, therefore the addresses returned by our function will still be empty
-               assert!(ann_info_with_addresses.addresses().is_empty());
+               // This serialized info has no announcement_message but its address field should still be considered
+               assert!(!ann_info_with_addresses.addresses().is_empty());
        }
 
        #[test]
index b4b238e820b2c6d4ad0f1e9f0ccf096010bd21ec..5b202604e371a5624a5cce671f2ec3fbe44a7eab 100644 (file)
@@ -15,7 +15,8 @@ use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode};
 use crate::blinded_path::message;
 use crate::blinded_path::payment::{ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, self};
 use crate::ln::{PaymentHash, PaymentPreimage};
-use crate::ln::channelmanager::{ChannelDetails, PaymentId, MIN_FINAL_CLTV_EXPIRY_DELTA, RecipientOnionFields};
+use crate::ln::channel_state::ChannelDetails;
+use crate::ln::channelmanager::{PaymentId, MIN_FINAL_CLTV_EXPIRY_DELTA, RecipientOnionFields};
 use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
 use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
 use crate::ln::onion_utils;
@@ -35,6 +36,11 @@ use core::{cmp, fmt};
 use core::ops::Deref;
 
 /// A [`Router`] implemented using [`find_route`].
+///
+/// # Privacy
+///
+/// Implements [`MessageRouter`] by delegating to [`DefaultMessageRouter`]. See those docs for
+/// privacy implications.
 pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> where
        L::Target: Logger,
        S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
@@ -172,10 +178,18 @@ impl< G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        > (
-               &self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                self.message_router.create_blinded_paths(recipient, peers, secp_ctx)
        }
+
+       fn create_compact_blinded_paths<
+               T: secp256k1::Signing + secp256k1::Verification
+       > (
+               &self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               self.message_router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+       }
 }
 
 /// A trait defining behavior for routing a payment.
@@ -2009,18 +2023,34 @@ where L::Target: Logger {
                true
        } else if let Some(payee) = payee_node_id_opt {
                network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false,
-                       |info| info.features.supports_basic_mpp()))
+                       |info| info.features().supports_basic_mpp()))
        } else { false };
 
        let max_total_routing_fee_msat = route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value());
 
+       let first_hop_count = first_hops.map(|hops| hops.len()).unwrap_or(0);
        log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph of {} nodes and {} channels with a fee limit of {} msat",
                our_node_pubkey, LoggedPayeePubkey(payment_params.payee.node_id()),
                if allow_mpp { "with" } else { "without" },
-               first_hops.map(|hops| hops.len()).unwrap_or(0), if first_hops.is_some() { "" } else { "not " },
+               first_hop_count, if first_hops.is_some() { "" } else { "not " },
                network_graph.nodes().len(), network_graph.channels().len(),
                max_total_routing_fee_msat);
 
+       if first_hop_count < 10 {
+               if let Some(hops) = first_hops {
+                       for hop in hops {
+                               log_trace!(
+                                       logger,
+                                       " First hop through {}/{} can send between {}msat and {}msat (inclusive).",
+                                       hop.counterparty.node_id,
+                                       hop.get_outbound_payment_scid().unwrap_or(0),
+                                       hop.next_outbound_htlc_minimum_msat,
+                                       hop.next_outbound_htlc_limit_msat
+                               );
+                       }
+               }
+       }
+
        // Step (1).
        // Prepare the data we'll use for payee-to-payer search by
        // inserting first hops suggested by the caller as targets.
@@ -2227,14 +2257,9 @@ where L::Target: Logger {
                                        // around again with a higher amount.
                                        if !contributes_sufficient_value {
                                                if should_log_candidate {
-                                                       log_trace!(logger, "Ignoring {} due to insufficient value contribution.", LoggedCandidateHop(&$candidate));
-
-                                                       if let Some(details) = first_hop_details {
-                                                               log_trace!(logger,
-                                                                       "First hop candidate next_outbound_htlc_limit_msat: {}",
-                                                                       details.next_outbound_htlc_limit_msat,
-                                                               );
-                                                       }
+                                                       log_trace!(logger, "Ignoring {} due to insufficient value contribution (channel max {:?}).",
+                                                               LoggedCandidateHop(&$candidate),
+                                                               effective_capacity);
                                                }
                                                num_ignored_value_contribution += 1;
                                        } else if exceeds_max_path_length {
@@ -2263,15 +2288,8 @@ where L::Target: Logger {
                                        } else if may_overpay_to_meet_path_minimum_msat {
                                                if should_log_candidate {
                                                        log_trace!(logger,
-                                                               "Ignoring {} to avoid overpaying to meet htlc_minimum_msat limit.",
-                                                               LoggedCandidateHop(&$candidate));
-
-                                                       if let Some(details) = first_hop_details {
-                                                               log_trace!(logger,
-                                                                       "First hop candidate next_outbound_htlc_minimum_msat: {}",
-                                                                       details.next_outbound_htlc_minimum_msat,
-                                                               );
-                                                       }
+                                                               "Ignoring {} to avoid overpaying to meet htlc_minimum_msat limit ({}).",
+                                                               LoggedCandidateHop(&$candidate), $candidate.htlc_minimum_msat());
                                                }
                                                num_ignored_avoid_overpayment += 1;
                                                hit_minimum_limit = true;
@@ -2495,7 +2513,7 @@ where L::Target: Logger {
                                }
 
                                let features = if let Some(node_info) = $node.announcement_info.as_ref() {
-                                       &node_info.features
+                                       &node_info.features()
                                } else {
                                        &default_node_features
                                };
@@ -2824,7 +2842,7 @@ where L::Target: Logger {
                                        if !features_set {
                                                if let Some(node) = network_nodes.get(&target) {
                                                        if let Some(node_info) = node.announcement_info.as_ref() {
-                                                               ordered_hops.last_mut().unwrap().1 = node_info.features.clone();
+                                                               ordered_hops.last_mut().unwrap().1 = node_info.features().clone();
                                                        } else {
                                                                ordered_hops.last_mut().unwrap().1 = default_node_features.clone();
                                                        }
@@ -3317,6 +3335,7 @@ mod tests {
        use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
        use crate::chain::transaction::OutPoint;
        use crate::sign::EntropySource;
+       use crate::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelShutdownState};
        use crate::ln::types::ChannelId;
        use crate::ln::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures};
        use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
@@ -3329,8 +3348,9 @@ mod tests {
        #[cfg(c_bindings)]
        use crate::util::ser::Writer;
 
+       use bitcoin::amount::Amount;
        use bitcoin::hashes::Hash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::Builder;
        use bitcoin::blockdata::opcodes;
@@ -3344,10 +3364,10 @@ mod tests {
        use crate::sync::Arc;
 
        fn get_channel_details(short_channel_id: Option<u64>, node_id: PublicKey,
-                       features: InitFeatures, outbound_capacity_msat: u64) -> channelmanager::ChannelDetails {
-               channelmanager::ChannelDetails {
+                       features: InitFeatures, outbound_capacity_msat: u64) -> ChannelDetails {
+               ChannelDetails {
                        channel_id: ChannelId::new_zero(),
-                       counterparty: channelmanager::ChannelCounterparty {
+                       counterparty: ChannelCounterparty {
                                features,
                                node_id,
                                unspendable_punishment_reserve: 0,
@@ -3377,7 +3397,7 @@ mod tests {
                        inbound_htlc_maximum_msat: None,
                        config: None,
                        feerate_sat_per_1000_weight: None,
-                       channel_shutdown_state: Some(channelmanager::ChannelShutdownState::NotShuttingDown),
+                       channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
                        pending_inbound_htlcs: Vec::new(),
                        pending_outbound_htlcs: Vec::new(),
                }
@@ -4888,10 +4908,10 @@ mod tests {
                .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize())
                .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize())
                .push_opcode(opcodes::all::OP_PUSHNUM_2)
-               .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
+               .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_p2wsh();
 
                *chain_monitor.utxo_ret.lock().unwrap() =
-                       UtxoResult::Sync(Ok(TxOut { value: 15, script_pubkey: good_script.clone() }));
+                       UtxoResult::Sync(Ok(TxOut { value: Amount::from_sat(15), script_pubkey: good_script.clone() }));
                gossip_sync.add_utxo_lookup(Some(chain_monitor));
 
                add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
@@ -8499,8 +8519,9 @@ pub(crate) mod bench_utils {
        use crate::chain::transaction::OutPoint;
        use crate::routing::scoring::ScoreUpdate;
        use crate::sign::KeysManager;
+       use crate::ln::channel_state::{ChannelCounterparty, ChannelShutdownState};
+       use crate::ln::channelmanager;
        use crate::ln::types::ChannelId;
-       use crate::ln::channelmanager::{self, ChannelCounterparty};
        use crate::util::config::UserConfig;
        use crate::util::test_utils::TestLogger;
 
@@ -8585,7 +8606,7 @@ pub(crate) mod bench_utils {
                        inbound_htlc_maximum_msat: None,
                        config: None,
                        feerate_sat_per_1000_weight: None,
-                       channel_shutdown_state: Some(channelmanager::ChannelShutdownState::NotShuttingDown),
+                       channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
                        pending_inbound_htlcs: Vec::new(),
                        pending_outbound_htlcs: Vec::new(),
                }
index 4cb9144d3394ed94896b861e5ac847994776f122..d782958ca9157a5fc1928b9dab0fb28241a8f484 100644 (file)
@@ -2166,7 +2166,7 @@ mod tests {
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::sha256d::Hash as Sha256dHash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
        use core::time::Duration;
        use crate::io;
index 6aca76a21678ceabc25f3e66ded06c96b1f883aa..6337adfb81c09088a653102f7f01bc12c04daedc 100644 (file)
@@ -17,7 +17,7 @@ use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::hex::FromHex;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::secp256k1::{PublicKey,SecretKey};
 use bitcoin::secp256k1::{Secp256k1, All};
 
index e775e2628f6ca1df9e497a084506be7dd7eed6eb..b4b8bf5144ee8c148305d1fd29ccc6346526805e 100644 (file)
@@ -14,6 +14,7 @@
 //! order to announce a channel. This module handles that checking.
 
 use bitcoin::TxOut;
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 
 use hex::DisplayHex;
@@ -455,12 +456,12 @@ impl PendingChecks {
        pub(super) fn check_channel_announcement<U: Deref>(&self,
                utxo_lookup: &Option<U>, msg: &msgs::UnsignedChannelAnnouncement,
                full_msg: Option<&msgs::ChannelAnnouncement>
-       ) -> Result<Option<u64>, msgs::LightningError> where U::Target: UtxoLookup {
+       ) -> Result<Option<Amount>, msgs::LightningError> where U::Target: UtxoLookup {
                let handle_result = |res| {
                        match res {
                                Ok(TxOut { value, script_pubkey }) => {
                                        let expected_script =
-                                               make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_array(), msg.bitcoin_key_2.as_array()).to_v0_p2wsh();
+                                               make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_array(), msg.bitcoin_key_2.as_array()).to_p2wsh();
                                        if script_pubkey != expected_script {
                                                return Err(LightningError{
                                                        err: format!("Channel announcement key ({}) didn't match on-chain script ({})",
@@ -564,6 +565,7 @@ mod tests {
        use crate::routing::gossip::tests::*;
        use crate::util::test_utils::{TestChainSource, TestLogger};
 
+       use bitcoin::amount::Amount;
        use bitcoin::secp256k1::{Secp256k1, SecretKey};
 
        use core::sync::atomic::Ordering;
@@ -610,7 +612,7 @@ mod tests {
 
                let future = UtxoFuture::new();
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+                       Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }));
                *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone());
 
                network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap();
@@ -632,7 +634,7 @@ mod tests {
                assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
 
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 0, script_pubkey: good_script }));
+                       Ok(TxOut { value: Amount::ZERO, script_pubkey: good_script }));
                network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap();
                network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap();
 
@@ -660,7 +662,7 @@ mod tests {
                assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
 
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 1_000_000, script_pubkey: bitcoin::ScriptBuf::new() }));
+                       Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: bitcoin::ScriptBuf::new() }));
                assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none());
        }
 
@@ -709,7 +711,7 @@ mod tests {
                        "Awaiting channel_announcement validation to accept channel_update");
 
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+                       Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }));
 
                assert!(network_graph.read_only().channels()
                        .get(&valid_announcement.contents.short_channel_id).unwrap().one_to_two.is_some());
@@ -745,7 +747,7 @@ mod tests {
                        "Awaiting channel_announcement validation to accept channel_update");
 
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+                       Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }));
 
                assert_eq!(chan_update_a.contents.timestamp, chan_update_b.contents.timestamp);
                let graph_lock = network_graph.read_only();
@@ -792,7 +794,7 @@ mod tests {
 
                // Still, if we resolve the original future, the original channel will be accepted.
                future.resolve_without_forwarding(&network_graph,
-                       Ok(TxOut { value: 1_000_000, script_pubkey: good_script }));
+                       Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }));
                assert!(!network_graph.read_only().channels()
                        .get(&valid_announcement.contents.short_channel_id).unwrap()
                        .announcement_message.as_ref().unwrap()
index abc40607dfc056aae2a9b3ea2e2eee45e2debca0..885b8840b7650d9f4f49f811195cdef09c2822a9 100644 (file)
 //! The provided output descriptors follow a custom LDK data format and are currently not fully
 //! compatible with Bitcoin Core output descriptors.
 
-use bitcoin::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey};
+use bitcoin::amount::Amount;
+use bitcoin::bip32::{ChildNumber, Xpriv, Xpub};
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::script::{Builder, Script, ScriptBuf};
 use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
 use bitcoin::ecdsa::Signature as EcdsaSignature;
-use bitcoin::network::constants::Network;
-use bitcoin::psbt::PartiallySignedTransaction;
+use bitcoin::network::Network;
 use bitcoin::sighash;
 use bitcoin::sighash::EcdsaSighashType;
+use bitcoin::transaction::Version;
 
-use bitcoin::bech32::u5;
-use bitcoin::hash_types::WPubkeyHash;
+use bech32::u5;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::{Hash, HashEngine};
@@ -34,8 +34,8 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
 use bitcoin::secp256k1::schnorr;
 #[cfg(taproot)]
 use bitcoin::secp256k1::All;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
-use bitcoin::{secp256k1, Sequence, Txid, Witness};
+use bitcoin::secp256k1::{Keypair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
+use bitcoin::{secp256k1, Psbt, Sequence, Txid, WPubkeyHash, Witness};
 
 use crate::chain::transaction::OutPoint;
 use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
@@ -63,7 +63,7 @@ use crate::util::transaction_utils;
 use crate::crypto::chacha20::ChaCha20;
 use crate::io::{self, Error};
 use crate::ln::features::ChannelTypeFeatures;
-use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
+use crate::ln::msgs::DecodeError;
 use crate::prelude::*;
 use crate::sign::ecdsa::EcdsaChannelSigner;
 #[cfg(taproot)]
@@ -314,7 +314,7 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
 
 impl SpendableOutputDescriptor {
        /// Turns this into a [`bitcoin::psbt::Input`] which can be used to create a
-       /// [`PartiallySignedTransaction`] which spends the given descriptor.
+       /// [`Psbt`] which spends the given descriptor.
        ///
        /// Note that this does not include any signatures, just the information required to
        /// construct the transaction and sign it.
@@ -327,7 +327,7 @@ impl SpendableOutputDescriptor {
        ///
        /// To get the proprietary field use:
        /// ```
-       /// use bitcoin::psbt::{PartiallySignedTransaction};
+       /// use bitcoin::psbt::{Psbt};
        /// use bitcoin::hashes::hex::FromHex;
        ///
        /// # let s = "70736274ff0100520200000001dee978529ab3e61a2987bea5183713d0e6d5ceb5ac81100fdb54a1a2\
@@ -337,7 +337,7 @@ impl SpendableOutputDescriptor {
        ///     #                d1d4ee2ea3802cd3cfbe2067029000b27521034629b1c8fdebfaeb58a74cd181f485e2c462e594cb30\
        ///     #                34dee655875f69f6c7c968ac20fc144c444b5f7370656e6461626c655f6f7574707574006164645f74\
        ///     #                7765616b20a86534f38ad61dc580ef41c3886204adf0911b81619c1ad7a2f5b5de39a2ba600000";
-       /// # let psbt = PartiallySignedTransaction::deserialize(<Vec<u8> as FromHex>::from_hex(s).unwrap().as_slice()).unwrap();
+       /// # let psbt = Psbt::deserialize(<Vec<u8> as FromHex>::from_hex(s).unwrap().as_slice()).unwrap();
        /// let key = bitcoin::psbt::raw::ProprietaryKey {
        ///     prefix: "LDK_spendable_output".as_bytes().to_vec(),
        ///     subtype: 0,
@@ -423,7 +423,7 @@ impl SpendableOutputDescriptor {
                }
        }
 
-       /// Creates an unsigned [`PartiallySignedTransaction`] which spends the given descriptors to
+       /// Creates an unsigned [`Psbt`] which spends the given descriptors to
        /// the given outputs, plus an output to the given change destination (if sufficient
        /// change value remains). The PSBT will have a feerate, at least, of the given value.
        ///
@@ -443,9 +443,9 @@ impl SpendableOutputDescriptor {
                secp_ctx: &Secp256k1<T>, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
                change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
                locktime: Option<LockTime>,
-       ) -> Result<(PartiallySignedTransaction, u64), ()> {
+       ) -> Result<(Psbt, u64), ()> {
                let mut input = Vec::with_capacity(descriptors.len());
-               let mut input_value = 0;
+               let mut input_value = Amount::ZERO;
                let mut witness_weight = 0;
                let mut output_set = hash_set_with_capacity(descriptors.len());
                for outp in descriptors {
@@ -514,12 +514,12 @@ impl SpendableOutputDescriptor {
                                        input_value += output.value;
                                },
                        }
-                       if input_value > MAX_VALUE_MSAT / 1000 {
+                       if input_value > Amount::MAX_MONEY {
                                return Err(());
                        }
                }
                let mut tx = Transaction {
-                       version: 2,
+                       version: Version::TWO,
                        lock_time: locktime.unwrap_or(LockTime::ZERO),
                        input,
                        output: outputs,
@@ -534,7 +534,7 @@ impl SpendableOutputDescriptor {
 
                let psbt_inputs =
                        descriptors.iter().map(|d| d.to_psbt_input(&secp_ctx)).collect::<Vec<_>>();
-               let psbt = PartiallySignedTransaction {
+               let psbt = Psbt {
                        inputs: psbt_inputs,
                        outputs: vec![Default::default(); tx.output.len()],
                        unsigned_tx: tx,
@@ -620,8 +620,8 @@ impl HTLCDescriptor {
                &self, secp: &Secp256k1<C>,
        ) -> TxOut {
                TxOut {
-                       script_pubkey: self.witness_script(secp).to_v0_p2wsh(),
-                       value: self.htlc.amount_msat / 1000,
+                       script_pubkey: self.witness_script(secp).to_p2wsh(),
+                       value: self.htlc.to_bitcoin_amount(),
                }
        }
 
@@ -1231,7 +1231,7 @@ impl InMemorySigner {
                };
                let sighash = hash_to_message!(
                        &sighash::SighashCache::new(spend_tx)
-                               .segwit_signature_hash(
+                               .p2wsh_signature_hash(
                                        input_idx,
                                        &witness_script,
                                        descriptor.output.value,
@@ -1241,9 +1241,9 @@ impl InMemorySigner {
                );
                let remotesig = sign_with_aux_rand(secp_ctx, &sighash, &self.payment_key, &self);
                let payment_script = if supports_anchors_zero_fee_htlc_tx {
-                       witness_script.to_v0_p2wsh()
+                       witness_script.to_p2wsh()
                } else {
-                       ScriptBuf::new_v0_p2wpkh(&remotepubkey.wpubkey_hash().unwrap())
+                       ScriptBuf::new_p2wpkh(&remotepubkey.wpubkey_hash().unwrap())
                };
 
                if payment_script != descriptor.output.script_pubkey {
@@ -1307,7 +1307,7 @@ impl InMemorySigner {
                );
                let sighash = hash_to_message!(
                        &sighash::SighashCache::new(spend_tx)
-                               .segwit_signature_hash(
+                               .p2wsh_signature_hash(
                                        input_idx,
                                        &witness_script,
                                        descriptor.output.value,
@@ -1436,10 +1436,10 @@ impl EcdsaChannelSigner for InMemorySigner {
                        };
                        let htlc_sighash = hash_to_message!(
                                &sighash::SighashCache::new(&htlc_tx)
-                                       .segwit_signature_hash(
+                                       .p2wsh_signature_hash(
                                                0,
                                                &htlc_redeemscript,
-                                               htlc.amount_msat / 1000,
+                                               htlc.to_bitcoin_amount(),
                                                htlc_sighashtype
                                        )
                                        .unwrap()[..]
@@ -1523,7 +1523,12 @@ impl EcdsaChannelSigner for InMemorySigner {
                let mut sighash_parts = sighash::SighashCache::new(justice_tx);
                let sighash = hash_to_message!(
                        &sighash_parts
-                               .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All)
+                               .p2wsh_signature_hash(
+                                       input,
+                                       &witness_script,
+                                       Amount::from_sat(amount),
+                                       EcdsaSighashType::All
+                               )
                                .unwrap()[..]
                );
                return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self));
@@ -1568,7 +1573,12 @@ impl EcdsaChannelSigner for InMemorySigner {
                let mut sighash_parts = sighash::SighashCache::new(justice_tx);
                let sighash = hash_to_message!(
                        &sighash_parts
-                               .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All)
+                               .p2wsh_signature_hash(
+                                       input,
+                                       &witness_script,
+                                       Amount::from_sat(amount),
+                                       EcdsaSighashType::All
+                               )
                                .unwrap()[..]
                );
                return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self));
@@ -1580,10 +1590,10 @@ impl EcdsaChannelSigner for InMemorySigner {
        ) -> Result<Signature, ()> {
                let witness_script = htlc_descriptor.witness_script(secp_ctx);
                let sighash = &sighash::SighashCache::new(&*htlc_tx)
-                       .segwit_signature_hash(
+                       .p2wsh_signature_hash(
                                input,
                                &witness_script,
-                               htlc_descriptor.htlc.amount_msat / 1000,
+                               htlc_descriptor.htlc.to_bitcoin_amount(),
                                EcdsaSighashType::All,
                        )
                        .map_err(|_| ())?;
@@ -1626,7 +1636,12 @@ impl EcdsaChannelSigner for InMemorySigner {
                let mut sighash_parts = sighash::SighashCache::new(htlc_tx);
                let sighash = hash_to_message!(
                        &sighash_parts
-                               .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All)
+                               .p2wsh_signature_hash(
+                                       input,
+                                       &witness_script,
+                                       Amount::from_sat(amount),
+                                       EcdsaSighashType::All
+                               )
                                .unwrap()[..]
                );
                Ok(sign_with_aux_rand(secp_ctx, &sighash, &htlc_key, &self))
@@ -1654,10 +1669,10 @@ impl EcdsaChannelSigner for InMemorySigner {
                let witness_script =
                        chan_utils::get_anchor_redeemscript(&self.holder_channel_pubkeys.funding_pubkey);
                let sighash = sighash::SighashCache::new(&*anchor_tx)
-                       .segwit_signature_hash(
+                       .p2wsh_signature_hash(
                                input,
                                &witness_script,
-                               ANCHOR_OUTPUT_VALUE_SATOSHI,
+                               Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI),
                                EcdsaSighashType::All,
                        )
                        .unwrap();
@@ -1824,7 +1839,7 @@ pub struct KeysManager {
        inbound_payment_key: KeyMaterial,
        destination_script: ScriptBuf,
        shutdown_pubkey: PublicKey,
-       channel_master_key: ExtendedPrivKey,
+       channel_master_key: Xpriv,
        channel_child_index: AtomicUsize,
 
        entropy_source: RandomBytes,
@@ -1855,21 +1870,19 @@ impl KeysManager {
        pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self {
                let secp_ctx = Secp256k1::new();
                // Note that when we aren't serializing the key, network doesn't matter
-               match ExtendedPrivKey::new_master(Network::Testnet, seed) {
+               match Xpriv::new_master(Network::Testnet, seed) {
                        Ok(master_key) => {
                                let node_secret = master_key
-                                       .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap())
+                                       .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(0).unwrap())
                                        .expect("Your RNG is busted")
                                        .private_key;
                                let node_id = PublicKey::from_secret_key(&secp_ctx, &node_secret);
                                let destination_script = match master_key
-                                       .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap())
+                                       .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(1).unwrap())
                                {
                                        Ok(destination_key) => {
                                                let wpubkey_hash = WPubkeyHash::hash(
-                                                       &ExtendedPubKey::from_priv(&secp_ctx, &destination_key)
-                                                               .to_pub()
-                                                               .to_bytes(),
+                                                       &Xpub::from_priv(&secp_ctx, &destination_key).to_pub().to_bytes(),
                                                );
                                                Builder::new()
                                                        .push_opcode(opcodes::all::OP_PUSHBYTES_0)
@@ -1879,18 +1892,16 @@ impl KeysManager {
                                        Err(_) => panic!("Your RNG is busted"),
                                };
                                let shutdown_pubkey = match master_key
-                                       .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(2).unwrap())
+                                       .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(2).unwrap())
                                {
-                                       Ok(shutdown_key) => {
-                                               ExtendedPubKey::from_priv(&secp_ctx, &shutdown_key).public_key
-                                       },
+                                       Ok(shutdown_key) => Xpub::from_priv(&secp_ctx, &shutdown_key).public_key,
                                        Err(_) => panic!("Your RNG is busted"),
                                };
                                let channel_master_key = master_key
-                                       .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap())
+                                       .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(3).unwrap())
                                        .expect("Your RNG is busted");
                                let inbound_payment_key: SecretKey = master_key
-                                       .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap())
+                                       .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(5).unwrap())
                                        .expect("Your RNG is busted")
                                        .private_key;
                                let mut inbound_pmt_key_bytes = [0; 32];
@@ -1949,9 +1960,9 @@ impl KeysManager {
                // starting_time provided in the constructor) to be unique.
                let child_privkey = self
                        .channel_master_key
-                       .ckd_priv(
+                       .derive_priv(
                                &self.secp_ctx,
-                               ChildNumber::from_hardened_idx((chan_id as u32) % (1 << 31))
+                               &ChildNumber::from_hardened_idx((chan_id as u32) % (1 << 31))
                                        .expect("key space exhausted"),
                        )
                        .expect("Your RNG is busted");
@@ -1996,7 +2007,7 @@ impl KeysManager {
                )
        }
 
-       /// Signs the given [`PartiallySignedTransaction`] which spends the given [`SpendableOutputDescriptor`]s.
+       /// Signs the given [`Psbt`] which spends the given [`SpendableOutputDescriptor`]s.
        /// The resulting inputs will be finalized and the PSBT will be ready for broadcast if there
        /// are no other inputs that need signing.
        ///
@@ -2005,9 +2016,8 @@ impl KeysManager {
        /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
        /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
        pub fn sign_spendable_outputs_psbt<C: Signing>(
-               &self, descriptors: &[&SpendableOutputDescriptor], mut psbt: PartiallySignedTransaction,
-               secp_ctx: &Secp256k1<C>,
-       ) -> Result<PartiallySignedTransaction, ()> {
+               &self, descriptors: &[&SpendableOutputDescriptor], mut psbt: Psbt, secp_ctx: &Secp256k1<C>,
+       ) -> Result<Psbt, ()> {
                let mut keys_cache: Option<(InMemorySigner, [u8; 32])> = None;
                for outp in descriptors {
                        let get_input_idx = |outpoint: &OutPoint| {
@@ -2069,11 +2079,11 @@ impl KeysManager {
                                                if output.script_pubkey == self.destination_script { 1 } else { 2 };
                                        let secret = {
                                                // Note that when we aren't serializing the key, network doesn't matter
-                                               match ExtendedPrivKey::new_master(Network::Testnet, &self.seed) {
+                                               match Xpriv::new_master(Network::Testnet, &self.seed) {
                                                        Ok(master_key) => {
-                                                               match master_key.ckd_priv(
+                                                               match master_key.derive_priv(
                                                                        &secp_ctx,
-                                                                       ChildNumber::from_hardened_idx(derivation_idx)
+                                                                       &ChildNumber::from_hardened_idx(derivation_idx)
                                                                                .expect("key space exhausted"),
                                                                ) {
                                                                        Ok(key) => key,
@@ -2083,7 +2093,7 @@ impl KeysManager {
                                                        Err(_) => panic!("Your rng is busted"),
                                                }
                                        };
-                                       let pubkey = ExtendedPubKey::from_priv(&secp_ctx, &secret).to_pub();
+                                       let pubkey = Xpub::from_priv(&secp_ctx, &secret).to_pub();
                                        if derivation_idx == 2 {
                                                assert_eq!(pubkey.inner, self.shutdown_pubkey);
                                        }
@@ -2099,7 +2109,7 @@ impl KeysManager {
 
                                        let sighash = hash_to_message!(
                                                &sighash::SighashCache::new(&psbt.unsigned_tx)
-                                                       .segwit_signature_hash(
+                                                       .p2wsh_signature_hash(
                                                                input_idx,
                                                                &witness_script,
                                                                output.value,
@@ -2170,7 +2180,7 @@ impl NodeSigner for KeysManager {
                &self, invoice_request: &UnsignedInvoiceRequest,
        ) -> Result<schnorr::Signature, ()> {
                let message = invoice_request.tagged_hash().as_digest();
-               let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret);
+               let keys = Keypair::from_secret_key(&self.secp_ctx, &self.node_secret);
                let aux_rand = self.get_secure_random_bytes();
                Ok(self.secp_ctx.sign_schnorr_with_aux_rand(message, &keys, &aux_rand))
        }
@@ -2179,7 +2189,7 @@ impl NodeSigner for KeysManager {
                &self, invoice: &UnsignedBolt12Invoice,
        ) -> Result<schnorr::Signature, ()> {
                let message = invoice.tagged_hash().as_digest();
-               let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret);
+               let keys = Keypair::from_secret_key(&self.secp_ctx, &self.node_secret);
                let aux_rand = self.get_secure_random_bytes();
                Ok(self.secp_ctx.sign_schnorr_with_aux_rand(message, &keys, &aux_rand))
        }
@@ -2216,7 +2226,7 @@ impl OutputSpender for KeysManager {
                        )?;
                psbt = self.sign_spendable_outputs_psbt(descriptors, psbt, secp_ctx)?;
 
-               let spend_tx = psbt.extract_tx();
+               let spend_tx = psbt.extract_tx_unchecked_fee_rate();
 
                debug_assert!(expected_max_weight >= spend_tx.weight().to_wu());
                // Note that witnesses with a signature vary somewhat in size, so allow
diff --git a/lightning/src/util/async_poll.rs b/lightning/src/util/async_poll.rs
new file mode 100644 (file)
index 0000000..7a368af
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+//! Some utilities to make working with the standard library's [`Future`]s easier
+
+use crate::prelude::*;
+use core::future::Future;
+use core::marker::Unpin;
+use core::pin::Pin;
+use core::task::{Context, Poll};
+
+pub(crate) struct MultiFuturePoller<F: Future<Output = ()> + Unpin>(pub Vec<Option<F>>);
+
+impl<F: Future<Output = ()> + Unpin> Future for MultiFuturePoller<F> {
+       type Output = ();
+       fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+               let mut have_pending_futures = false;
+               for fut_option in self.get_mut().0.iter_mut() {
+                       let mut fut = match fut_option.take() {
+                               None => continue,
+                               Some(fut) => fut,
+                       };
+                       match Pin::new(&mut fut).poll(cx) {
+                               Poll::Ready(()) => {},
+                               Poll::Pending => {
+                                       have_pending_futures = true;
+                                       *fut_option = Some(fut);
+                               },
+                       }
+               }
+               if have_pending_futures {
+                       Poll::Pending
+               } else {
+                       Poll::Ready(())
+               }
+       }
+}
index afe9c402c713981a5860002655aa101442fad37e..dec3d8f6590ac44eef0e1b2754e9c88191c4f0e0 100644 (file)
@@ -12,13 +12,13 @@ macro_rules! hash_to_message {
                {
                        #[cfg(not(fuzzing))]
                        {
-                               ::bitcoin::secp256k1::Message::from_slice($slice).unwrap()
+                               ::bitcoin::secp256k1::Message::from_digest_slice($slice).unwrap()
                        }
                        #[cfg(fuzzing)]
                        {
-                               match ::bitcoin::secp256k1::Message::from_slice($slice) {
+                               match ::bitcoin::secp256k1::Message::from_digest_slice($slice) {
                                        Ok(msg) => msg,
-                                       Err(_) => ::bitcoin::secp256k1::Message::from_slice(&[1; 32]).unwrap()
+                                       Err(_) => ::bitcoin::secp256k1::Message::from_digest([1; 32])
                                }
                        }
                }
index b6cf452ffc955935a55a3e4cb801c649fb10d915..4a4baa45267673b3abddac845918c52a64a2dcde 100644 (file)
@@ -1,6 +1,6 @@
 //! Low level invoice utilities.
 
-use bitcoin::bech32::{u5, FromBase32};
+use bech32::{u5, FromBase32};
 
 #[allow(unused)]
 use crate::prelude::*;
index 79572f31246a7ae53fa1885b13ee3cc282c68d50..0a45af26f8633e27fa97ad783f2a7e32079bd94f 100644 (file)
@@ -54,12 +54,12 @@ fn sigrec_decode(sig_rec: Vec<u8>) -> Result<RecoverableSignature, Error> {
 /// Creates a digital signature of a message given a SecretKey, like the node's secret.
 /// A receiver knowing the PublicKey (e.g. the node's id) and the message can be sure that the signature was generated by the caller.
 /// Signatures are EC recoverable, meaning that given the message and the signature the PublicKey of the signer can be extracted.
-pub fn sign(msg: &[u8], sk: &SecretKey) -> Result<String, Error> {
+pub fn sign(msg: &[u8], sk: &SecretKey) -> String {
        let secp_ctx = Secp256k1::signing_only();
        let msg_hash = sha256d::Hash::hash(&[LN_MESSAGE_PREFIX, msg].concat());
 
-       let sig = secp_ctx.sign_ecdsa_recoverable(&Message::from_slice(msg_hash.as_byte_array())?, sk);
-       Ok(base32::Alphabet::ZBase32.encode(&sigrec_encode(sig)))
+       let sig = secp_ctx.sign_ecdsa_recoverable(&Message::from_digest(msg_hash.to_byte_array()), sk);
+       base32::Alphabet::ZBase32.encode(&sigrec_encode(sig))
 }
 
 /// Recovers the PublicKey of the signer of the message given the message and the signature.
@@ -70,7 +70,7 @@ pub fn recover_pk(msg: &[u8], sig: &str) ->  Result<PublicKey, Error> {
        match base32::Alphabet::ZBase32.decode(&sig) {
                Ok(sig_rec) => {
                        match sigrec_decode(sig_rec) {
-                               Ok(sig) => secp_ctx.recover_ecdsa(&Message::from_slice(msg_hash.as_byte_array())?, &sig),
+                               Ok(sig) => secp_ctx.recover_ecdsa(&Message::from_digest(msg_hash.to_byte_array()), &sig),
                                Err(e) => Err(e)
                        }
                },
@@ -100,7 +100,7 @@ mod test {
                let one_key = SecretKey::from_slice(&ONE).unwrap();
                let zbase32_sig = sign(message.as_bytes(), &one_key);
 
-               assert_eq!(zbase32_sig.unwrap(), "d9tibmnic9t5y41hg7hkakdcra94akas9ku3rmmj4ag9mritc8ok4p5qzefs78c9pqfhpuftqqzhydbdwfg7u6w6wdxcqpqn4sj4e73e")
+               assert_eq!(zbase32_sig, "d9tibmnic9t5y41hg7hkakdcra94akas9ku3rmmj4ag9mritc8ok4p5qzefs78c9pqfhpuftqqzhydbdwfg7u6w6wdxcqpqn4sj4e73e")
        }
 
        #[test]
@@ -117,7 +117,7 @@ mod test {
        fn test_verify() {
                let message = "another message";
                let one_key = SecretKey::from_slice(&ONE).unwrap();
-               let sig = sign(message.as_bytes(), &one_key).unwrap();
+               let sig = sign(message.as_bytes(), &one_key);
                let pk = PublicKey::from_secret_key(&Secp256k1::signing_only(), &one_key);
 
                assert!(verify(message.as_bytes(), &sig, &pk))
index c1ab8c75c2ee70efb51e7bb214ee76a8d06bef03..a81a36c5583b713bc491f6556e57999ce681af5e 100644 (file)
@@ -30,6 +30,7 @@ pub mod base32;
 pub(crate) mod base32;
 
 pub(crate) mod atomic_counter;
+pub(crate) mod async_poll;
 pub(crate) mod byte_utils;
 pub(crate) mod transaction_utils;
 pub(crate) mod time;
index d03474b292ade70f28993eee63c8521e42b2f443..95c68b589fa2c0d3e5694236d1889e99e709d330 100644 (file)
@@ -1072,7 +1072,9 @@ mod tests {
 
                // Force close because cooperative close doesn't result in any persisted
                // updates.
-               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+
+               let error_message = "Channel force-closed";
+               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
 
                check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
                check_closed_broadcast!(nodes[0], true);
@@ -1110,7 +1112,8 @@ mod tests {
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000);
                {
                        let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
@@ -1226,7 +1229,8 @@ mod tests {
                        .is_err());
 
                // Force close.
-               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+               let error_message = "Channel force-closed";
+               nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
                check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
                check_closed_broadcast!(nodes[0], true);
                check_added_monitors!(nodes[0], 1);
index c9485b60b70be78fd88b52eb45703c74f4da5af1..ce789ef9fdc6fd7eb2b23f04f7c66ff379238ac5 100644 (file)
@@ -72,7 +72,7 @@ pub fn scid_from_parts(block: u64, tx_index: u64, vout_index: u64) -> Result<u64
 ///    the forwarding node can open a JIT channel to the next hop)
 pub(crate) mod fake_scid {
        use bitcoin::blockdata::constants::ChainHash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::Network;
        use crate::sign::EntropySource;
        use crate::crypto::chacha20::ChaCha20;
        use crate::util::scid_utils;
@@ -183,7 +183,7 @@ pub(crate) mod fake_scid {
        #[cfg(test)]
        mod tests {
                use bitcoin::blockdata::constants::ChainHash;
-               use bitcoin::network::constants::Network;
+               use bitcoin::network::Network;
                use crate::util::scid_utils::fake_scid::{is_valid_intercept, is_valid_phantom, MAINNET_SEGWIT_ACTIVATION_HEIGHT, MAX_TX_INDEX, MAX_NAMESPACES, Namespace, NAMESPACE_ID_BITMASK, segwit_activation_height, TEST_SEGWIT_ACTIVATION_HEIGHT};
                use crate::util::scid_utils;
                use crate::util::test_utils;
index 5e7c6f8565946a938d198fd412583c07922372da..5f109e1a93c64529d09e462899fb539abf662c68 100644 (file)
@@ -27,6 +27,7 @@ use bitcoin::secp256k1::{PublicKey, SecretKey};
 use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE, SCHNORR_SIGNATURE_SIZE};
 use bitcoin::secp256k1::ecdsa;
 use bitcoin::secp256k1::schnorr;
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::script::{self, ScriptBuf};
 use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
@@ -900,7 +901,7 @@ impl Writeable for Vec<Witness> {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                (self.len() as u16).write(w)?;
                for witness in self {
-                       (witness.serialized_len() as u16).write(w)?;
+                       (witness.size() as u16).write(w)?;
                        witness.write(w)?;
                }
                Ok(())
@@ -920,7 +921,7 @@ impl Readable for Vec<Witness> {
                        // of witnesses. We'll just do a sanity check for the lengths and error if there is a mismatch.
                        let witness_len = <u16 as Readable>::read(r)? as usize;
                        let witness = <Witness as Readable>::read(r)?;
-                       if witness.serialized_len() != witness_len {
+                       if witness.size() != witness_len {
                                return Err(DecodeError::BadLengthDescriptor);
                        }
                        witnesses.push(witness);
@@ -1145,6 +1146,20 @@ impl<T: Readable> Readable for Option<T>
        }
 }
 
+impl Writeable for Amount {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.to_sat().write(w)
+       }
+}
+
+
+impl Readable for Amount {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let amount: u64 = Readable::read(r)?;
+               Ok(Amount::from_sat(amount))
+       }
+}
+
 impl Writeable for Txid {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                w.write_all(&self[..])
index 0ad1d95bd0671bf3b7dcceb358d166298283c037..2009e4d0b08a9a22fd68941b8290bfabffe75203 100644 (file)
@@ -250,8 +250,8 @@ impl EcdsaChannelSigner for TestChannelSigner {
                        } else {
                                EcdsaSighashType::All
                        };
-                       let sighash = &sighash::SighashCache::new(&*htlc_tx).segwit_signature_hash(
-                               input, &witness_script, htlc_descriptor.htlc.amount_msat / 1000, sighash_type
+                       let sighash = &sighash::SighashCache::new(&*htlc_tx).p2wsh_signature_hash(
+                               input, &witness_script, htlc_descriptor.htlc.to_bitcoin_amount(), sighash_type
                        ).unwrap();
                        let countersignatory_htlc_key = HtlcKey::from_basepoint(
                                &secp_ctx, &self.inner.counterparty_pubkeys().unwrap().htlc_basepoint, &htlc_descriptor.per_commitment_point,
index 92d43193e305def0ee3624613770117322d5eb43..f6616a8e5d2449391c2beb68d08e93c295127cee 100644 (file)
@@ -25,7 +25,8 @@ use crate::sign;
 use crate::events;
 use crate::events::bump_transaction::{WalletSource, Utxo};
 use crate::ln::types::ChannelId;
-use crate::ln::channelmanager::{ChannelDetails, self};
+use crate::ln::channel_state::ChannelDetails;
+use crate::ln::channelmanager;
 #[cfg(test)]
 use crate::ln::chan_utils::CommitmentTransaction;
 use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
@@ -46,14 +47,16 @@ use crate::util::logger::{Logger, Level, Record};
 use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
 use crate::util::persist::KVStore;
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::{Builder, Script, ScriptBuf};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::block::Block;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
 use bitcoin::hash_types::{BlockHash, Txid};
+use bitcoin::hashes::Hash;
 use bitcoin::sighash::{SighashCache, EcdsaSighashType};
 
 use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self};
@@ -68,12 +71,12 @@ use core::time::Duration;
 use crate::sync::{Mutex, Arc};
 use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use core::mem;
-use bitcoin::bech32::u5;
+use bech32::u5;
 use crate::sign::{InMemorySigner, RandomBytes, Recipient, EntropySource, NodeSigner, SignerProvider};
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
-use bitcoin::psbt::PartiallySignedTransaction;
+use bitcoin::psbt::Psbt;
 use bitcoin::Sequence;
 
 pub fn pubkey(byte: u8) -> PublicKey {
@@ -247,10 +250,18 @@ impl<'a> MessageRouter for TestRouter<'a> {
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                self.router.create_blinded_paths(recipient, peers, secp_ctx)
        }
+
+       fn create_compact_blinded_paths<
+               T: secp256k1::Signing + secp256k1::Verification
+       >(
+               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               self.router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+       }
 }
 
 impl<'a> Drop for TestRouter<'a> {
@@ -282,10 +293,16 @@ impl<'a> MessageRouter for TestMessageRouter<'a> {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                self.inner.create_blinded_paths(recipient, peers, secp_ctx)
        }
+
+       fn create_compact_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
+               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<BlindedPath>, ()> {
+               self.inner.create_compact_blinded_paths(recipient, peers, secp_ctx)
+       }
 }
 
 pub struct OnlyReadsKeysInterface {}
@@ -410,7 +427,7 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
 #[cfg(test)]
 struct JusticeTxData {
        justice_tx: Transaction,
-       value: u64,
+       value: Amount,
        commitment_number: u64,
 }
 
@@ -499,7 +516,7 @@ impl<Signer: sign::ecdsa::EcdsaChannelSigner> chainmonitor::Persist<Signer> for
                        while let Some(JusticeTxData { justice_tx, value, commitment_number }) = channel_state.front() {
                                let input_idx = 0;
                                let commitment_txid = justice_tx.input[input_idx].previous_output.txid;
-                               match data.sign_to_local_justice_tx(justice_tx.clone(), input_idx, *value, *commitment_number) {
+                               match data.sign_to_local_justice_tx(justice_tx.clone(), input_idx, value.to_sat(), *commitment_number) {
                                        Ok(signed_justice_tx) => {
                                                let dup = self.watchtower_state.lock().unwrap()
                                                        .get_mut(&funding_txo).unwrap()
@@ -1170,7 +1187,7 @@ impl NodeSigner for TestNodeSigner {
                Ok(SharedSecret::new(other_key, &node_secret))
        }
 
-       fn sign_invoice(&self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
+       fn sign_invoice(&self, _: &[u8], _: &[bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
                unreachable!()
        }
 
@@ -1374,7 +1391,7 @@ impl TestChainSource {
                let script_pubkey = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
                Self {
                        chain_hash: ChainHash::using_genesis_block(network),
-                       utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: u64::max_value(), script_pubkey }))),
+                       utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: Amount::MAX, script_pubkey }))),
                        get_utxo_call_count: AtomicUsize::new(0),
                        watched_txn: Mutex::new(new_hash_set()),
                        watched_outputs: Mutex::new(new_hash_set()),
@@ -1505,7 +1522,7 @@ impl TestWalletSource {
                }
        }
 
-       pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: u64) -> TxOut {
+       pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: Amount) -> TxOut {
                let public_key = bitcoin::PublicKey::new(self.secret_key.public_key(&self.secp));
                let utxo = Utxo::new_p2pkh(outpoint, value, &public_key.pubkey_hash());
                self.utxos.borrow_mut().push(utxo.clone());
@@ -1533,15 +1550,15 @@ impl WalletSource for TestWalletSource {
                Ok(ScriptBuf::new_p2pkh(&public_key.pubkey_hash()))
        }
 
-       fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result<Transaction, ()> {
-               let mut tx = psbt.extract_tx();
+       fn sign_psbt(&self, psbt: Psbt) -> Result<Transaction, ()> {
+               let mut tx = psbt.extract_tx_unchecked_fee_rate();
                let utxos = self.utxos.borrow();
                for i in 0..tx.input.len() {
                        if let Some(utxo) = utxos.iter().find(|utxo| utxo.outpoint == tx.input[i].previous_output) {
                                let sighash = SighashCache::new(&tx)
                                        .legacy_signature_hash(i, &utxo.output.script_pubkey, EcdsaSighashType::All as u32)
                                        .map_err(|_| ())?;
-                               let sig = self.secp.sign_ecdsa(&(*sighash.as_raw_hash()).into(), &self.secret_key);
+                               let sig = self.secp.sign_ecdsa(&secp256k1::Message::from_digest(sighash.to_byte_array()), &self.secret_key);
                                let bitcoin_sig = bitcoin::ecdsa::Signature { sig, hash_ty: EcdsaSighashType::All };
                                tx.input[i].script_sig = Builder::new()
                                        .push_slice(&bitcoin_sig.serialize())
index 59b7be6073c1dd9a1516adb25f3a41af1d0222f5..5eb7ba3b94966a16ef9d927f6dcb6d117035b936 100644 (file)
@@ -7,13 +7,12 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::ScriptBuf;
 use bitcoin::consensus::Encodable;
 use bitcoin::consensus::encode::VarInt;
 
-use crate::ln::msgs::MAX_VALUE_MSAT;
-
 #[allow(unused_imports)]
 use crate::prelude::*;
 
@@ -35,12 +34,12 @@ pub fn sort_outputs<T, C : Fn(&T, &T) -> Ordering>(outputs: &mut Vec<(TxOut, T)>
 /// Assumes at least one input will have a witness (ie spends a segwit output).
 /// Returns an Err(()) if the requested feerate cannot be met.
 /// Returns the expected maximum weight of the fully signed transaction on success.
-pub(crate) fn maybe_add_change_output(tx: &mut Transaction, input_value: u64, witness_max_weight: u64, feerate_sat_per_1000_weight: u32, change_destination_script: ScriptBuf) -> Result<u64, ()> {
-       if input_value > MAX_VALUE_MSAT / 1000 { return Err(()); }
+pub(crate) fn maybe_add_change_output(tx: &mut Transaction, input_value: Amount, witness_max_weight: u64, feerate_sat_per_1000_weight: u32, change_destination_script: ScriptBuf) -> Result<u64, ()> {
+       if input_value > Amount::MAX_MONEY { return Err(()); }
 
        const WITNESS_FLAG_BYTES: u64 = 2;
 
-       let mut output_value = 0;
+       let mut output_value = Amount::ZERO;
        for output in tx.output.iter() {
                output_value += output.value;
                if output_value >= input_value { return Err(()); }
@@ -49,20 +48,20 @@ pub(crate) fn maybe_add_change_output(tx: &mut Transaction, input_value: u64, wi
        let dust_value = change_destination_script.dust_value();
        let mut change_output = TxOut {
                script_pubkey: change_destination_script,
-               value: 0,
+               value: Amount::ZERO,
        };
        let change_len = change_output.consensus_encode(&mut sink()).unwrap();
        let starting_weight = tx.weight().to_wu() + WITNESS_FLAG_BYTES + witness_max_weight as u64;
        let mut weight_with_change: i64 = starting_weight as i64 + change_len as i64 * 4;
        // Include any extra bytes required to push an extra output.
-       weight_with_change += (VarInt(tx.output.len() as u64 + 1).len() - VarInt(tx.output.len() as u64).len()) as i64 * 4;
+       weight_with_change += (VarInt(tx.output.len() as u64 + 1).size() - VarInt(tx.output.len() as u64).size()) as i64 * 4;
        // When calculating weight, add two for the flag bytes
-       let change_value: i64 = (input_value - output_value) as i64 - weight_with_change * feerate_sat_per_1000_weight as i64 / 1000;
+       let change_value: i64 = (input_value - output_value).to_sat() as i64 - weight_with_change * feerate_sat_per_1000_weight as i64 / 1000;
        if change_value >= dust_value.to_sat() as i64 {
-               change_output.value = change_value as u64;
+               change_output.value = Amount::from_sat(change_value as u64);
                tx.output.push(change_output);
                Ok(weight_with_change as u64)
-       } else if (input_value - output_value) as i64 - (starting_weight as i64) * feerate_sat_per_1000_weight as i64 / 1000 < 0 {
+       } else if (input_value - output_value).to_sat() as i64 - (starting_weight as i64) * feerate_sat_per_1000_weight as i64 / 1000 < 0 {
                Err(())
        } else {
                Ok(starting_weight)
@@ -73,26 +72,27 @@ pub(crate) fn maybe_add_change_output(tx: &mut Transaction, input_value: u64, wi
 mod tests {
        use super::*;
 
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::locktime::absolute::LockTime;
-       use bitcoin::blockdata::transaction::{TxIn, OutPoint};
+       use bitcoin::blockdata::transaction::{TxIn, OutPoint, Version};
        use bitcoin::blockdata::script::Builder;
-       use bitcoin::hash_types::{PubkeyHash, Txid};
+       use bitcoin::hash_types::Txid;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::hex::FromHex;
-       use bitcoin::{Sequence, Witness};
+       use bitcoin::{PubkeyHash, Sequence, Witness};
 
        use alloc::vec;
 
        #[test]
        fn sort_output_by_value() {
                let txout1 = TxOut {
-                       value:  100,
+                       value:  Amount::from_sat(100),
                        script_pubkey: Builder::new().push_int(0).into_script()
                };
                let txout1_ = txout1.clone();
 
                let txout2 = TxOut {
-                       value: 99,
+                       value: Amount::from_sat(99),
                        script_pubkey: Builder::new().push_int(0).into_script()
                };
                let txout2_ = txout2.clone();
@@ -109,13 +109,13 @@ mod tests {
        #[test]
        fn sort_output_by_script_pubkey() {
                let txout1 = TxOut {
-                       value:  100,
+                       value:  Amount::from_sat(100),
                        script_pubkey: Builder::new().push_int(3).into_script(),
                };
                let txout1_ = txout1.clone();
 
                let txout2 = TxOut {
-                       value: 100,
+                       value: Amount::from_sat(100),
                        script_pubkey: Builder::new().push_int(1).push_int(2).into_script()
                };
                let txout2_ = txout2.clone();
@@ -132,14 +132,14 @@ mod tests {
        #[test]
        fn sort_output_by_bip_test() {
                let txout1 = TxOut {
-                       value: 100000000,
+                       value: Amount::from_sat(100000000),
                        script_pubkey: script_from_hex("41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac")
                };
                let txout1_ = txout1.clone();
 
                // doesn't deserialize cleanly:
                let txout2 = TxOut {
-                       value: 2400000000,
+                       value: Amount::from_sat(2400000000),
                        script_pubkey: script_from_hex("41044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac")
                };
                let txout2_ = txout2.clone();
@@ -153,7 +153,7 @@ mod tests {
        #[test]
        fn sort_output_tie_breaker_test() {
                let txout1 = TxOut {
-                       value:  100,
+                       value:  Amount::from_sat(100),
                        script_pubkey: Builder::new().push_int(1).push_int(2).into_script()
                };
                let txout1_ = txout1.clone();
@@ -182,7 +182,7 @@ mod tests {
                                        let expected_raw: Vec<(u64, &str)> = $value;
                                        let expected: Vec<(TxOut, &str)> = expected_raw.iter()
                                                .map(|txout_raw| TxOut {
-                                                       value: txout_raw.0,
+                                                       value: Amount::from_sat(txout_raw.0),
                                                        script_pubkey: script_from_hex(txout_raw.1)
                                                }).map(|txout| (txout, "ignore"))
                                        .collect();
@@ -215,41 +215,43 @@ mod tests {
        #[test]
        fn test_tx_value_overrun() {
                // If we have a bogus input amount or outputs valued more than inputs, we should fail
-               let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       script_pubkey: ScriptBuf::new(), value: 1000
+               let mut tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       script_pubkey: ScriptBuf::new(), value: Amount::from_sat(1000)
                }] };
-               assert!(maybe_add_change_output(&mut tx, 21_000_000_0000_0001, 0, 253, ScriptBuf::new()).is_err());
-               assert!(maybe_add_change_output(&mut tx, 400, 0, 253, ScriptBuf::new()).is_err());
-               assert!(maybe_add_change_output(&mut tx, 4000, 0, 253, ScriptBuf::new()).is_ok());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(21_000_000_0000_0001), 0, 253, ScriptBuf::new()).is_err());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(400), 0, 253, ScriptBuf::new()).is_err());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(4000), 0, 253, ScriptBuf::new()).is_ok());
        }
 
        #[test]
        fn test_tx_change_edge() {
                // Check that we never add dust outputs
-               let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+               let mut tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                let orig_wtxid = tx.wtxid();
                let output_spk = ScriptBuf::new_p2pkh(&PubkeyHash::hash(&[0; 0]));
                assert_eq!(output_spk.dust_value().to_sat(), 546);
-               // 9 sats isn't enough to pay fee on a dummy transaction...
-               assert_eq!(tx.weight().to_wu(), 40); // ie 10 vbytes
-               assert!(maybe_add_change_output(&mut tx, 9, 0, 250, output_spk.clone()).is_err());
+               // base size = version size + varint[input count] + input size + varint[output count] + output size + lock time size
+               // total size = version size + marker + flag + varint[input count] + input size + varint[output count] + output size + lock time size
+               // weight = 3 * base size + total size = 3 * (4 + 1 + 0 + 1 + 0 + 4) + (4 + 1 + 1 + 1 + 0 + 1 + 0 + 4) = 3 * 10 + 12 = 42
+               assert_eq!(tx.weight().to_wu(), 42);
+               // 10 sats isn't enough to pay fee on a dummy transaction...
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(10), 0, 250, output_spk.clone()).is_err());
                assert_eq!(tx.wtxid(), orig_wtxid); // Failure doesn't change the transaction
-               // but 10-564 is, just not enough to add a change output...
-               assert!(maybe_add_change_output(&mut tx, 10, 0, 250, output_spk.clone()).is_ok());
+               // but 11 (= ceil(42 * 250 / 1000)) is, just not enough to add a change output...
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(11), 0, 250, output_spk.clone()).is_ok());
                assert_eq!(tx.output.len(), 0);
                assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction
-               assert!(maybe_add_change_output(&mut tx, 549, 0, 250, output_spk.clone()).is_ok());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(549), 0, 250, output_spk.clone()).is_ok());
                assert_eq!(tx.output.len(), 0);
                assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction
-               // 590 is also not enough, if we anticipate 2 more weight units pushing us up to the next vbyte
-               // (considering the two bytes for segwit flags)
-               assert!(maybe_add_change_output(&mut tx, 590, 2, 250, output_spk.clone()).is_ok());
+               // 590 is also not enough
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(590), 0, 250, output_spk.clone()).is_ok());
                assert_eq!(tx.output.len(), 0);
                assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction
-               // at 590 we can afford the change output at the dust limit (546)
-               assert!(maybe_add_change_output(&mut tx, 590, 0, 250, output_spk.clone()).is_ok());
+               // at 591 we can afford the change output at the dust limit (546)
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(591), 0, 250, output_spk.clone()).is_ok());
                assert_eq!(tx.output.len(), 1);
-               assert_eq!(tx.output[0].value, 546);
+               assert_eq!(tx.output[0].value.to_sat(), 546);
                assert_eq!(tx.output[0].script_pubkey, output_spk);
                assert_eq!(tx.weight().to_wu() / 4, 590-546); // New weight is exactly the fee we wanted.
 
@@ -260,10 +262,10 @@ mod tests {
        #[test]
        fn test_tx_extra_outputs() {
                // Check that we correctly handle existing outputs
-               let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: vec![TxIn {
+               let mut tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn {
                        previous_output: OutPoint::new(Txid::all_zeros(), 0), script_sig: ScriptBuf::new(), witness: Witness::new(), sequence: Sequence::ZERO,
                }], output: vec![TxOut {
-                       script_pubkey: Builder::new().push_int(1).into_script(), value: 1000
+                       script_pubkey: Builder::new().push_int(1).into_script(), value: Amount::from_sat(1000)
                }] };
                let orig_wtxid = tx.wtxid();
                let orig_weight = tx.weight().to_wu();
@@ -272,18 +274,18 @@ mod tests {
                assert_eq!(Builder::new().push_int(2).into_script().dust_value().to_sat(), 474);
 
                // Input value of the output value + fee - 1 should fail:
-               assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 - 1, 400, 250, Builder::new().push_int(2).into_script()).is_err());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(1000 + 61 + 100 - 1), 400, 250, Builder::new().push_int(2).into_script()).is_err());
                assert_eq!(tx.wtxid(), orig_wtxid); // Failure doesn't change the transaction
                // but one more input sat should succeed, without changing the transaction
-               assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100, 400, 250, Builder::new().push_int(2).into_script()).is_ok());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(1000 + 61 + 100), 400, 250, Builder::new().push_int(2).into_script()).is_ok());
                assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction
                // In order to get a change output, we need to add 474 plus the output's weight / 4 (10)...
-               assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 + 474 + 9, 400, 250, Builder::new().push_int(2).into_script()).is_ok());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(1000 + 61 + 100 + 474 + 9), 400, 250, Builder::new().push_int(2).into_script()).is_ok());
                assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction
 
-               assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 + 474 + 10, 400, 250, Builder::new().push_int(2).into_script()).is_ok());
+               assert!(maybe_add_change_output(&mut tx, Amount::from_sat(1000 + 61 + 100 + 474 + 10), 400, 250, Builder::new().push_int(2).into_script()).is_ok());
                assert_eq!(tx.output.len(), 2);
-               assert_eq!(tx.output[1].value, 474);
+               assert_eq!(tx.output[1].value.to_sat(), 474);
                assert_eq!(tx.output[1].script_pubkey, Builder::new().push_int(2).into_script());
                assert_eq!(tx.weight().to_wu() - orig_weight, 40); // Weight difference matches what we had to add above
                tx.output.pop();
index 36d85ef2061b4056d24c268ec3d1157cc9f5a574..d4317eb0e89e269b1737acc37ecb2d7de5a8b1f4 100644 (file)
@@ -1,136 +1,7 @@
 ./bench/benches/bench.rs
-./fuzz/src/base32.rs
-./fuzz/src/bech32_parse.rs
-./fuzz/src/bin/base32_target.rs
-./fuzz/src/bin/bech32_parse_target.rs
-./fuzz/src/bin/bolt11_deser_target.rs
-./fuzz/src/bin/chanmon_consistency_target.rs
-./fuzz/src/bin/chanmon_deser_target.rs
-./fuzz/src/bin/fromstr_to_netaddress_target.rs
-./fuzz/src/bin/full_stack_target.rs
-./fuzz/src/bin/indexedmap_target.rs
-./fuzz/src/bin/invoice_deser_target.rs
-./fuzz/src/bin/invoice_request_deser_target.rs
-./fuzz/src/bin/msg_accept_channel_target.rs
-./fuzz/src/bin/msg_accept_channel_v2_target.rs
-./fuzz/src/bin/msg_announcement_signatures_target.rs
-./fuzz/src/bin/msg_channel_announcement_target.rs
-./fuzz/src/bin/msg_channel_details_target.rs
-./fuzz/src/bin/msg_channel_ready_target.rs
-./fuzz/src/bin/msg_channel_reestablish_target.rs
-./fuzz/src/bin/msg_channel_update_target.rs
-./fuzz/src/bin/msg_closing_signed_target.rs
-./fuzz/src/bin/msg_commitment_signed_target.rs
-./fuzz/src/bin/msg_decoded_onion_error_packet_target.rs
-./fuzz/src/bin/msg_error_message_target.rs
-./fuzz/src/bin/msg_funding_created_target.rs
-./fuzz/src/bin/msg_funding_signed_target.rs
-./fuzz/src/bin/msg_gossip_timestamp_filter_target.rs
-./fuzz/src/bin/msg_init_target.rs
-./fuzz/src/bin/msg_node_announcement_target.rs
-./fuzz/src/bin/msg_open_channel_target.rs
-./fuzz/src/bin/msg_open_channel_v2_target.rs
-./fuzz/src/bin/msg_ping_target.rs
-./fuzz/src/bin/msg_pong_target.rs
-./fuzz/src/bin/msg_query_channel_range_target.rs
-./fuzz/src/bin/msg_query_short_channel_ids_target.rs
-./fuzz/src/bin/msg_reply_channel_range_target.rs
-./fuzz/src/bin/msg_reply_short_channel_ids_end_target.rs
-./fuzz/src/bin/msg_revoke_and_ack_target.rs
-./fuzz/src/bin/msg_shutdown_target.rs
-./fuzz/src/bin/msg_splice_ack_target.rs
-./fuzz/src/bin/msg_splice_locked_target.rs
-./fuzz/src/bin/msg_splice_target.rs
-./fuzz/src/bin/msg_stfu_target.rs
-./fuzz/src/bin/msg_tx_abort_target.rs
-./fuzz/src/bin/msg_tx_ack_rbf_target.rs
-./fuzz/src/bin/msg_tx_add_input_target.rs
-./fuzz/src/bin/msg_tx_add_output_target.rs
-./fuzz/src/bin/msg_tx_complete_target.rs
-./fuzz/src/bin/msg_tx_init_rbf_target.rs
-./fuzz/src/bin/msg_tx_remove_input_target.rs
-./fuzz/src/bin/msg_tx_remove_output_target.rs
-./fuzz/src/bin/msg_tx_signatures_target.rs
-./fuzz/src/bin/msg_update_add_htlc_target.rs
-./fuzz/src/bin/msg_update_fail_htlc_target.rs
-./fuzz/src/bin/msg_update_fail_malformed_htlc_target.rs
-./fuzz/src/bin/msg_update_fee_target.rs
-./fuzz/src/bin/msg_update_fulfill_htlc_target.rs
-./fuzz/src/bin/offer_deser_target.rs
-./fuzz/src/bin/onion_hop_data_target.rs
-./fuzz/src/bin/onion_message_target.rs
-./fuzz/src/bin/peer_crypt_target.rs
-./fuzz/src/bin/process_network_graph_target.rs
-./fuzz/src/bin/refund_deser_target.rs
-./fuzz/src/bin/router_target.rs
-./fuzz/src/bin/zbase32_target.rs
 ./fuzz/src/chanmon_consistency.rs
-./fuzz/src/chanmon_deser.rs
-./fuzz/src/fromstr_to_netaddress.rs
 ./fuzz/src/full_stack.rs
-./fuzz/src/indexedmap.rs
-./fuzz/src/invoice_deser.rs
-./fuzz/src/invoice_request_deser.rs
 ./fuzz/src/lib.rs
-./fuzz/src/msg_targets/mod.rs
-./fuzz/src/msg_targets/msg_accept_channel.rs
-./fuzz/src/msg_targets/msg_accept_channel_v2.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
-./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_open_channel.rs
-./fuzz/src/msg_targets/msg_open_channel_v2.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_splice.rs
-./fuzz/src/msg_targets/msg_splice_ack.rs
-./fuzz/src/msg_targets/msg_splice_locked.rs
-./fuzz/src/msg_targets/msg_stfu.rs
-./fuzz/src/msg_targets/msg_tx_abort.rs
-./fuzz/src/msg_targets/msg_tx_ack_rbf.rs
-./fuzz/src/msg_targets/msg_tx_add_input.rs
-./fuzz/src/msg_targets/msg_tx_add_output.rs
-./fuzz/src/msg_targets/msg_tx_complete.rs
-./fuzz/src/msg_targets/msg_tx_init_rbf.rs
-./fuzz/src/msg_targets/msg_tx_remove_input.rs
-./fuzz/src/msg_targets/msg_tx_remove_output.rs
-./fuzz/src/msg_targets/msg_tx_signatures.rs
-./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/msg_targets/utils.rs
-./fuzz/src/offer_deser.rs
-./fuzz/src/onion_hop_data.rs
-./fuzz/src/onion_message.rs
-./fuzz/src/peer_crypt.rs
-./fuzz/src/process_network_graph.rs
-./fuzz/src/refund_deser.rs
-./fuzz/src/router.rs
-./fuzz/src/utils/mod.rs
-./fuzz/src/utils/test_logger.rs
-./fuzz/src/utils/test_persister.rs
-./fuzz/src/zbase32.rs
 ./lightning-background-processor/src/lib.rs
 ./lightning-block-sync/src/convert.rs
 ./lightning-block-sync/src/gossip.rs
 ./lightning-rapid-gossip-sync/src/error.rs
 ./lightning-rapid-gossip-sync/src/lib.rs
 ./lightning-rapid-gossip-sync/src/processing.rs
-./lightning-transaction-sync/src/common.rs
-./lightning-transaction-sync/src/electrum.rs
-./lightning-transaction-sync/src/error.rs
-./lightning-transaction-sync/src/esplora.rs
-./lightning-transaction-sync/src/lib.rs
-./lightning-transaction-sync/tests/integration_tests.rs
 ./lightning/src/blinded_path/message.rs
 ./lightning/src/blinded_path/mod.rs
 ./lightning/src/blinded_path/payment.rs