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 ..
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":
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
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 }
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%.*}"
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
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
#[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::*;
// 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,
//! 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 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 {
}
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))
}
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();
//! 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 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 {
}
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))
}
}
},
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);
// 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();
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
} 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 {
// 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 bitcoin::secp256k1::{Keypair, Parity, PublicKey, Secp256k1, SecretKey, self};
use crate::utils::test_logger;
use core::convert::TryFrom;
use lightning::blinded_path::BlindedPath;
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) {
// You may not use this file except in accordance with one or both of these
// licenses.
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
use crate::utils::test_logger;
use core::convert::TryFrom;
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
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();
// 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;
// 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 bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self};
use crate::utils::test_logger;
use core::convert::TryFrom;
use lightning::blinded_path::BlindedPath;
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();
// 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 bitcoin::hashes::Hash;
use bitcoin::secp256k1::PublicKey;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use crate::utils::test_logger;
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)),
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 }
#[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};
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)
},
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 }
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;
use bitcoin::blockdata::block::Header;
use bitcoin::hash_types::BlockHash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use lightning::chain;
///
/// ```
/// use bitcoin::hash_types::BlockHash;
-/// use bitcoin::network::constants::Network;
+/// use bitcoin::network::Network;
///
/// use lightning::chain;
/// use lightning::chain::Watch;
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() {
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() {
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;
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;
// 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![]
-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))
}
#[cfg(test)]
mod tests {
use super::*;
+ use bitcoin::hashes::hex::HexToBytesError;
use bitcoin::pow::Work;
#[test]
#[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]
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
-bitcoin = "0.30.2"
+bitcoin = "0.31.2"
lightning = { version = "0.0.123-beta", path = "../lightning" }
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"] }
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::*;
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);
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))
}
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![
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;
/// 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,
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(
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 {
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) => {
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::*;
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" ] }
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]
[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 }
[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 }
[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"] }
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();
use bitcoin::{Amount, Txid, BlockHash};
use bitcoin::blockdata::block::Header;
use bitcoin::blockdata::constants::genesis_block;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
use bitcoind::bitcoincore_rpc::RpcApi;
use bdk_macros::maybe_await;
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());
+ $tx_sync.register_tx(&txid, &new_address.payload().script_pubkey());
maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap();
_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 = []
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 }
regex = "1.5.6"
[dev-dependencies.bitcoin]
-version = "0.30.2"
+version = "0.31.2"
default-features = false
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" }
//! 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};
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};
/// 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)
} else { None }
}) {
res.push(Balance::ClaimableAwaitingConfirmations {
- amount_satoshis: value,
+ amount_satoshis: value.to_sat(),
confirmation_height: conf_thresh,
});
} else {
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) {
.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 {
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,
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)
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() {
for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
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);
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 =
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);
}
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 {
{
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"); }
}
}
// 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
}
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!(); }
}
// 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 {
#[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;
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};
}
}
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 {
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);
// 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 {
}
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)];
{
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;
}
}
// 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 {
}
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)];
{
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;
}
}
// 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 {
});
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];
{
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;
}
}
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};
//! 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;
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)));
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 {
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};
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};
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,
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,
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);
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 {
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;
{
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))
}
}
}
///
/// 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);
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;
/// [`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),
}
}
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 */ +
}
/// 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 */ +
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,
}
///
/// 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
///
/// 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
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| {
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 {
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 {
(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 {
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 = {})",
.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)
}
}
// 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(&[]),
});
}
// 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,
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);
)?;
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![],
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
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;
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![],
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,
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());
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;
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;
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),
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;
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(),
},
],
//! 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;
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;
}
/// 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 {
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
}
Transaction {
- version: 2,
+ version: Version::TWO,
lock_time: LockTime::ZERO,
input: txins,
output: outputs,
/// 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()))
}
}
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),
));
Transaction {
- version: 2,
+ version: Version::TWO,
lock_time: LockTime::from_consensus(if htlc.offered { htlc.cltv_expiry } else { 0 }),
input: txins,
output: txouts,
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,
}
}
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 {
/// 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))
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
}
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(),
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());
///
/// 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)
}
/// 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,
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(),
/// 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
///
/// 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)
}
#[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>,
///
/// 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();
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,
// - 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 {
))
}
- if to_broadcaster_value_sat > 0 {
+ if to_broadcaster_value_sat > Amount::ZERO {
let redeem_script = get_revokeable_redeemscript(
&keys.revocation_key,
contest_delay,
);
txouts.push((
TxOut {
- script_pubkey: redeem_script.to_v0_p2wsh(),
+ script_pubkey: redeem_script.to_p2wsh(),
value: to_broadcaster_value_sat,
},
None,
}
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,
));
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)));
}
/// 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.
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)
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)
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)
}
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);
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
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");
}
.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);
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);
}
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};
// 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;
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());
};
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()));
}
}
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
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
}
// 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);
// 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);
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);
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);
#[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};
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]
// 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();
// 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();
// 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();
&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();
&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;
// 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 };
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;
///
/// ```
/// 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};
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 {
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");
}
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));
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};
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!(); }
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};
#[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]
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;
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);
}
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());
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)
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
{
$(
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| {
/// 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(),
/// 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,
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"),
// 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,
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};
//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);
}
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;
}
}
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);
}
});
// 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);
}
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);
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();
} }
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.
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
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);
// (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() };
}
}
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();
}
}
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();
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);
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);
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 {
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();
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());
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();
// 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(),
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(),
}]
};
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"),
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"),
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,
.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
.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,
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 }
}
}
}
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
.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())
})
}
.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())
})
}
// 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:
//
// 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)))
{
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(())
},
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(())
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)?;
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,
};
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,
},
};
- 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(),
}
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> {
}
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]
use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1::{Secp256k1, SecretKey};
use bitcoin::sighash::{SighashCache, EcdsaSighashType};
+use bitcoin::transaction::Version;
use crate::prelude::*;
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(),
},
],
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);
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".
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(),
},
],
// 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;
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(),
},
],
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
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);
}
}, 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()));
}, 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()));
// 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()));
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()));
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(),
}],
};
}, 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()));
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());
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(),
}],
};
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))
}
}
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))
};
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(),
}],
};
_ => 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);
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`
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 },
}
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);
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);
};
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);
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(),
},
],
#[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};
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};
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)
}
}
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(),
}],
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(),
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();
//! 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};
#[cfg(test)]
mod tests {
- use bitcoin::network::constants::Network;
+ use bitcoin::network::Network;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use core::time::Duration;
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::*;
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() {
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).
//! 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;
/// 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.
/// 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()
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,
}
}
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;
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()));
#[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()));
#[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()));
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::*;
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);
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!(); }
#[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;
//! 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;
//! 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();
//! # 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};
/// [`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 {}
#[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();
#[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();
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,
};
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;
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());
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());
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 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))
};
//! 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;
//!
//! # 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();
//!
//! ```
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;
}
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")] {
}
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;
/// [`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`].
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;
#[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()
) -> 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,
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};
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
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);
}
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)
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)
//! 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};
//! # #[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);
//! [`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;
/// 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| {
};
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;
//! Parsing and formatting for bech32 message encoding.
-use bitcoin::bech32;
use bitcoin::secp256k1;
use crate::io;
use crate::ln::msgs::DecodeError;
pub use sealed::Bech32Encode;
mod sealed {
- use bitcoin::bech32;
- use bitcoin::bech32::{FromBase32, ToBase32};
+ use bech32::{FromBase32, ToBase32};
use core::fmt;
use super::Bolt12ParseError;
#[cfg(test)]
mod tests {
use super::Bolt12ParseError;
- use bitcoin::bech32;
use crate::ln::msgs::DecodeError;
use crate::offers::offer::Offer;
//! 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};
//! # #[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);
//! [`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;
};
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;
#[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();
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};
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) => {
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();
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)
}
}
}
-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:
/// 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);
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()) {
//! 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;
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))
}
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))
}
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};
//! The [`NetworkGraph`] stores the network gossip and [`P2PGossipSync`] fetches it from peers
+use bitcoin::amount::Amount;
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
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;
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();
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,
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;
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 {
// 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);
// 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")
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;
{
};
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) {
#[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;
.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);
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;
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};
//! 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;
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 ({})",
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;
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();
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();
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());
}
"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());
"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();
// 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()
//! 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};
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};
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)]
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.
///
/// To get the proprietary field use:
/// ```
- /// use bitcoin::psbt::{PartiallySignedTransaction};
+ /// use bitcoin::psbt::{Psbt};
/// use bitcoin::hashes::hex::FromHex;
///
/// # let s = "70736274ff0100520200000001dee978529ab3e61a2987bea5183713d0e6d5ceb5ac81100fdb54a1a2\
/// # 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,
}
}
- /// 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.
///
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 {
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,
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,
&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(),
}
}
};
let sighash = hash_to_message!(
&sighash::SighashCache::new(spend_tx)
- .segwit_signature_hash(
+ .p2wsh_signature_hash(
input_idx,
&witness_script,
descriptor.output.value,
);
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 {
);
let sighash = hash_to_message!(
&sighash::SighashCache::new(spend_tx)
- .segwit_signature_hash(
+ .p2wsh_signature_hash(
input_idx,
&witness_script,
descriptor.output.value,
};
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()[..]
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));
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));
) -> 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(|_| ())?;
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))
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();
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,
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)
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];
// 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");
)
}
- /// 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.
///
/// 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| {
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,
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);
}
let sighash = hash_to_message!(
&sighash::SighashCache::new(&psbt.unsigned_tx)
- .segwit_signature_hash(
+ .p2wsh_signature_hash(
input_idx,
&witness_script,
output.value,
&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))
}
&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))
}
)?;
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
{
#[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])
}
}
}
//! Low level invoice utilities.
-use bitcoin::bech32::{u5, FromBase32};
+use bech32::{u5, FromBase32};
#[allow(unused)]
use crate::prelude::*;
/// 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.
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)
}
},
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]
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))
/// 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;
#[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;
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};
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(())
// 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);
}
}
+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[..])
} 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,
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};
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 {
#[cfg(test)]
struct JusticeTxData {
justice_tx: Transaction,
- value: u64,
+ value: Amount,
commitment_number: u64,
}
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()
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!()
}
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()),
}
}
- 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());
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())
// 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::*;
/// 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(()); }
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)
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();
#[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();
#[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();
#[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();
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();
#[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.
#[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();
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();