From 4a8ec80ca87dbc9a67ce59e6900f24acf6b93800 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 20 Apr 2022 12:44:26 +1000 Subject: [PATCH] Run rustfmt Add a `rustfmt` config file. Change a few options and add comments with the original default value. Run `cargo +nightly fmt`. --- examples/bip32.rs | 18 +- examples/handshake.rs | 7 +- rustfmt.toml | 78 +++- src/blockdata/block.rs | 107 ++++-- src/blockdata/constants.rs | 172 ++++----- src/blockdata/mod.rs | 3 +- src/blockdata/opcodes.rs | 615 ++++++++++++++++--------------- src/blockdata/script.rs | 449 +++++++++++++--------- src/blockdata/transaction.rs | 421 +++++++++++++-------- src/blockdata/witness.rs | 28 +- src/consensus/encode.rs | 269 +++++++++----- src/consensus/mod.rs | 5 +- src/consensus/params.rs | 2 +- src/internal_macros.rs | 54 ++- src/lib.rs | 81 ++-- src/network/address.rs | 229 ++++++++---- src/network/constants.rs | 15 +- src/network/message.rs | 281 +++++++++----- src/network/message_blockdata.rs | 34 +- src/network/message_bloom.rs | 4 +- src/network/message_network.rs | 37 +- src/network/mod.rs | 10 +- src/network/stream_reader.rs | 57 ++- src/policy.rs | 3 +- src/serde_utils.rs | 41 ++- src/util/address.rs | 254 +++++++------ src/util/amount.rs | 211 ++++++----- src/util/base58.rs | 74 ++-- src/util/bip143.rs | 64 ++-- src/util/bip158.rs | 199 ++++++---- src/util/bip32.rs | 224 ++++++----- src/util/ecdsa.rs | 44 +-- src/util/endian.rs | 42 ++- src/util/hash.rs | 26 +- src/util/key.rs | 121 +++--- src/util/merkleblock.rs | 67 ++-- src/util/misc.rs | 116 +++--- src/util/mod.rs | 26 +- src/util/psbt/error.rs | 37 +- src/util/psbt/macros.rs | 16 +- src/util/psbt/map/global.rs | 99 ++--- src/util/psbt/map/input.rs | 88 +++-- src/util/psbt/map/mod.rs | 8 +- src/util/psbt/map/output.rs | 75 ++-- src/util/psbt/mod.rs | 182 ++++----- src/util/psbt/raw.rs | 37 +- src/util/psbt/serialize.rs | 118 +++--- src/util/schnorr.rs | 53 +-- src/util/sighash.rs | 235 ++++++------ src/util/taproot.rs | 216 +++++++---- src/util/uint.rs | 200 +++++++--- 51 files changed, 3438 insertions(+), 2414 deletions(-) diff --git a/examples/bip32.rs b/examples/bip32.rs index 6dfd38891f..8ebdd84552 100644 --- a/examples/bip32.rs +++ b/examples/bip32.rs @@ -1,17 +1,14 @@ extern crate bitcoin; -use std::{env, process}; use std::str::FromStr; +use std::{env, process}; +use bitcoin::hashes::hex::FromHex; +use bitcoin::secp256k1::ffi::types::AlignedType; use bitcoin::secp256k1::Secp256k1; -use bitcoin::PublicKey; -use bitcoin::util::bip32::ExtendedPrivKey; -use bitcoin::util::bip32::ExtendedPubKey; -use bitcoin::util::bip32::DerivationPath; -use bitcoin::util::bip32::ChildNumber; use bitcoin::util::address::Address; -use bitcoin::secp256k1::ffi::types::AlignedType; -use bitcoin::hashes::hex::FromHex; +use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey}; +use bitcoin::PublicKey; fn main() { // This example derives root xprv from a 32-byte seed, @@ -55,10 +52,7 @@ fn main() { // generate first receiving address at m/0/0 // manually creating indexes this time let zero = ChildNumber::from_normal_idx(0).unwrap(); - let public_key = xpub.derive_pub(&secp, &vec![zero, zero]) - .unwrap() - .public_key; + let public_key = xpub.derive_pub(&secp, &vec![zero, zero]).unwrap().public_key; let address = Address::p2wpkh(&PublicKey::new(public_key), network).unwrap(); println!("First receiving address: {}", address); - } diff --git a/examples/handshake.rs b/examples/handshake.rs index 9c4cf0462a..8852b04231 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -1,9 +1,9 @@ extern crate bitcoin; +use std::io::{BufReader, Write}; use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, process}; -use std::io::{Write, BufReader}; use bitcoin::consensus::{encode, Decodable}; use bitcoin::network::{address, constants, message, message_network}; @@ -80,10 +80,7 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage { let services = constants::ServiceFlags::NONE; // "standard UNIX timestamp in seconds" - let timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time error") - .as_secs(); + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs(); // "The network address of the node receiving this message" let addr_recv = address::Address::new(&address, constants::ServiceFlags::NONE); diff --git a/rustfmt.toml b/rustfmt.toml index c7ad93bafe..d098ff265a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,77 @@ -disable_all_formatting = true +max_width = 100 # Default 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Auto" +indent_style = "Block" +use_small_heuristics = "Default" +fn_call_width = 80 # Default 60 +attr_fn_like_width = 80 # Default 70 +struct_lit_width = 50 # Default 18 +struct_variant_width = 80 # Default 35 +array_width = 80 # Default 60 +chain_width = 80 # Default 60 +single_line_if_else_max_width = 80 # Default 50 +wrap_comments = false +format_code_in_doc_comments = false +comment_width = 100 # Default 80 +normalize_comments = false +normalize_doc_attributes = false +license_template_path = "" +format_strings = false +format_macro_matchers = false +format_macro_bodies = true +hex_literal_case = "Preserve" +empty_item_single_line = true +struct_lit_single_line = true +fn_single_line = false +where_single_line = false +imports_indent = "Block" +imports_layout = "Mixed" +imports_granularity = "Module" # Default "Preserve" +group_imports = "StdExternalCrate" # Default "Preserve" +reorder_imports = true +reorder_modules = true +reorder_impl_items = false +type_punctuation_density = "Wide" +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false +binop_separator = "Front" +remove_nested_parens = true +combine_control_expr = true +overflow_delimited_expr = false +struct_field_align_threshold = 0 +enum_discrim_align_threshold = 0 +match_arm_blocks = true +match_arm_leading_pipes = "Never" +force_multiline_blocks = false +fn_args_layout = "Tall" +brace_style = "SameLineWhere" +control_brace_style = "AlwaysSameLine" +trailing_semicolon = true +trailing_comma = "Vertical" +match_block_trailing_comma = false +blank_lines_upper_bound = 1 +blank_lines_lower_bound = 0 +edition = "2015" +version = "One" +inline_attribute_width = 0 +format_generated_files = true +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true +condense_wildcard_suffixes = false +color = "Auto" +required_version = "1.4.38" +unstable_features = false +disable_all_formatting = false +skip_children = false +hide_parse_errors = false +error_on_line_overflow = false +error_on_unformatted = false +report_todo = "Never" +report_fixme = "Never" +ignore = [] +emit_mode = "Files" +make_backup = false diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 8fe78118cf..92acb46766 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -20,22 +20,20 @@ //! these blocks and the blockchain. //! -use prelude::*; - use core::fmt; -use util; -use util::Error::{BlockBadTarget, BlockBadProofOfWork}; -use util::hash::bitcoin_merkle_root; -use hashes::{Hash, HashEngine}; -use hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; -use util::uint::Uint256; -use consensus::encode::Encodable; -use network::constants::Network; -use blockdata::transaction::Transaction; use blockdata::constants::{max_target, WITNESS_SCALE_FACTOR}; use blockdata::script; -use VarInt; +use blockdata::transaction::Transaction; +use consensus::encode::Encodable; +use hash_types::{BlockHash, TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid}; +use hashes::{Hash, HashEngine}; +use network::constants::Network; +use prelude::*; +use util::hash::bitcoin_merkle_root; +use util::uint::Uint256; +use util::Error::{BlockBadProofOfWork, BlockBadTarget}; +use {util, VarInt}; /// A block header, which contains all the block's information except /// the actual transactions @@ -140,7 +138,11 @@ impl BlockHeader { let mut ret = [0u64; 4]; util::endian::bytes_to_u64_slice_le(block_hash.as_inner(), &mut ret); let hash = &Uint256(ret); - if hash <= target { Ok(block_hash) } else { Err(BlockBadProofOfWork) } + if hash <= target { + Ok(block_hash) + } else { + Err(BlockBadProofOfWork) + } } /// Returns the total work of the block. @@ -163,7 +165,7 @@ pub struct Block { /// The block header pub header: BlockHeader, /// List of transactions contained in the block - pub txdata: Vec + pub txdata: Vec, } impl_consensus_encoding!(Block, header, txdata); @@ -200,15 +202,21 @@ impl Block { } // Commitment is in the last output that starts with magic bytes. - if let Some(pos) = coinbase.output.iter() - .rposition(|o| o.script_pubkey.len () >= 38 && o.script_pubkey[0..6] == MAGIC) + if let Some(pos) = coinbase + .output + .iter() + .rposition(|o| o.script_pubkey.len() >= 38 && o.script_pubkey[0..6] == MAGIC) { - let commitment = WitnessCommitment::from_slice(&coinbase.output[pos].script_pubkey.as_bytes()[6..38]).unwrap(); + let commitment = WitnessCommitment::from_slice( + &coinbase.output[pos].script_pubkey.as_bytes()[6..38], + ) + .unwrap(); // Witness reserved value is in coinbase input witness. let witness_vec: Vec<_> = coinbase.input[0].witness.iter().collect(); if witness_vec.len() == 1 && witness_vec[0].len() == 32 { if let Some(witness_root) = self.witness_root() { - return commitment == Self::compute_witness_commitment(&witness_root, witness_vec[0]); + return commitment + == Self::compute_witness_commitment(&witness_root, witness_vec[0]); } } } @@ -229,7 +237,10 @@ impl Block { } /// Computes the witness commitment for the block's transaction list. - pub fn compute_witness_commitment(witness_root: &WitnessMerkleNode, witness_reserved_value: &[u8]) -> WitnessCommitment { + pub fn compute_witness_commitment( + witness_root: &WitnessMerkleNode, + witness_reserved_value: &[u8], + ) -> WitnessCommitment { let mut encoder = WitnessCommitment::engine(); witness_root.consensus_encode(&mut encoder).expect("engines don't error"); encoder.input(witness_reserved_value); @@ -359,13 +370,12 @@ impl ::std::error::Error for Bip34Error {} #[cfg(test)] mod tests { - use hashes::hex::FromHex; - use blockdata::block::{Block, BlockHeader}; use consensus::encode::{deserialize, serialize}; - use util::uint::Uint256; - use util::Error::{BlockBadTarget, BlockBadProofOfWork}; + use hashes::hex::FromHex; use network::constants::Network; + use util::uint::Uint256; + use util::Error::{BlockBadProofOfWork, BlockBadTarget}; #[test] fn test_coinbase_and_bip34() { @@ -378,7 +388,6 @@ mod tests { assert_eq!(block.bip34_block_height(), Ok(100_000)); - // block with 9-byte bip34 push let bad_hex = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3d09a08601112233445566000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000"; let bad: Block = deserialize(&Vec::::from_hex(bad_hex).unwrap()).unwrap(); @@ -393,8 +402,12 @@ mod tests { let some_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap(); let cutoff_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap(); - let prevhash = Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); - let merkle = Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); + let prevhash = + Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000") + .unwrap(); + let merkle = + Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c") + .unwrap(); let work = Uint256([0x100010001u64, 0, 0, 0]); let decode: Result = deserialize(&some_block); @@ -411,7 +424,10 @@ mod tests { assert_eq!(real_decode.header.bits, 486604799); assert_eq!(real_decode.header.nonce, 2067413810); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!( + real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), + real_decode.block_hash() + ); assert_eq!(real_decode.header.difficulty(Network::Bitcoin), 1); // [test] TODO: check the transaction data @@ -432,13 +448,17 @@ mod tests { let decode: Result = deserialize(&segwit_block); - let prevhash = Vec::from_hex("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000").unwrap(); - let merkle = Vec::from_hex("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e").unwrap(); + let prevhash = + Vec::from_hex("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000") + .unwrap(); + let merkle = + Vec::from_hex("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e") + .unwrap(); let work = Uint256([0x257c3becdacc64u64, 0, 0, 0]); assert!(decode.is_ok()); let real_decode = decode.unwrap(); - assert_eq!(real_decode.header.version, 0x20000000); // VERSIONBITS but no bits set + assert_eq!(real_decode.header.version, 0x20000000); // VERSIONBITS but no bits set assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash); assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap()); @@ -446,7 +466,10 @@ mod tests { assert_eq!(real_decode.header.bits, 0x1a06d450); assert_eq!(real_decode.header.nonce, 1879759182); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!( + real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), + real_decode.block_hash() + ); assert_eq!(real_decode.header.difficulty(Network::Testnet), 2456598); // [test] TODO: check the transaction data @@ -477,13 +500,17 @@ mod tests { #[test] fn validate_pow_test() { let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); - let some_header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header"); - assert_eq!(some_header.validate_pow(&some_header.target()).unwrap(), some_header.block_hash()); + let some_header: BlockHeader = + deserialize(&some_header).expect("Can't deserialize correct block header"); + assert_eq!( + some_header.validate_pow(&some_header.target()).unwrap(), + some_header.block_hash() + ); // test with zero target match some_header.validate_pow(&Uint256::default()) { Err(BlockBadTarget) => (), - _ => assert!(false) + _ => assert!(false), } // test with modified header @@ -491,7 +518,7 @@ mod tests { invalid_header.version = invalid_header.version + 1; match invalid_header.validate_pow(&invalid_header.target()) { Err(BlockBadProofOfWork) => (), - _ => assert!(false) + _ => assert!(false), } } @@ -499,7 +526,8 @@ mod tests { fn compact_roundrtip_test() { let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); - let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header"); + let header: BlockHeader = + deserialize(&some_header).expect("Can't deserialize correct block header"); assert_eq!(header.bits, BlockHeader::compact_target_from_u256(&header.target())); } @@ -507,11 +535,12 @@ mod tests { #[cfg(all(test, feature = "unstable"))] mod benches { - use super::Block; - use EmptyWrite; use consensus::{deserialize, Encodable}; - use test::{black_box, Bencher}; use network::stream_reader::StreamReader; + use test::{black_box, Bencher}; + use EmptyWrite; + + use super::Block; #[bench] #[allow(deprecated)] diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index bb0ac0b508..12319dd270 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -19,18 +19,16 @@ //! single transaction. //! -use prelude::*; - use core::default::Default; -use hashes::hex::{HexIterator, Error as HexError}; -use hashes::sha256d; -use blockdata::opcodes; -use blockdata::script; -use blockdata::transaction::{OutPoint, Transaction, TxOut, TxIn}; use blockdata::block::{Block, BlockHeader}; +use blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use blockdata::witness::Witness; +use blockdata::{opcodes, script}; +use hashes::hex::{Error as HexError, HexIterator}; +use hashes::sha256d; use network::constants::Network; +use prelude::*; use util::uint::Uint256; /// The maximum allowable sequence number @@ -87,10 +85,11 @@ fn bitcoin_genesis_tx() -> Transaction { }; // Inputs - let in_script = script::Builder::new().push_scriptint(486604799) - .push_scriptint(4) - .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") - .into_script(); + let in_script = script::Builder::new() + .push_scriptint(486604799) + .push_scriptint(4) + .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") + .into_script(); ret.input.push(TxIn { previous_output: OutPoint::null(), script_sig: in_script, @@ -106,10 +105,7 @@ fn bitcoin_genesis_tx() -> Transaction { .push_slice(script_bytes.unwrap().as_slice()) .push_opcode(opcodes::all::OP_CHECKSIG) .into_script(); - ret.output.push(TxOut { - value: 50 * COIN_VALUE, - script_pubkey: out_script - }); + ret.output.push(TxOut { value: 50 * COIN_VALUE, script_pubkey: out_script }); // end ret @@ -121,70 +117,61 @@ pub fn genesis_block(network: Network) -> Block { let hash: sha256d::Hash = txdata[0].txid().into(); let merkle_root = hash.into(); match network { - Network::Bitcoin => { - Block { - header: BlockHeader { - version: 1, - prev_blockhash: Default::default(), - merkle_root, - time: 1231006505, - bits: 0x1d00ffff, - nonce: 2083236893 - }, - txdata, - } - } - Network::Testnet => { - Block { - header: BlockHeader { - version: 1, - prev_blockhash: Default::default(), - merkle_root, - time: 1296688602, - bits: 0x1d00ffff, - nonce: 414098458 - }, - txdata, - } - } - Network::Signet => { - Block { - header: BlockHeader { - version: 1, - prev_blockhash: Default::default(), - merkle_root, - time: 1598918400, - bits: 0x1e0377ae, - nonce: 52613770 - }, - txdata, - } - } - Network::Regtest => { - Block { - header: BlockHeader { - version: 1, - prev_blockhash: Default::default(), - merkle_root, - time: 1296688602, - bits: 0x207fffff, - nonce: 2 - }, - txdata, - } - } + Network::Bitcoin => Block { + header: BlockHeader { + version: 1, + prev_blockhash: Default::default(), + merkle_root, + time: 1231006505, + bits: 0x1d00ffff, + nonce: 2083236893, + }, + txdata, + }, + Network::Testnet => Block { + header: BlockHeader { + version: 1, + prev_blockhash: Default::default(), + merkle_root, + time: 1296688602, + bits: 0x1d00ffff, + nonce: 414098458, + }, + txdata, + }, + Network::Signet => Block { + header: BlockHeader { + version: 1, + prev_blockhash: Default::default(), + merkle_root, + time: 1598918400, + bits: 0x1e0377ae, + nonce: 52613770, + }, + txdata, + }, + Network::Regtest => Block { + header: BlockHeader { + version: 1, + prev_blockhash: Default::default(), + merkle_root, + time: 1296688602, + bits: 0x207fffff, + nonce: 2, + }, + txdata, + }, } } #[cfg(test)] mod test { use core::default::Default; - use hashes::hex::FromHex; - use network::constants::Network; + use blockdata::constants::{bitcoin_genesis_tx, genesis_block, COIN_VALUE, MAX_SEQUENCE}; use consensus::encode::serialize; - use blockdata::constants::{genesis_block, bitcoin_genesis_tx}; - use blockdata::constants::{MAX_SEQUENCE, COIN_VALUE}; + use hashes::hex::FromHex; + use network::constants::Network; #[test] fn bitcoin_genesis_first_transaction() { @@ -204,8 +191,10 @@ mod test { assert_eq!(gen.output[0].value, 50 * COIN_VALUE); assert_eq!(gen.lock_time, 0); - assert_eq!(format!("{:x}", gen.wtxid()), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); + assert_eq!( + format!("{:x}", gen.wtxid()), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string() + ); } #[test] @@ -214,13 +203,17 @@ mod test { assert_eq!(gen.header.version, 1); assert_eq!(gen.header.prev_blockhash, Default::default()); - assert_eq!(format!("{:x}", gen.header.merkle_root), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); + assert_eq!( + format!("{:x}", gen.header.merkle_root), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string() + ); assert_eq!(gen.header.time, 1231006505); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 2083236893); - assert_eq!(format!("{:x}", gen.header.block_hash()), - "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f".to_string()); + assert_eq!( + format!("{:x}", gen.header.block_hash()), + "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f".to_string() + ); } #[test] @@ -228,13 +221,17 @@ mod test { let gen = genesis_block(Network::Testnet); assert_eq!(gen.header.version, 1); assert_eq!(gen.header.prev_blockhash, Default::default()); - assert_eq!(format!("{:x}", gen.header.merkle_root), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); + assert_eq!( + format!("{:x}", gen.header.merkle_root), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string() + ); assert_eq!(gen.header.time, 1296688602); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 414098458); - assert_eq!(format!("{:x}", gen.header.block_hash()), - "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string()); + assert_eq!( + format!("{:x}", gen.header.block_hash()), + "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string() + ); } #[test] @@ -242,13 +239,16 @@ mod test { let gen = genesis_block(Network::Signet); assert_eq!(gen.header.version, 1); assert_eq!(gen.header.prev_blockhash, Default::default()); - assert_eq!(format!("{:x}", gen.header.merkle_root), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); + assert_eq!( + format!("{:x}", gen.header.merkle_root), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string() + ); assert_eq!(gen.header.time, 1598918400); assert_eq!(gen.header.bits, 0x1e0377ae); assert_eq!(gen.header.nonce, 52613770); - assert_eq!(format!("{:x}", gen.header.block_hash()), - "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6".to_string()); + assert_eq!( + format!("{:x}", gen.header.block_hash()), + "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6".to_string() + ); } } - diff --git a/src/blockdata/mod.rs b/src/blockdata/mod.rs index 48f80ef8b7..e410cdaaea 100644 --- a/src/blockdata/mod.rs +++ b/src/blockdata/mod.rs @@ -18,10 +18,9 @@ //! transactions which make up the Bitcoin system. //! +pub mod block; pub mod constants; pub mod opcodes; pub mod script; pub mod transaction; -pub mod block; pub mod witness; - diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index 41b4796d30..a37ff1e7e5 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -20,11 +20,13 @@ #![allow(non_camel_case_types)] -#[cfg(feature = "serde")] use serde; +use core::convert::From; +use core::fmt; -#[cfg(feature = "serde")] use prelude::*; - -use core::{fmt, convert::From}; +#[cfg(feature = "serde")] +use prelude::*; +#[cfg(feature = "serde")] +use serde; // Note: I am deliberately not implementing PartialOrd or Ord on the // opcode enum. If you want to check ranges of opcodes, etc., @@ -41,535 +43,537 @@ pub mod all { use super::All; /// Push an empty array onto the stack. - pub const OP_PUSHBYTES_0: All = All {code: 0x00}; + pub const OP_PUSHBYTES_0: All = All { code: 0x00 }; /// Push the next byte as an array onto the stack. - pub const OP_PUSHBYTES_1: All = All {code: 0x01}; + pub const OP_PUSHBYTES_1: All = All { code: 0x01 }; /// Push the next 2 bytes as an array onto the stack. - pub const OP_PUSHBYTES_2: All = All {code: 0x02}; + pub const OP_PUSHBYTES_2: All = All { code: 0x02 }; /// Push the next 2 bytes as an array onto the stack. - pub const OP_PUSHBYTES_3: All = All {code: 0x03}; + pub const OP_PUSHBYTES_3: All = All { code: 0x03 }; /// Push the next 4 bytes as an array onto the stack. - pub const OP_PUSHBYTES_4: All = All {code: 0x04}; + pub const OP_PUSHBYTES_4: All = All { code: 0x04 }; /// Push the next 5 bytes as an array onto the stack. - pub const OP_PUSHBYTES_5: All = All {code: 0x05}; + pub const OP_PUSHBYTES_5: All = All { code: 0x05 }; /// Push the next 6 bytes as an array onto the stack. - pub const OP_PUSHBYTES_6: All = All {code: 0x06}; + pub const OP_PUSHBYTES_6: All = All { code: 0x06 }; /// Push the next 7 bytes as an array onto the stack. - pub const OP_PUSHBYTES_7: All = All {code: 0x07}; + pub const OP_PUSHBYTES_7: All = All { code: 0x07 }; /// Push the next 8 bytes as an array onto the stack. - pub const OP_PUSHBYTES_8: All = All {code: 0x08}; + pub const OP_PUSHBYTES_8: All = All { code: 0x08 }; /// Push the next 9 bytes as an array onto the stack. - pub const OP_PUSHBYTES_9: All = All {code: 0x09}; + pub const OP_PUSHBYTES_9: All = All { code: 0x09 }; /// Push the next 10 bytes as an array onto the stack. - pub const OP_PUSHBYTES_10: All = All {code: 0x0a}; + pub const OP_PUSHBYTES_10: All = All { code: 0x0a }; /// Push the next 11 bytes as an array onto the stack. - pub const OP_PUSHBYTES_11: All = All {code: 0x0b}; + pub const OP_PUSHBYTES_11: All = All { code: 0x0b }; /// Push the next 12 bytes as an array onto the stack. - pub const OP_PUSHBYTES_12: All = All {code: 0x0c}; + pub const OP_PUSHBYTES_12: All = All { code: 0x0c }; /// Push the next 13 bytes as an array onto the stack. - pub const OP_PUSHBYTES_13: All = All {code: 0x0d}; + pub const OP_PUSHBYTES_13: All = All { code: 0x0d }; /// Push the next 14 bytes as an array onto the stack. - pub const OP_PUSHBYTES_14: All = All {code: 0x0e}; + pub const OP_PUSHBYTES_14: All = All { code: 0x0e }; /// Push the next 15 bytes as an array onto the stack. - pub const OP_PUSHBYTES_15: All = All {code: 0x0f}; + pub const OP_PUSHBYTES_15: All = All { code: 0x0f }; /// Push the next 16 bytes as an array onto the stack. - pub const OP_PUSHBYTES_16: All = All {code: 0x10}; + pub const OP_PUSHBYTES_16: All = All { code: 0x10 }; /// Push the next 17 bytes as an array onto the stack. - pub const OP_PUSHBYTES_17: All = All {code: 0x11}; + pub const OP_PUSHBYTES_17: All = All { code: 0x11 }; /// Push the next 18 bytes as an array onto the stack. - pub const OP_PUSHBYTES_18: All = All {code: 0x12}; + pub const OP_PUSHBYTES_18: All = All { code: 0x12 }; /// Push the next 19 bytes as an array onto the stack. - pub const OP_PUSHBYTES_19: All = All {code: 0x13}; + pub const OP_PUSHBYTES_19: All = All { code: 0x13 }; /// Push the next 20 bytes as an array onto the stack. - pub const OP_PUSHBYTES_20: All = All {code: 0x14}; + pub const OP_PUSHBYTES_20: All = All { code: 0x14 }; /// Push the next 21 bytes as an array onto the stack. - pub const OP_PUSHBYTES_21: All = All {code: 0x15}; + pub const OP_PUSHBYTES_21: All = All { code: 0x15 }; /// Push the next 22 bytes as an array onto the stack. - pub const OP_PUSHBYTES_22: All = All {code: 0x16}; + pub const OP_PUSHBYTES_22: All = All { code: 0x16 }; /// Push the next 23 bytes as an array onto the stack. - pub const OP_PUSHBYTES_23: All = All {code: 0x17}; + pub const OP_PUSHBYTES_23: All = All { code: 0x17 }; /// Push the next 24 bytes as an array onto the stack. - pub const OP_PUSHBYTES_24: All = All {code: 0x18}; + pub const OP_PUSHBYTES_24: All = All { code: 0x18 }; /// Push the next 25 bytes as an array onto the stack. - pub const OP_PUSHBYTES_25: All = All {code: 0x19}; + pub const OP_PUSHBYTES_25: All = All { code: 0x19 }; /// Push the next 26 bytes as an array onto the stack. - pub const OP_PUSHBYTES_26: All = All {code: 0x1a}; + pub const OP_PUSHBYTES_26: All = All { code: 0x1a }; /// Push the next 27 bytes as an array onto the stack. - pub const OP_PUSHBYTES_27: All = All {code: 0x1b}; + pub const OP_PUSHBYTES_27: All = All { code: 0x1b }; /// Push the next 28 bytes as an array onto the stack. - pub const OP_PUSHBYTES_28: All = All {code: 0x1c}; + pub const OP_PUSHBYTES_28: All = All { code: 0x1c }; /// Push the next 29 bytes as an array onto the stack. - pub const OP_PUSHBYTES_29: All = All {code: 0x1d}; + pub const OP_PUSHBYTES_29: All = All { code: 0x1d }; /// Push the next 30 bytes as an array onto the stack. - pub const OP_PUSHBYTES_30: All = All {code: 0x1e}; + pub const OP_PUSHBYTES_30: All = All { code: 0x1e }; /// Push the next 31 bytes as an array onto the stack. - pub const OP_PUSHBYTES_31: All = All {code: 0x1f}; + pub const OP_PUSHBYTES_31: All = All { code: 0x1f }; /// Push the next 32 bytes as an array onto the stack. - pub const OP_PUSHBYTES_32: All = All {code: 0x20}; + pub const OP_PUSHBYTES_32: All = All { code: 0x20 }; /// Push the next 33 bytes as an array onto the stack. - pub const OP_PUSHBYTES_33: All = All {code: 0x21}; + pub const OP_PUSHBYTES_33: All = All { code: 0x21 }; /// Push the next 34 bytes as an array onto the stack. - pub const OP_PUSHBYTES_34: All = All {code: 0x22}; + pub const OP_PUSHBYTES_34: All = All { code: 0x22 }; /// Push the next 35 bytes as an array onto the stack. - pub const OP_PUSHBYTES_35: All = All {code: 0x23}; + pub const OP_PUSHBYTES_35: All = All { code: 0x23 }; /// Push the next 36 bytes as an array onto the stack. - pub const OP_PUSHBYTES_36: All = All {code: 0x24}; + pub const OP_PUSHBYTES_36: All = All { code: 0x24 }; /// Push the next 37 bytes as an array onto the stack. - pub const OP_PUSHBYTES_37: All = All {code: 0x25}; + pub const OP_PUSHBYTES_37: All = All { code: 0x25 }; /// Push the next 38 bytes as an array onto the stack. - pub const OP_PUSHBYTES_38: All = All {code: 0x26}; + pub const OP_PUSHBYTES_38: All = All { code: 0x26 }; /// Push the next 39 bytes as an array onto the stack. - pub const OP_PUSHBYTES_39: All = All {code: 0x27}; + pub const OP_PUSHBYTES_39: All = All { code: 0x27 }; /// Push the next 40 bytes as an array onto the stack. - pub const OP_PUSHBYTES_40: All = All {code: 0x28}; + pub const OP_PUSHBYTES_40: All = All { code: 0x28 }; /// Push the next 41 bytes as an array onto the stack. - pub const OP_PUSHBYTES_41: All = All {code: 0x29}; + pub const OP_PUSHBYTES_41: All = All { code: 0x29 }; /// Push the next 42 bytes as an array onto the stack. - pub const OP_PUSHBYTES_42: All = All {code: 0x2a}; + pub const OP_PUSHBYTES_42: All = All { code: 0x2a }; /// Push the next 43 bytes as an array onto the stack. - pub const OP_PUSHBYTES_43: All = All {code: 0x2b}; + pub const OP_PUSHBYTES_43: All = All { code: 0x2b }; /// Push the next 44 bytes as an array onto the stack. - pub const OP_PUSHBYTES_44: All = All {code: 0x2c}; + pub const OP_PUSHBYTES_44: All = All { code: 0x2c }; /// Push the next 45 bytes as an array onto the stack. - pub const OP_PUSHBYTES_45: All = All {code: 0x2d}; + pub const OP_PUSHBYTES_45: All = All { code: 0x2d }; /// Push the next 46 bytes as an array onto the stack. - pub const OP_PUSHBYTES_46: All = All {code: 0x2e}; + pub const OP_PUSHBYTES_46: All = All { code: 0x2e }; /// Push the next 47 bytes as an array onto the stack. - pub const OP_PUSHBYTES_47: All = All {code: 0x2f}; + pub const OP_PUSHBYTES_47: All = All { code: 0x2f }; /// Push the next 48 bytes as an array onto the stack. - pub const OP_PUSHBYTES_48: All = All {code: 0x30}; + pub const OP_PUSHBYTES_48: All = All { code: 0x30 }; /// Push the next 49 bytes as an array onto the stack. - pub const OP_PUSHBYTES_49: All = All {code: 0x31}; + pub const OP_PUSHBYTES_49: All = All { code: 0x31 }; /// Push the next 50 bytes as an array onto the stack. - pub const OP_PUSHBYTES_50: All = All {code: 0x32}; + pub const OP_PUSHBYTES_50: All = All { code: 0x32 }; /// Push the next 51 bytes as an array onto the stack. - pub const OP_PUSHBYTES_51: All = All {code: 0x33}; + pub const OP_PUSHBYTES_51: All = All { code: 0x33 }; /// Push the next 52 bytes as an array onto the stack. - pub const OP_PUSHBYTES_52: All = All {code: 0x34}; + pub const OP_PUSHBYTES_52: All = All { code: 0x34 }; /// Push the next 53 bytes as an array onto the stack. - pub const OP_PUSHBYTES_53: All = All {code: 0x35}; + pub const OP_PUSHBYTES_53: All = All { code: 0x35 }; /// Push the next 54 bytes as an array onto the stack. - pub const OP_PUSHBYTES_54: All = All {code: 0x36}; + pub const OP_PUSHBYTES_54: All = All { code: 0x36 }; /// Push the next 55 bytes as an array onto the stack. - pub const OP_PUSHBYTES_55: All = All {code: 0x37}; + pub const OP_PUSHBYTES_55: All = All { code: 0x37 }; /// Push the next 56 bytes as an array onto the stack. - pub const OP_PUSHBYTES_56: All = All {code: 0x38}; + pub const OP_PUSHBYTES_56: All = All { code: 0x38 }; /// Push the next 57 bytes as an array onto the stack. - pub const OP_PUSHBYTES_57: All = All {code: 0x39}; + pub const OP_PUSHBYTES_57: All = All { code: 0x39 }; /// Push the next 58 bytes as an array onto the stack. - pub const OP_PUSHBYTES_58: All = All {code: 0x3a}; + pub const OP_PUSHBYTES_58: All = All { code: 0x3a }; /// Push the next 59 bytes as an array onto the stack. - pub const OP_PUSHBYTES_59: All = All {code: 0x3b}; + pub const OP_PUSHBYTES_59: All = All { code: 0x3b }; /// Push the next 60 bytes as an array onto the stack. - pub const OP_PUSHBYTES_60: All = All {code: 0x3c}; + pub const OP_PUSHBYTES_60: All = All { code: 0x3c }; /// Push the next 61 bytes as an array onto the stack. - pub const OP_PUSHBYTES_61: All = All {code: 0x3d}; + pub const OP_PUSHBYTES_61: All = All { code: 0x3d }; /// Push the next 62 bytes as an array onto the stack. - pub const OP_PUSHBYTES_62: All = All {code: 0x3e}; + pub const OP_PUSHBYTES_62: All = All { code: 0x3e }; /// Push the next 63 bytes as an array onto the stack. - pub const OP_PUSHBYTES_63: All = All {code: 0x3f}; + pub const OP_PUSHBYTES_63: All = All { code: 0x3f }; /// Push the next 64 bytes as an array onto the stack. - pub const OP_PUSHBYTES_64: All = All {code: 0x40}; + pub const OP_PUSHBYTES_64: All = All { code: 0x40 }; /// Push the next 65 bytes as an array onto the stack. - pub const OP_PUSHBYTES_65: All = All {code: 0x41}; + pub const OP_PUSHBYTES_65: All = All { code: 0x41 }; /// Push the next 66 bytes as an array onto the stack. - pub const OP_PUSHBYTES_66: All = All {code: 0x42}; + pub const OP_PUSHBYTES_66: All = All { code: 0x42 }; /// Push the next 67 bytes as an array onto the stack. - pub const OP_PUSHBYTES_67: All = All {code: 0x43}; + pub const OP_PUSHBYTES_67: All = All { code: 0x43 }; /// Push the next 68 bytes as an array onto the stack. - pub const OP_PUSHBYTES_68: All = All {code: 0x44}; + pub const OP_PUSHBYTES_68: All = All { code: 0x44 }; /// Push the next 69 bytes as an array onto the stack. - pub const OP_PUSHBYTES_69: All = All {code: 0x45}; + pub const OP_PUSHBYTES_69: All = All { code: 0x45 }; /// Push the next 70 bytes as an array onto the stack. - pub const OP_PUSHBYTES_70: All = All {code: 0x46}; + pub const OP_PUSHBYTES_70: All = All { code: 0x46 }; /// Push the next 71 bytes as an array onto the stack. - pub const OP_PUSHBYTES_71: All = All {code: 0x47}; + pub const OP_PUSHBYTES_71: All = All { code: 0x47 }; /// Push the next 72 bytes as an array onto the stack. - pub const OP_PUSHBYTES_72: All = All {code: 0x48}; + pub const OP_PUSHBYTES_72: All = All { code: 0x48 }; /// Push the next 73 bytes as an array onto the stack. - pub const OP_PUSHBYTES_73: All = All {code: 0x49}; + pub const OP_PUSHBYTES_73: All = All { code: 0x49 }; /// Push the next 74 bytes as an array onto the stack. - pub const OP_PUSHBYTES_74: All = All {code: 0x4a}; + pub const OP_PUSHBYTES_74: All = All { code: 0x4a }; /// Push the next 75 bytes as an array onto the stack. - pub const OP_PUSHBYTES_75: All = All {code: 0x4b}; + pub const OP_PUSHBYTES_75: All = All { code: 0x4b }; /// Read the next byte as N; push the next N bytes as an array onto the stack. - pub const OP_PUSHDATA1: All = All {code: 0x4c}; + pub const OP_PUSHDATA1: All = All { code: 0x4c }; /// Read the next 2 bytes as N; push the next N bytes as an array onto the stack. - pub const OP_PUSHDATA2: All = All {code: 0x4d}; + pub const OP_PUSHDATA2: All = All { code: 0x4d }; /// Read the next 4 bytes as N; push the next N bytes as an array onto the stack. - pub const OP_PUSHDATA4: All = All {code: 0x4e}; + pub const OP_PUSHDATA4: All = All { code: 0x4e }; /// Push the array `0x81` onto the stack. - pub const OP_PUSHNUM_NEG1: All = All {code: 0x4f}; + pub const OP_PUSHNUM_NEG1: All = All { code: 0x4f }; /// Synonym for OP_RETURN. - pub const OP_RESERVED: All = All {code: 0x50}; + pub const OP_RESERVED: All = All { code: 0x50 }; /// Push the array `0x01` onto the stack. - pub const OP_PUSHNUM_1: All = All {code: 0x51}; + pub const OP_PUSHNUM_1: All = All { code: 0x51 }; /// Push the array `0x02` onto the stack. - pub const OP_PUSHNUM_2: All = All {code: 0x52}; + pub const OP_PUSHNUM_2: All = All { code: 0x52 }; /// Push the array `0x03` onto the stack. - pub const OP_PUSHNUM_3: All = All {code: 0x53}; + pub const OP_PUSHNUM_3: All = All { code: 0x53 }; /// Push the array `0x04` onto the stack. - pub const OP_PUSHNUM_4: All = All {code: 0x54}; + pub const OP_PUSHNUM_4: All = All { code: 0x54 }; /// Push the array `0x05` onto the stack. - pub const OP_PUSHNUM_5: All = All {code: 0x55}; + pub const OP_PUSHNUM_5: All = All { code: 0x55 }; /// Push the array `0x06` onto the stack. - pub const OP_PUSHNUM_6: All = All {code: 0x56}; + pub const OP_PUSHNUM_6: All = All { code: 0x56 }; /// Push the array `0x07` onto the stack. - pub const OP_PUSHNUM_7: All = All {code: 0x57}; + pub const OP_PUSHNUM_7: All = All { code: 0x57 }; /// Push the array `0x08` onto the stack. - pub const OP_PUSHNUM_8: All = All {code: 0x58}; + pub const OP_PUSHNUM_8: All = All { code: 0x58 }; /// Push the array `0x09` onto the stack. - pub const OP_PUSHNUM_9: All = All {code: 0x59}; + pub const OP_PUSHNUM_9: All = All { code: 0x59 }; /// Push the array `0x0a` onto the stack. - pub const OP_PUSHNUM_10: All = All {code: 0x5a}; + pub const OP_PUSHNUM_10: All = All { code: 0x5a }; /// Push the array `0x0b` onto the stack. - pub const OP_PUSHNUM_11: All = All {code: 0x5b}; + pub const OP_PUSHNUM_11: All = All { code: 0x5b }; /// Push the array `0x0c` onto the stack. - pub const OP_PUSHNUM_12: All = All {code: 0x5c}; + pub const OP_PUSHNUM_12: All = All { code: 0x5c }; /// Push the array `0x0d` onto the stack. - pub const OP_PUSHNUM_13: All = All {code: 0x5d}; + pub const OP_PUSHNUM_13: All = All { code: 0x5d }; /// Push the array `0x0e` onto the stack. - pub const OP_PUSHNUM_14: All = All {code: 0x5e}; + pub const OP_PUSHNUM_14: All = All { code: 0x5e }; /// Push the array `0x0f` onto the stack. - pub const OP_PUSHNUM_15: All = All {code: 0x5f}; + pub const OP_PUSHNUM_15: All = All { code: 0x5f }; /// Push the array `0x10` onto the stack. - pub const OP_PUSHNUM_16: All = All {code: 0x60}; + pub const OP_PUSHNUM_16: All = All { code: 0x60 }; /// Does nothing. - pub const OP_NOP: All = All {code: 0x61}; + pub const OP_NOP: All = All { code: 0x61 }; /// Synonym for OP_RETURN. - pub const OP_VER: All = All {code: 0x62}; + pub const OP_VER: All = All { code: 0x62 }; /// Pop and execute the next statements if a nonzero element was popped. - pub const OP_IF: All = All {code: 0x63}; + pub const OP_IF: All = All { code: 0x63 }; /// Pop and execute the next statements if a zero element was popped. - pub const OP_NOTIF: All = All {code: 0x64}; + pub const OP_NOTIF: All = All { code: 0x64 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_VERIF: All = All {code: 0x65}; + pub const OP_VERIF: All = All { code: 0x65 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_VERNOTIF: All = All {code: 0x66}; + pub const OP_VERNOTIF: All = All { code: 0x66 }; /// Execute statements if those after the previous OP_IF were not, and vice-versa. /// If there is no previous OP_IF, this acts as a RETURN. - pub const OP_ELSE: All = All {code: 0x67}; + pub const OP_ELSE: All = All { code: 0x67 }; /// Pop and execute the next statements if a zero element was popped. - pub const OP_ENDIF: All = All {code: 0x68}; + pub const OP_ENDIF: All = All { code: 0x68 }; /// If the top value is zero or the stack is empty, fail; otherwise, pop the stack. - pub const OP_VERIFY: All = All {code: 0x69}; + pub const OP_VERIFY: All = All { code: 0x69 }; /// Fail the script immediately. (Must be executed.). - pub const OP_RETURN: All = All {code: 0x6a}; + pub const OP_RETURN: All = All { code: 0x6a }; /// Pop one element from the main stack onto the alt stack. - pub const OP_TOALTSTACK: All = All {code: 0x6b}; + pub const OP_TOALTSTACK: All = All { code: 0x6b }; /// Pop one element from the alt stack onto the main stack. - pub const OP_FROMALTSTACK: All = All {code: 0x6c}; + pub const OP_FROMALTSTACK: All = All { code: 0x6c }; /// Drops the top two stack items. - pub const OP_2DROP: All = All {code: 0x6d}; + pub const OP_2DROP: All = All { code: 0x6d }; /// Duplicates the top two stack items as AB -> ABAB. - pub const OP_2DUP: All = All {code: 0x6e}; + pub const OP_2DUP: All = All { code: 0x6e }; /// Duplicates the two three stack items as ABC -> ABCABC. - pub const OP_3DUP: All = All {code: 0x6f}; + pub const OP_3DUP: All = All { code: 0x6f }; /// Copies the two stack items of items two spaces back to /// the front, as xxAB -> ABxxAB. - pub const OP_2OVER: All = All {code: 0x70}; + pub const OP_2OVER: All = All { code: 0x70 }; /// Moves the two stack items four spaces back to the front, /// as xxxxAB -> ABxxxx. - pub const OP_2ROT: All = All {code: 0x71}; + pub const OP_2ROT: All = All { code: 0x71 }; /// Swaps the top two pairs, as ABCD -> CDAB. - pub const OP_2SWAP: All = All {code: 0x72}; + pub const OP_2SWAP: All = All { code: 0x72 }; /// Duplicate the top stack element unless it is zero. - pub const OP_IFDUP: All = All {code: 0x73}; + pub const OP_IFDUP: All = All { code: 0x73 }; /// Push the current number of stack items onto the stack. - pub const OP_DEPTH: All = All {code: 0x74}; + pub const OP_DEPTH: All = All { code: 0x74 }; /// Drops the top stack item. - pub const OP_DROP: All = All {code: 0x75}; + pub const OP_DROP: All = All { code: 0x75 }; /// Duplicates the top stack item. - pub const OP_DUP: All = All {code: 0x76}; + pub const OP_DUP: All = All { code: 0x76 }; /// Drops the second-to-top stack item. - pub const OP_NIP: All = All {code: 0x77}; + pub const OP_NIP: All = All { code: 0x77 }; /// Copies the second-to-top stack item, as xA -> AxA. - pub const OP_OVER: All = All {code: 0x78}; + pub const OP_OVER: All = All { code: 0x78 }; /// Pop the top stack element as N. Copy the Nth stack element to the top. - pub const OP_PICK: All = All {code: 0x79}; + pub const OP_PICK: All = All { code: 0x79 }; /// Pop the top stack element as N. Move the Nth stack element to the top. - pub const OP_ROLL: All = All {code: 0x7a}; + pub const OP_ROLL: All = All { code: 0x7a }; /// Rotate the top three stack items, as [top next1 next2] -> [next2 top next1]. - pub const OP_ROT: All = All {code: 0x7b}; + pub const OP_ROT: All = All { code: 0x7b }; /// Swap the top two stack items. - pub const OP_SWAP: All = All {code: 0x7c}; + pub const OP_SWAP: All = All { code: 0x7c }; /// Copy the top stack item to before the second item, as [top next] -> [top next top]. - pub const OP_TUCK: All = All {code: 0x7d}; + pub const OP_TUCK: All = All { code: 0x7d }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_CAT: All = All {code: 0x7e}; + pub const OP_CAT: All = All { code: 0x7e }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_SUBSTR: All = All {code: 0x7f}; + pub const OP_SUBSTR: All = All { code: 0x7f }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_LEFT: All = All {code: 0x80}; + pub const OP_LEFT: All = All { code: 0x80 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_RIGHT: All = All {code: 0x81}; + pub const OP_RIGHT: All = All { code: 0x81 }; /// Pushes the length of the top stack item onto the stack. - pub const OP_SIZE: All = All {code: 0x82}; + pub const OP_SIZE: All = All { code: 0x82 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_INVERT: All = All {code: 0x83}; + pub const OP_INVERT: All = All { code: 0x83 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_AND: All = All {code: 0x84}; + pub const OP_AND: All = All { code: 0x84 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_OR: All = All {code: 0x85}; + pub const OP_OR: All = All { code: 0x85 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_XOR: All = All {code: 0x86}; + pub const OP_XOR: All = All { code: 0x86 }; /// Pushes 1 if the inputs are exactly equal, 0 otherwise. - pub const OP_EQUAL: All = All {code: 0x87}; + pub const OP_EQUAL: All = All { code: 0x87 }; /// Returns success if the inputs are exactly equal, failure otherwise. - pub const OP_EQUALVERIFY: All = All {code: 0x88}; + pub const OP_EQUALVERIFY: All = All { code: 0x88 }; /// Synonym for OP_RETURN. - pub const OP_RESERVED1: All = All {code: 0x89}; + pub const OP_RESERVED1: All = All { code: 0x89 }; /// Synonym for OP_RETURN. - pub const OP_RESERVED2: All = All {code: 0x8a}; + pub const OP_RESERVED2: All = All { code: 0x8a }; /// Increment the top stack element in place. - pub const OP_1ADD: All = All {code: 0x8b}; + pub const OP_1ADD: All = All { code: 0x8b }; /// Decrement the top stack element in place. - pub const OP_1SUB: All = All {code: 0x8c}; + pub const OP_1SUB: All = All { code: 0x8c }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_2MUL: All = All {code: 0x8d}; + pub const OP_2MUL: All = All { code: 0x8d }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_2DIV: All = All {code: 0x8e}; + pub const OP_2DIV: All = All { code: 0x8e }; /// Multiply the top stack item by -1 in place. - pub const OP_NEGATE: All = All {code: 0x8f}; + pub const OP_NEGATE: All = All { code: 0x8f }; /// Absolute value the top stack item in place. - pub const OP_ABS: All = All {code: 0x90}; + pub const OP_ABS: All = All { code: 0x90 }; /// Map 0 to 1 and everything else to 0, in place. - pub const OP_NOT: All = All {code: 0x91}; + pub const OP_NOT: All = All { code: 0x91 }; /// Map 0 to 0 and everything else to 1, in place. - pub const OP_0NOTEQUAL: All = All {code: 0x92}; + pub const OP_0NOTEQUAL: All = All { code: 0x92 }; /// Pop two stack items and push their sum. - pub const OP_ADD: All = All {code: 0x93}; + pub const OP_ADD: All = All { code: 0x93 }; /// Pop two stack items and push the second minus the top. - pub const OP_SUB: All = All {code: 0x94}; + pub const OP_SUB: All = All { code: 0x94 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_MUL: All = All {code: 0x95}; + pub const OP_MUL: All = All { code: 0x95 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_DIV: All = All {code: 0x96}; + pub const OP_DIV: All = All { code: 0x96 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_MOD: All = All {code: 0x97}; + pub const OP_MOD: All = All { code: 0x97 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_LSHIFT: All = All {code: 0x98}; + pub const OP_LSHIFT: All = All { code: 0x98 }; /// Fail the script unconditionally, does not even need to be executed. - pub const OP_RSHIFT: All = All {code: 0x99}; + pub const OP_RSHIFT: All = All { code: 0x99 }; /// Pop the top two stack items and push 1 if both are nonzero, else push 0. - pub const OP_BOOLAND: All = All {code: 0x9a}; + pub const OP_BOOLAND: All = All { code: 0x9a }; /// Pop the top two stack items and push 1 if either is nonzero, else push 0. - pub const OP_BOOLOR: All = All {code: 0x9b}; + pub const OP_BOOLOR: All = All { code: 0x9b }; /// Pop the top two stack items and push 1 if both are numerically equal, else push 0. - pub const OP_NUMEQUAL: All = All {code: 0x9c}; + pub const OP_NUMEQUAL: All = All { code: 0x9c }; /// Pop the top two stack items and return success if both are numerically equal, else return failure. - pub const OP_NUMEQUALVERIFY: All = All {code: 0x9d}; + pub const OP_NUMEQUALVERIFY: All = All { code: 0x9d }; /// Pop the top two stack items and push 0 if both are numerically equal, else push 1. - pub const OP_NUMNOTEQUAL: All = All {code: 0x9e}; + pub const OP_NUMNOTEQUAL: All = All { code: 0x9e }; /// Pop the top two items; push 1 if the second is less than the top, 0 otherwise. - pub const OP_LESSTHAN : All = All {code: 0x9f}; + pub const OP_LESSTHAN: All = All { code: 0x9f }; /// Pop the top two items; push 1 if the second is greater than the top, 0 otherwise. - pub const OP_GREATERTHAN : All = All {code: 0xa0}; + pub const OP_GREATERTHAN: All = All { code: 0xa0 }; /// Pop the top two items; push 1 if the second is <= the top, 0 otherwise. - pub const OP_LESSTHANOREQUAL : All = All {code: 0xa1}; + pub const OP_LESSTHANOREQUAL: All = All { code: 0xa1 }; /// Pop the top two items; push 1 if the second is >= the top, 0 otherwise. - pub const OP_GREATERTHANOREQUAL : All = All {code: 0xa2}; + pub const OP_GREATERTHANOREQUAL: All = All { code: 0xa2 }; /// Pop the top two items; push the smaller. - pub const OP_MIN: All = All {code: 0xa3}; + pub const OP_MIN: All = All { code: 0xa3 }; /// Pop the top two items; push the larger. - pub const OP_MAX: All = All {code: 0xa4}; + pub const OP_MAX: All = All { code: 0xa4 }; /// Pop the top three items; if the top is >= the second and < the third, push 1, otherwise push 0. - pub const OP_WITHIN: All = All {code: 0xa5}; + pub const OP_WITHIN: All = All { code: 0xa5 }; /// Pop the top stack item and push its RIPEMD160 hash. - pub const OP_RIPEMD160: All = All {code: 0xa6}; + pub const OP_RIPEMD160: All = All { code: 0xa6 }; /// Pop the top stack item and push its SHA1 hash. - pub const OP_SHA1: All = All {code: 0xa7}; + pub const OP_SHA1: All = All { code: 0xa7 }; /// Pop the top stack item and push its SHA256 hash. - pub const OP_SHA256: All = All {code: 0xa8}; + pub const OP_SHA256: All = All { code: 0xa8 }; /// Pop the top stack item and push its RIPEMD(SHA256) hash. - pub const OP_HASH160: All = All {code: 0xa9}; + pub const OP_HASH160: All = All { code: 0xa9 }; /// Pop the top stack item and push its SHA256(SHA256) hash. - pub const OP_HASH256: All = All {code: 0xaa}; + pub const OP_HASH256: All = All { code: 0xaa }; /// Ignore this and everything preceding when deciding what to sign when signature-checking. - pub const OP_CODESEPARATOR: All = All {code: 0xab}; + pub const OP_CODESEPARATOR: All = All { code: 0xab }; /// pushing 1/0 for success/failure. - pub const OP_CHECKSIG: All = All {code: 0xac}; + pub const OP_CHECKSIG: All = All { code: 0xac }; /// returning success/failure. - pub const OP_CHECKSIGVERIFY: All = All {code: 0xad}; + pub const OP_CHECKSIGVERIFY: All = All { code: 0xad }; /// Pop N, N pubkeys, M, M signatures, a dummy (due to bug in reference code), and verify that all M signatures are valid. /// Push 1 for "all valid", 0 otherwise. - pub const OP_CHECKMULTISIG: All = All {code: 0xae}; + pub const OP_CHECKMULTISIG: All = All { code: 0xae }; /// Like the above but return success/failure. - pub const OP_CHECKMULTISIGVERIFY: All = All {code: 0xaf}; + pub const OP_CHECKMULTISIGVERIFY: All = All { code: 0xaf }; /// Does nothing. - pub const OP_NOP1: All = All {code: 0xb0}; + pub const OP_NOP1: All = All { code: 0xb0 }; /// - pub const OP_CLTV: All = All {code: 0xb1}; + pub const OP_CLTV: All = All { code: 0xb1 }; /// - pub const OP_CSV: All = All {code: 0xb2}; + pub const OP_CSV: All = All { code: 0xb2 }; /// Does nothing. - pub const OP_NOP4: All = All {code: 0xb3}; + pub const OP_NOP4: All = All { code: 0xb3 }; /// Does nothing. - pub const OP_NOP5: All = All {code: 0xb4}; + pub const OP_NOP5: All = All { code: 0xb4 }; /// Does nothing. - pub const OP_NOP6: All = All {code: 0xb5}; + pub const OP_NOP6: All = All { code: 0xb5 }; /// Does nothing. - pub const OP_NOP7: All = All {code: 0xb6}; + pub const OP_NOP7: All = All { code: 0xb6 }; /// Does nothing. - pub const OP_NOP8: All = All {code: 0xb7}; + pub const OP_NOP8: All = All { code: 0xb7 }; /// Does nothing. - pub const OP_NOP9: All = All {code: 0xb8}; + pub const OP_NOP9: All = All { code: 0xb8 }; /// Does nothing. - pub const OP_NOP10: All = All {code: 0xb9}; + pub const OP_NOP10: All = All { code: 0xb9 }; // Every other opcode acts as OP_RETURN /// OP_CHECKSIGADD post tapscript. - pub const OP_CHECKSIGADD: All = All {code: 0xba}; + pub const OP_CHECKSIGADD: All = All { code: 0xba }; /// Synonym for OP_RETURN. - pub const OP_RETURN_187: All = All {code: 0xbb}; + pub const OP_RETURN_187: All = All { code: 0xbb }; /// Synonym for OP_RETURN. - pub const OP_RETURN_188: All = All {code: 0xbc}; + pub const OP_RETURN_188: All = All { code: 0xbc }; /// Synonym for OP_RETURN. - pub const OP_RETURN_189: All = All {code: 0xbd}; + pub const OP_RETURN_189: All = All { code: 0xbd }; /// Synonym for OP_RETURN. - pub const OP_RETURN_190: All = All {code: 0xbe}; + pub const OP_RETURN_190: All = All { code: 0xbe }; /// Synonym for OP_RETURN. - pub const OP_RETURN_191: All = All {code: 0xbf}; + pub const OP_RETURN_191: All = All { code: 0xbf }; /// Synonym for OP_RETURN. - pub const OP_RETURN_192: All = All {code: 0xc0}; + pub const OP_RETURN_192: All = All { code: 0xc0 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_193: All = All {code: 0xc1}; + pub const OP_RETURN_193: All = All { code: 0xc1 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_194: All = All {code: 0xc2}; + pub const OP_RETURN_194: All = All { code: 0xc2 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_195: All = All {code: 0xc3}; + pub const OP_RETURN_195: All = All { code: 0xc3 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_196: All = All {code: 0xc4}; + pub const OP_RETURN_196: All = All { code: 0xc4 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_197: All = All {code: 0xc5}; + pub const OP_RETURN_197: All = All { code: 0xc5 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_198: All = All {code: 0xc6}; + pub const OP_RETURN_198: All = All { code: 0xc6 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_199: All = All {code: 0xc7}; + pub const OP_RETURN_199: All = All { code: 0xc7 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_200: All = All {code: 0xc8}; + pub const OP_RETURN_200: All = All { code: 0xc8 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_201: All = All {code: 0xc9}; + pub const OP_RETURN_201: All = All { code: 0xc9 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_202: All = All {code: 0xca}; + pub const OP_RETURN_202: All = All { code: 0xca }; /// Synonym for OP_RETURN. - pub const OP_RETURN_203: All = All {code: 0xcb}; + pub const OP_RETURN_203: All = All { code: 0xcb }; /// Synonym for OP_RETURN. - pub const OP_RETURN_204: All = All {code: 0xcc}; + pub const OP_RETURN_204: All = All { code: 0xcc }; /// Synonym for OP_RETURN. - pub const OP_RETURN_205: All = All {code: 0xcd}; + pub const OP_RETURN_205: All = All { code: 0xcd }; /// Synonym for OP_RETURN. - pub const OP_RETURN_206: All = All {code: 0xce}; + pub const OP_RETURN_206: All = All { code: 0xce }; /// Synonym for OP_RETURN. - pub const OP_RETURN_207: All = All {code: 0xcf}; + pub const OP_RETURN_207: All = All { code: 0xcf }; /// Synonym for OP_RETURN. - pub const OP_RETURN_208: All = All {code: 0xd0}; + pub const OP_RETURN_208: All = All { code: 0xd0 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_209: All = All {code: 0xd1}; + pub const OP_RETURN_209: All = All { code: 0xd1 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_210: All = All {code: 0xd2}; + pub const OP_RETURN_210: All = All { code: 0xd2 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_211: All = All {code: 0xd3}; + pub const OP_RETURN_211: All = All { code: 0xd3 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_212: All = All {code: 0xd4}; + pub const OP_RETURN_212: All = All { code: 0xd4 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_213: All = All {code: 0xd5}; + pub const OP_RETURN_213: All = All { code: 0xd5 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_214: All = All {code: 0xd6}; + pub const OP_RETURN_214: All = All { code: 0xd6 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_215: All = All {code: 0xd7}; + pub const OP_RETURN_215: All = All { code: 0xd7 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_216: All = All {code: 0xd8}; + pub const OP_RETURN_216: All = All { code: 0xd8 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_217: All = All {code: 0xd9}; + pub const OP_RETURN_217: All = All { code: 0xd9 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_218: All = All {code: 0xda}; + pub const OP_RETURN_218: All = All { code: 0xda }; /// Synonym for OP_RETURN. - pub const OP_RETURN_219: All = All {code: 0xdb}; + pub const OP_RETURN_219: All = All { code: 0xdb }; /// Synonym for OP_RETURN. - pub const OP_RETURN_220: All = All {code: 0xdc}; + pub const OP_RETURN_220: All = All { code: 0xdc }; /// Synonym for OP_RETURN. - pub const OP_RETURN_221: All = All {code: 0xdd}; + pub const OP_RETURN_221: All = All { code: 0xdd }; /// Synonym for OP_RETURN. - pub const OP_RETURN_222: All = All {code: 0xde}; + pub const OP_RETURN_222: All = All { code: 0xde }; /// Synonym for OP_RETURN. - pub const OP_RETURN_223: All = All {code: 0xdf}; + pub const OP_RETURN_223: All = All { code: 0xdf }; /// Synonym for OP_RETURN. - pub const OP_RETURN_224: All = All {code: 0xe0}; + pub const OP_RETURN_224: All = All { code: 0xe0 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_225: All = All {code: 0xe1}; + pub const OP_RETURN_225: All = All { code: 0xe1 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_226: All = All {code: 0xe2}; + pub const OP_RETURN_226: All = All { code: 0xe2 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_227: All = All {code: 0xe3}; + pub const OP_RETURN_227: All = All { code: 0xe3 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_228: All = All {code: 0xe4}; + pub const OP_RETURN_228: All = All { code: 0xe4 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_229: All = All {code: 0xe5}; + pub const OP_RETURN_229: All = All { code: 0xe5 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_230: All = All {code: 0xe6}; + pub const OP_RETURN_230: All = All { code: 0xe6 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_231: All = All {code: 0xe7}; + pub const OP_RETURN_231: All = All { code: 0xe7 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_232: All = All {code: 0xe8}; + pub const OP_RETURN_232: All = All { code: 0xe8 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_233: All = All {code: 0xe9}; + pub const OP_RETURN_233: All = All { code: 0xe9 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_234: All = All {code: 0xea}; + pub const OP_RETURN_234: All = All { code: 0xea }; /// Synonym for OP_RETURN. - pub const OP_RETURN_235: All = All {code: 0xeb}; + pub const OP_RETURN_235: All = All { code: 0xeb }; /// Synonym for OP_RETURN. - pub const OP_RETURN_236: All = All {code: 0xec}; + pub const OP_RETURN_236: All = All { code: 0xec }; /// Synonym for OP_RETURN. - pub const OP_RETURN_237: All = All {code: 0xed}; + pub const OP_RETURN_237: All = All { code: 0xed }; /// Synonym for OP_RETURN. - pub const OP_RETURN_238: All = All {code: 0xee}; + pub const OP_RETURN_238: All = All { code: 0xee }; /// Synonym for OP_RETURN. - pub const OP_RETURN_239: All = All {code: 0xef}; + pub const OP_RETURN_239: All = All { code: 0xef }; /// Synonym for OP_RETURN. - pub const OP_RETURN_240: All = All {code: 0xf0}; + pub const OP_RETURN_240: All = All { code: 0xf0 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_241: All = All {code: 0xf1}; + pub const OP_RETURN_241: All = All { code: 0xf1 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_242: All = All {code: 0xf2}; + pub const OP_RETURN_242: All = All { code: 0xf2 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_243: All = All {code: 0xf3}; + pub const OP_RETURN_243: All = All { code: 0xf3 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_244: All = All {code: 0xf4}; + pub const OP_RETURN_244: All = All { code: 0xf4 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_245: All = All {code: 0xf5}; + pub const OP_RETURN_245: All = All { code: 0xf5 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_246: All = All {code: 0xf6}; + pub const OP_RETURN_246: All = All { code: 0xf6 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_247: All = All {code: 0xf7}; + pub const OP_RETURN_247: All = All { code: 0xf7 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_248: All = All {code: 0xf8}; + pub const OP_RETURN_248: All = All { code: 0xf8 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_249: All = All {code: 0xf9}; + pub const OP_RETURN_249: All = All { code: 0xf9 }; /// Synonym for OP_RETURN. - pub const OP_RETURN_250: All = All {code: 0xfa}; + pub const OP_RETURN_250: All = All { code: 0xfa }; /// Synonym for OP_RETURN. - pub const OP_RETURN_251: All = All {code: 0xfb}; + pub const OP_RETURN_251: All = All { code: 0xfb }; /// Synonym for OP_RETURN. - pub const OP_RETURN_252: All = All {code: 0xfc}; + pub const OP_RETURN_252: All = All { code: 0xfc }; /// Synonym for OP_RETURN. - pub const OP_RETURN_253: All = All {code: 0xfd}; + pub const OP_RETURN_253: All = All { code: 0xfd }; /// Synonym for OP_RETURN. - pub const OP_RETURN_254: All = All {code: 0xfe}; + pub const OP_RETURN_254: All = All { code: 0xfe }; /// Synonym for OP_RETURN. - pub const OP_INVALIDOPCODE: All = All {code: 0xff}; + pub const OP_INVALIDOPCODE: All = All { code: 0xff }; } impl fmt::Debug for All { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("OP_")?; match *self { - All {code: x} if x <= 75 => write!(f, "PUSHBYTES_{}", self.code), + All { code: x } if x <= 75 => write!(f, "PUSHBYTES_{}", self.code), all::OP_PUSHDATA1 => write!(f, "PUSHDATA1"), all::OP_PUSHDATA2 => write!(f, "PUSHDATA2"), all::OP_PUSHDATA4 => write!(f, "PUSHDATA4"), all::OP_PUSHNUM_NEG1 => write!(f, "PUSHNUM_NEG1"), all::OP_RESERVED => write!(f, "RESERVED"), - All {code: x} if x >= all::OP_PUSHNUM_1.code && x <= all::OP_PUSHNUM_16.code => write!(f, "PUSHNUM_{}", x - all::OP_PUSHNUM_1.code + 1), + All { code: x } if x >= all::OP_PUSHNUM_1.code && x <= all::OP_PUSHNUM_16.code => { + write!(f, "PUSHNUM_{}", x - all::OP_PUSHNUM_1.code + 1) + } all::OP_NOP => write!(f, "NOP"), all::OP_VER => write!(f, "VER"), all::OP_IF => write!(f, "IF"), @@ -651,10 +655,12 @@ impl fmt::Debug for All { all::OP_CHECKMULTISIGVERIFY => write!(f, "CHECKMULTISIGVERIFY"), all::OP_CLTV => write!(f, "CLTV"), all::OP_CSV => write!(f, "CSV"), - All {code: x} if x >= all::OP_NOP1.code && x <= all::OP_NOP10.code => write!(f, "NOP{}", x - all::OP_NOP1.code + 1), + All { code: x } if x >= all::OP_NOP1.code && x <= all::OP_NOP10.code => { + write!(f, "NOP{}", x - all::OP_NOP1.code + 1) + } all::OP_INVALIDOPCODE => write!(f, "INVALIDOPCODE"), all::OP_CHECKSIGADD => write!(f, "CHECKSIGADD"), - All {code: x} => write!(f, "RETURN_{}", x), + All { code: x } => write!(f, "RETURN_{}", x), } } } @@ -681,23 +687,39 @@ impl All { (OP_VERIF, _) | (OP_VERNOTIF, _) | (OP_INVALIDOPCODE, _) => Class::IllegalOp, // 15 opcodes illegal in Legacy context - (OP_CAT, ctx) | (OP_SUBSTR, ctx) - | (OP_LEFT, ctx) | (OP_RIGHT, ctx) + (OP_CAT, ctx) + | (OP_SUBSTR, ctx) + | (OP_LEFT, ctx) + | (OP_RIGHT, ctx) | (OP_INVERT, ctx) - | (OP_AND, ctx) | (OP_OR, ctx) | (OP_XOR, ctx) - | (OP_2MUL, ctx) | (OP_2DIV, ctx) - | (OP_MUL, ctx) | (OP_DIV, ctx) | (OP_MOD, ctx) - | (OP_LSHIFT, ctx) | (OP_RSHIFT, ctx) if ctx == ClassifyContext::Legacy => Class::IllegalOp, + | (OP_AND, ctx) + | (OP_OR, ctx) + | (OP_XOR, ctx) + | (OP_2MUL, ctx) + | (OP_2DIV, ctx) + | (OP_MUL, ctx) + | (OP_DIV, ctx) + | (OP_MOD, ctx) + | (OP_LSHIFT, ctx) + | (OP_RSHIFT, ctx) + if ctx == ClassifyContext::Legacy => + { + Class::IllegalOp + } // 87 opcodes of SuccessOp class only in TapScript context (op, ClassifyContext::TapScript) - if op.code == 80 || op.code == 98 || - (op.code >= 126 && op.code <= 129) || - (op.code >= 131 && op.code <= 134) || - (op.code >= 137 && op.code <= 138) || - (op.code >= 141 && op.code <= 142) || - (op.code >= 149 && op.code <= 153) || - (op.code >= 187 && op.code <= 254) => Class::SuccessOp, + if op.code == 80 + || op.code == 98 + || (op.code >= 126 && op.code <= 129) + || (op.code >= 131 && op.code <= 134) + || (op.code >= 137 && op.code <= 138) + || (op.code >= 141 && op.code <= 142) + || (op.code >= 149 && op.code <= 153) + || (op.code >= 187 && op.code <= 254) => + { + Class::SuccessOp + } // 11 opcodes of NoOp class (OP_NOP, _) => Class::NoOp, @@ -707,9 +729,11 @@ impl All { (OP_RETURN, _) => Class::ReturnOp, // 4 opcodes operating equally to `OP_RETURN` only in Legacy context - (OP_RESERVED, ctx) - | (OP_RESERVED1, ctx) | (OP_RESERVED2, ctx) - | (OP_VER, ctx) if ctx == ClassifyContext::Legacy => Class::ReturnOp, + (OP_RESERVED, ctx) | (OP_RESERVED1, ctx) | (OP_RESERVED2, ctx) | (OP_VER, ctx) + if ctx == ClassifyContext::Legacy => + { + Class::ReturnOp + } // 71 opcodes operating equally to `OP_RETURN` only in Legacy context (op, ClassifyContext::Legacy) if op.code >= OP_CHECKSIGADD.code => Class::ReturnOp, @@ -724,7 +748,7 @@ impl All { // 16 opcodes of PushNum class (op, _) if op.code >= OP_PUSHNUM_1.code && op.code <= OP_PUSHNUM_16.code => { Class::PushNum(1 + self.code as i32 - OP_PUSHNUM_1.code as i32) - }, + } // 76 opcodes of PushBytes class (op, _) if op.code <= OP_PUSHBYTES_75.code => Class::PushBytes(self.code as u32), @@ -744,7 +768,7 @@ impl All { impl From for All { #[inline] fn from(b: u8) -> All { - All {code: b} + All { code: b } } } @@ -786,7 +810,7 @@ pub enum Class { /// Does nothing. NoOp, /// Any opcode not covered above. - Ordinary(Ordinary) + Ordinary(Ordinary), } display_from_debug!(Class); @@ -879,22 +903,31 @@ mod tests { assert_eq!(s1, s2); assert_eq!(s1, stringify!($op)); assert!($unique.insert(s1)); - } + }; } #[test] fn classify_test() { let op174 = all::OP_CHECKMULTISIG; - assert_eq!(op174.classify(ClassifyContext::Legacy), Class::Ordinary(Ordinary::OP_CHECKMULTISIG)); + assert_eq!( + op174.classify(ClassifyContext::Legacy), + Class::Ordinary(Ordinary::OP_CHECKMULTISIG) + ); assert_eq!(op174.classify(ClassifyContext::TapScript), Class::ReturnOp); let op175 = all::OP_CHECKMULTISIGVERIFY; - assert_eq!(op175.classify(ClassifyContext::Legacy), Class::Ordinary(Ordinary::OP_CHECKMULTISIGVERIFY)); + assert_eq!( + op175.classify(ClassifyContext::Legacy), + Class::Ordinary(Ordinary::OP_CHECKMULTISIGVERIFY) + ); assert_eq!(op175.classify(ClassifyContext::TapScript), Class::ReturnOp); let op186 = all::OP_CHECKSIGADD; assert_eq!(op186.classify(ClassifyContext::Legacy), Class::ReturnOp); - assert_eq!(op186.classify(ClassifyContext::TapScript), Class::Ordinary(Ordinary::OP_CHECKSIGADD)); + assert_eq!( + op186.classify(ClassifyContext::TapScript), + Class::Ordinary(Ordinary::OP_CHECKSIGADD) + ); let op187 = all::OP_RETURN_187; assert_eq!(op187.classify(ClassifyContext::Legacy), Class::ReturnOp); @@ -1063,10 +1096,10 @@ mod tests { roundtrip!(unique, OP_NUMEQUAL); roundtrip!(unique, OP_NUMEQUALVERIFY); roundtrip!(unique, OP_NUMNOTEQUAL); - roundtrip!(unique, OP_LESSTHAN ); - roundtrip!(unique, OP_GREATERTHAN ); - roundtrip!(unique, OP_LESSTHANOREQUAL ); - roundtrip!(unique, OP_GREATERTHANOREQUAL ); + roundtrip!(unique, OP_LESSTHAN); + roundtrip!(unique, OP_GREATERTHAN); + roundtrip!(unique, OP_LESSTHANOREQUAL); + roundtrip!(unique, OP_GREATERTHANOREQUAL); roundtrip!(unique, OP_MIN); roundtrip!(unique, OP_MAX); roundtrip!(unique, OP_WITHIN); diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 02e90c1f3b..1305c89458 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -23,28 +23,28 @@ //! This module provides the structures and functions needed to support scripts. //! -use prelude::*; - -use io; -use core::{fmt, default::Default}; +#[cfg(feature = "bitcoinconsensus")] +use core::convert::From; +use core::default::Default; +use core::fmt; use core::ops::Index; -#[cfg(feature = "serde")] use serde; - -use hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash}; +#[cfg(feature = "bitcoinconsensus")] +use bitcoinconsensus; use blockdata::opcodes; use consensus::{encode, Decodable, Encodable}; -use hashes::{Hash, hex}; +use hash_types::{PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash}; +use hashes::{hex, Hash}; use policy::DUST_RELAY_TX_FEE; -#[cfg(feature="bitcoinconsensus")] use bitcoinconsensus; -#[cfg(feature="bitcoinconsensus")] use core::convert::From; -use OutPoint; - -use util::key::PublicKey; +use prelude::*; +use schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; +#[cfg(feature = "serde")] +use serde; use util::address::WitnessVersion; +use util::key::PublicKey; use util::taproot::{LeafVersion, TapBranchHash, TapLeafHash}; -use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; -use schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use {io, OutPoint}; /// A Bitcoin script. #[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -103,7 +103,7 @@ impl fmt::UpperHex for Script { impl hex::FromHex for Script { fn from_byte_iter(iter: I) -> Result where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, + I: Iterator> + ExactSizeIterator + DoubleEndedIterator, { Vec::from_byte_iter(iter).map(|v| Script(Box::<[u8]>::from(v))) } @@ -150,7 +150,7 @@ pub enum Error { /// Can not find the spent output UnknownSpentOutput(OutPoint), /// Can not serialize the spending transaction - SerializationError + SerializationError, } /// A [`bitcoinconsensus::Error`] alias. Exists to enable the compiler to ensure `bitcoinconsensus` @@ -180,7 +180,9 @@ impl fmt::Display for Error { Error::NumericOverflow => "numeric overflow (number on stack larger than 4 bytes)", Error::BitcoinConsensus(ref _n) => "bitcoinconsensus verification failed", Error::UnknownSpentOutput(ref _point) => "unknown spent output Transaction::verify()", - Error::SerializationError => "can not serialize the spending transaction in Transaction::verify()", + Error::SerializationError => { + "can not serialize the spending transaction in Transaction::verify()" + } }; f.write_str(str) } @@ -215,7 +217,9 @@ impl From for Error { } /// Helper to encode an integer in script format fn build_scriptint(n: i64) -> Vec { - if n == 0 { return vec![] } + if n == 0 { + return vec![]; + } let neg = n < 0; @@ -255,11 +259,14 @@ fn build_scriptint(n: i64) -> Vec { /// This is basically a ranged type implementation. pub fn read_scriptint(v: &[u8]) -> Result { let len = v.len(); - if len == 0 { return Ok(0); } - if len > 4 { return Err(Error::NumericOverflow); } + if len == 0 { + return Ok(0); + } + if len > 4 { + return Err(Error::NumericOverflow); + } - let (mut ret, sh) = v.iter() - .fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8)); + let (mut ret, sh) = v.iter().fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8)); if v[len - 1] & 0x80 != 0 { ret &= (1 << (sh - 1)) - 1; ret = -ret; @@ -317,7 +324,9 @@ fn read_uint_iter(data: &mut ::core::slice::Iter<'_, u8>, size: usize) -> Result impl Script { /// Creates a new empty script. - pub fn new() -> Script { Script(vec![].into_boxed_slice()) } + pub fn new() -> Script { + Script(vec![].into_boxed_slice()) + } /// Generates P2PK-type of scriptPubkey. pub fn new_p2pk(pubkey: &PublicKey) -> Script { @@ -371,7 +380,11 @@ impl Script { /// Generates P2TR for script spending path using an internal public key and some optional /// script tree merkle root. - pub fn new_v1_p2tr(secp: &Secp256k1, internal_key: UntweakedPublicKey, merkle_root: Option) -> Script { + pub fn new_v1_p2tr( + secp: &Secp256k1, + internal_key: UntweakedPublicKey, + merkle_root: Option, + ) -> Script { let (output_key, _) = internal_key.tap_tweak(secp, merkle_root); Script::new_witness_program(WitnessVersion::V1, &output_key.serialize()) } @@ -383,10 +396,7 @@ impl Script { /// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script. pub fn new_witness_program(version: WitnessVersion, program: &[u8]) -> Script { - Builder::new() - .push_opcode(version.into()) - .push_slice(program) - .into_script() + Builder::new().push_opcode(version.into()).push_slice(program).into_script() } /// Generates OP_RETURN-type of scriptPubkey for the given data. @@ -408,19 +418,29 @@ impl Script { } /// Returns the length in bytes of the script. - pub fn len(&self) -> usize { self.0.len() } + pub fn len(&self) -> usize { + self.0.len() + } /// Returns whether the script is the empty script. - pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } /// Returns the script data as a byte slice. - pub fn as_bytes(&self) -> &[u8] { &*self.0 } + pub fn as_bytes(&self) -> &[u8] { + &*self.0 + } /// Returns a copy of the script data. - pub fn to_bytes(&self) -> Vec { self.0.clone().into_vec() } + pub fn to_bytes(&self) -> Vec { + self.0.clone().into_vec() + } /// Converts the script into a byte vector. - pub fn into_bytes(self) -> Vec { self.0.into_vec() } + pub fn into_bytes(self) -> Vec { + self.0.into_vec() + } /// Computes the P2SH output corresponding to this redeem script. pub fn to_p2sh(&self) -> Script { @@ -436,7 +456,11 @@ impl Script { /// Computes P2TR output with a given internal key and a single script spending path equal to /// the current script, assuming that the script is a Tapscript. #[inline] - pub fn to_v1_p2tr(&self, secp: &Secp256k1, internal_key: UntweakedPublicKey) -> Script { + pub fn to_v1_p2tr( + &self, + secp: &Secp256k1, + internal_key: UntweakedPublicKey, + ) -> Script { let leaf_hash = TapLeafHash::from_script(&self, LeafVersion::TapScript); let merkle_root = TapBranchHash::from_inner(leaf_hash.into_inner()); Script::new_v1_p2tr(&secp, internal_key, Some(merkle_root)) @@ -445,7 +469,9 @@ impl Script { /// Returns witness version of the script, if any, assuming the script is a `scriptPubkey`. #[inline] pub fn witness_version(&self) -> Option { - self.0.get(0).and_then(|opcode| WitnessVersion::from_opcode(opcodes::All::from(*opcode)).ok()) + self.0 + .get(0) + .and_then(|opcode| WitnessVersion::from_opcode(opcodes::All::from(*opcode)).ok()) } /// Checks whether a script pubkey is a P2SH output. @@ -480,7 +506,7 @@ impl Script { self.0[0] == opcodes::all::OP_PUSHBYTES_33.into_u8() && self.0[34] == opcodes::all::OP_CHECKSIG.into_u8() } - _ => false + _ => false, } } @@ -493,7 +519,7 @@ impl Script { // byte vector pushed is called the "witness program". let script_len = self.0.len(); if script_len < 4 || script_len > 42 { - return false + return false; } let ver_opcode = opcodes::All::from(self.0[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16 let push_opbyte = self.0[1]; // Second byte push opcode 2-40 bytes @@ -529,16 +555,16 @@ impl Script { } /// Check if this is an OP_RETURN output. - pub fn is_op_return (&self) -> bool { + pub fn is_op_return(&self) -> bool { match self.0.first() { Some(b) => *b == opcodes::all::OP_RETURN.into_u8(), - None => false + None => false, } } /// Checks whether a script can be proven to have no satisfying input. pub fn is_provably_unspendable(&self) -> bool { - use blockdata::opcodes::Class::{ReturnOp, IllegalOp}; + use blockdata::opcodes::Class::{IllegalOp, ReturnOp}; match self.0.first() { Some(b) => { @@ -546,7 +572,7 @@ impl Script { let class = first.classify(opcodes::ClassifyContext::Legacy); class == ReturnOp || class == IllegalOp - }, + } None => false, } } @@ -581,24 +607,18 @@ impl Script { /// /// To force minimal pushes, use [`Self::instructions_minimal`]. pub fn instructions(&self) -> Instructions { - Instructions { - data: &self.0[..], - enforce_minimal: false, - } + Instructions { data: &self.0[..], enforce_minimal: false } } /// Iterates over the script in the form of `Instruction`s while enforcing minimal pushes. pub fn instructions_minimal(&self) -> Instructions { - Instructions { - data: &self.0[..], - enforce_minimal: true, - } + Instructions { data: &self.0[..], enforce_minimal: true } } /// Shorthand for [`Self::verify_with_flags`] with flag [bitcoinconsensus::VERIFY_ALL]. - #[cfg(feature="bitcoinconsensus")] + #[cfg(feature = "bitcoinconsensus")] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))] - pub fn verify (&self, index: usize, amount: ::Amount, spending: &[u8]) -> Result<(), Error> { + pub fn verify(&self, index: usize, amount: ::Amount, spending: &[u8]) -> Result<(), Error> { self.verify_with_flags(index, amount, spending, ::bitcoinconsensus::VERIFY_ALL) } @@ -609,10 +629,22 @@ impl Script { /// * `amount` - The amount this script guards. /// * `spending` - The transaction that attempts to spend the output holding this script. /// * `flags` - Verification flags, see [`bitcoinconsensus::VERIFY_ALL`] and similar. - #[cfg(feature="bitcoinconsensus")] + #[cfg(feature = "bitcoinconsensus")] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))] - pub fn verify_with_flags>(&self, index: usize, amount: ::Amount, spending: &[u8], flags: F) -> Result<(), Error> { - Ok(bitcoinconsensus::verify_with_flags (&self.0[..], amount.as_sat(), spending, index, flags.into())?) + pub fn verify_with_flags>( + &self, + index: usize, + amount: ::Amount, + spending: &[u8], + flags: F, + ) -> Result<(), Error> { + Ok(bitcoinconsensus::verify_with_flags( + &self.0[..], + amount.as_sat(), + spending, + index, + flags.into(), + )?) } /// Writes the assembly decoding of the script bytes to the formatter. @@ -648,7 +680,9 @@ impl Script { while let Some(byte) = iter.next() { let opcode = opcodes::All::from(*byte); - let data_len = if let opcodes::Class::PushBytes(n) = opcode.classify(opcodes::ClassifyContext::Legacy) { + let data_len = if let opcodes::Class::PushBytes(n) = + opcode.classify(opcodes::ClassifyContext::Legacy) + { n as usize } else { match opcode { @@ -664,7 +698,7 @@ impl Script { // side effects: may write and break from the loop read_push_data_len!(&mut iter, 4, f) } - _ => 0 + _ => 0, } }; @@ -715,7 +749,9 @@ impl Script { /// Creates a new script from an existing vector. impl From> for Script { - fn from(v: Vec) -> Script { Script(v.into_boxed_slice()) } + fn from(v: Vec) -> Script { + Script(v.into_boxed_slice()) + } } /// A "parsed opcode" which allows iterating over a [`Script`] in a more sensible way. @@ -751,12 +787,13 @@ impl<'a> Iterator for Instructions<'a> { return Some(Err(Error::EarlyEndOfScript)); } if self.enforce_minimal { - if n == 1 && (self.data[1] == 0x81 || (self.data[1] > 0 && self.data[1] <= 16)) { + if n == 1 && (self.data[1] == 0x81 || (self.data[1] > 0 && self.data[1] <= 16)) + { self.data = &[]; return Some(Err(Error::NonMinimalPush)); } } - let ret = Some(Ok(Instruction::PushBytes(&self.data[1..n+1]))); + let ret = Some(Ok(Instruction::PushBytes(&self.data[1..n + 1]))); self.data = &self.data[n + 1..]; ret } @@ -780,7 +817,7 @@ impl<'a> Iterator for Instructions<'a> { self.data = &[]; return Some(Err(Error::NonMinimalPush)); } - let ret = Some(Ok(Instruction::PushBytes(&self.data[2..n+2]))); + let ret = Some(Ok(Instruction::PushBytes(&self.data[2..n + 2]))); self.data = &self.data[n + 2..]; ret } @@ -851,10 +888,14 @@ impl Builder { } /// Returns the length in bytes of the script. - pub fn len(&self) -> usize { self.0.len() } + pub fn len(&self) -> usize { + self.0.len() + } /// Checks whether the script is the empty script. - pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } /// Adds instructions to push an integer onto the stack. Integers are /// encoded as little-endian signed-magnitude numbers, but there are @@ -862,9 +903,7 @@ impl Builder { pub fn push_int(self, data: i64) -> Builder { // We can special-case -1, 1-16 if data == -1 || (data >= 1 && data <= 16) { - let opcode = opcodes::All::from( - (data - 1 + opcodes::OP_TRUE.into_u8() as i64) as u8 - ); + let opcode = opcodes::All::from((data - 1 + opcodes::OP_TRUE.into_u8() as i64) as u8); self.push_opcode(opcode) } // We can also special-case zero @@ -872,7 +911,9 @@ impl Builder { self.push_opcode(opcodes::OP_FALSE) } // Otherwise encode it as data - else { self.push_scriptint(data) } + else { + self.push_scriptint(data) + } } /// Adds instructions to push an integer onto the stack, using the explicit @@ -885,16 +926,18 @@ impl Builder { pub fn push_slice(mut self, data: &[u8]) -> Builder { // Start with a PUSH opcode match data.len() as u64 { - n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => { self.0.push(n as u8); }, + n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => { + self.0.push(n as u8); + } n if n < 0x100 => { self.0.push(opcodes::Ordinary::OP_PUSHDATA1.into_u8()); self.0.push(n as u8); - }, + } n if n < 0x10000 => { self.0.push(opcodes::Ordinary::OP_PUSHDATA2.into_u8()); self.0.push((n % 0x100) as u8); self.0.push((n / 0x100) as u8); - }, + } n if n < 0x100000000 => { self.0.push(opcodes::Ordinary::OP_PUSHDATA4.into_u8()); self.0.push((n % 0x100) as u8); @@ -902,7 +945,7 @@ impl Builder { self.0.push(((n / 0x10000) % 0x100) as u8); self.0.push((n / 0x1000000) as u8); } - _ => panic!("tried to put a 4bn+ sized object into a script!") + _ => panic!("tried to put a 4bn+ sized object into a script!"), } // Then push the raw bytes self.0.extend(data.iter().cloned()); @@ -939,19 +982,19 @@ impl Builder { Some(opcodes::all::OP_EQUAL) => { self.0.pop(); self.push_opcode(opcodes::all::OP_EQUALVERIFY) - }, + } Some(opcodes::all::OP_NUMEQUAL) => { self.0.pop(); self.push_opcode(opcodes::all::OP_NUMEQUALVERIFY) - }, + } Some(opcodes::all::OP_CHECKSIG) => { self.0.pop(); self.push_opcode(opcodes::all::OP_CHECKSIGVERIFY) - }, + } Some(opcodes::all::OP_CHECKMULTISIG) => { self.0.pop(); self.push_opcode(opcodes::all::OP_CHECKMULTISIGVERIFY) - }, + } _ => self.push_opcode(opcodes::all::OP_VERIFY), } } @@ -963,7 +1006,9 @@ impl Builder { } impl Default for Builder { - fn default() -> Builder { Builder::new() } + fn default() -> Builder { + Builder::new() + } } /// Creates a new builder from an existing vector. @@ -986,10 +1031,10 @@ impl<'de> serde::Deserialize<'de> for Script { D: serde::Deserializer<'de>, { use core::fmt::Formatter; + use hashes::hex::FromHex; if deserializer.is_human_readable() { - struct Visitor; impl<'de> serde::de::Visitor<'de> for Visitor { type Value = Script; @@ -1077,15 +1122,14 @@ impl Decodable for Script { mod test { use core::str::FromStr; - use super::*; - use super::build_scriptint; - - use hashes::hex::{FromHex, ToHex}; - use consensus::encode::{deserialize, serialize}; use blockdata::opcodes; + use consensus::encode::{deserialize, serialize}; + use hashes::hex::{FromHex, ToHex}; use util::key::PublicKey; use util::psbt::serialize::Serialize; + use super::{build_scriptint, *}; + #[test] fn script() { let mut comp = vec![]; @@ -1093,33 +1137,61 @@ mod test { assert_eq!(&script[..], &comp[..]); // small ints - script = script.push_int(1); comp.push(81u8); assert_eq!(&script[..], &comp[..]); - script = script.push_int(0); comp.push(0u8); assert_eq!(&script[..], &comp[..]); - script = script.push_int(4); comp.push(84u8); assert_eq!(&script[..], &comp[..]); - script = script.push_int(-1); comp.push(79u8); assert_eq!(&script[..], &comp[..]); + script = script.push_int(1); + comp.push(81u8); + assert_eq!(&script[..], &comp[..]); + script = script.push_int(0); + comp.push(0u8); + assert_eq!(&script[..], &comp[..]); + script = script.push_int(4); + comp.push(84u8); + assert_eq!(&script[..], &comp[..]); + script = script.push_int(-1); + comp.push(79u8); + assert_eq!(&script[..], &comp[..]); // forced scriptint - script = script.push_scriptint(4); comp.extend([1u8, 4].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_scriptint(4); + comp.extend([1u8, 4].iter().cloned()); + assert_eq!(&script[..], &comp[..]); // big ints - script = script.push_int(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(&script[..], &comp[..]); - script = script.push_int(10000); comp.extend([2u8, 16, 39].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_int(17); + comp.extend([1u8, 17].iter().cloned()); + assert_eq!(&script[..], &comp[..]); + script = script.push_int(10000); + comp.extend([2u8, 16, 39].iter().cloned()); + assert_eq!(&script[..], &comp[..]); // notice the sign bit set here, hence the extra zero/128 at the end - script = script.push_int(10000000); comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); assert_eq!(&script[..], &comp[..]); - script = script.push_int(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_int(10000000); + comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); + assert_eq!(&script[..], &comp[..]); + script = script.push_int(-10000000); + comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); + assert_eq!(&script[..], &comp[..]); // data - script = script.push_slice("NRA4VR".as_bytes()); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_slice("NRA4VR".as_bytes()); + comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); + assert_eq!(&script[..], &comp[..]); // keys let keystr = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; let key = PublicKey::from_str(&keystr[2..]).unwrap(); - script = script.push_key(&key); comp.extend(Vec::from_hex(keystr).unwrap().iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_key(&key); + comp.extend(Vec::from_hex(keystr).unwrap().iter().cloned()); + assert_eq!(&script[..], &comp[..]); let keystr = "41042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; let key = PublicKey::from_str(&keystr[2..]).unwrap(); - script = script.push_key(&key); comp.extend(Vec::from_hex(keystr).unwrap().iter().cloned()); assert_eq!(&script[..], &comp[..]); + script = script.push_key(&key); + comp.extend(Vec::from_hex(keystr).unwrap().iter().cloned()); + assert_eq!(&script[..], &comp[..]); // opcodes - script = script.push_opcode(opcodes::all::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]); - script = script.push_opcode(opcodes::all::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]); + script = script.push_opcode(opcodes::all::OP_CHECKSIG); + comp.push(0xACu8); + assert_eq!(&script[..], &comp[..]); + script = script.push_opcode(opcodes::all::OP_CHECKSIG); + comp.push(0xACu8); + assert_eq!(&script[..], &comp[..]); } #[test] @@ -1136,18 +1208,22 @@ mod test { #[test] fn script_builder() { // from txid 3bb5e6434c11fb93f64574af5d116736510717f2c595eb45b52c28e31622dfff which was in my mempool when I wrote the test - let script = Builder::new().push_opcode(opcodes::all::OP_DUP) - .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&Vec::from_hex("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap()) - .push_opcode(opcodes::all::OP_EQUALVERIFY) - .push_opcode(opcodes::all::OP_CHECKSIG) - .into_script(); + let script = Builder::new() + .push_opcode(opcodes::all::OP_DUP) + .push_opcode(opcodes::all::OP_HASH160) + .push_slice(&Vec::from_hex("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap()) + .push_opcode(opcodes::all::OP_EQUALVERIFY) + .push_opcode(opcodes::all::OP_CHECKSIG) + .into_script(); assert_eq!(&format!("{:x}", script), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac"); } #[test] fn script_generators() { - let pubkey = PublicKey::from_str("0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e").unwrap(); + let pubkey = PublicKey::from_str( + "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e", + ) + .unwrap(); assert!(Script::new_p2pk(&pubkey).is_p2pk()); let pubkey_hash = PubkeyHash::hash(&pubkey.inner.serialize()); @@ -1156,9 +1232,10 @@ mod test { let wpubkey_hash = WPubkeyHash::hash(&pubkey.inner.serialize()); assert!(Script::new_v0_p2wpkh(&wpubkey_hash).is_v0_p2wpkh()); - let script = Builder::new().push_opcode(opcodes::all::OP_NUMEQUAL) - .push_verify() - .into_script(); + let script = Builder::new() + .push_opcode(opcodes::all::OP_NUMEQUAL) + .push_verify() + .into_script(); let script_hash = ScriptHash::hash(&script.serialize()); let p2sh = Script::new_p2sh(&script_hash); assert!(p2sh.is_p2sh()); @@ -1171,41 +1248,33 @@ mod test { // Test data are taken from the second output of // 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction - let data = Vec::::from_hex("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a").unwrap(); + let data = Vec::::from_hex( + "aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a", + ) + .unwrap(); let op_return = Script::new_op_return(&data); assert!(op_return.is_op_return()); - assert_eq!(op_return.to_hex(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a"); + assert_eq!( + op_return.to_hex(), + "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a" + ); } #[test] fn script_builder_verify() { - let simple = Builder::new() - .push_verify() - .into_script(); + let simple = Builder::new().push_verify().into_script(); assert_eq!(format!("{:x}", simple), "69"); - let simple2 = Builder::from(vec![]) - .push_verify() - .into_script(); + let simple2 = Builder::from(vec![]).push_verify().into_script(); assert_eq!(format!("{:x}", simple2), "69"); - let nonverify = Builder::new() - .push_verify() - .push_verify() - .into_script(); + let nonverify = Builder::new().push_verify().push_verify().into_script(); assert_eq!(format!("{:x}", nonverify), "6969"); - let nonverify2 = Builder::from(vec![0x69]) - .push_verify() - .into_script(); + let nonverify2 = Builder::from(vec![0x69]).push_verify().into_script(); assert_eq!(format!("{:x}", nonverify2), "6969"); - let equal = Builder::new() - .push_opcode(opcodes::all::OP_EQUAL) - .push_verify() - .into_script(); + let equal = Builder::new().push_opcode(opcodes::all::OP_EQUAL).push_verify().into_script(); assert_eq!(format!("{:x}", equal), "88"); - let equal2 = Builder::from(vec![0x87]) - .push_verify() - .into_script(); + let equal2 = Builder::from(vec![0x87]).push_verify().into_script(); assert_eq!(format!("{:x}", equal2), "88"); let numequal = Builder::new() @@ -1213,9 +1282,7 @@ mod test { .push_verify() .into_script(); assert_eq!(format!("{:x}", numequal), "9d"); - let numequal2 = Builder::from(vec![0x9c]) - .push_verify() - .into_script(); + let numequal2 = Builder::from(vec![0x9c]).push_verify().into_script(); assert_eq!(format!("{:x}", numequal2), "9d"); let checksig = Builder::new() @@ -1223,9 +1290,7 @@ mod test { .push_verify() .into_script(); assert_eq!(format!("{:x}", checksig), "ad"); - let checksig2 = Builder::from(vec![0xac]) - .push_verify() - .into_script(); + let checksig2 = Builder::from(vec![0xac]).push_verify().into_script(); assert_eq!(format!("{:x}", checksig2), "ad"); let checkmultisig = Builder::new() @@ -1233,9 +1298,7 @@ mod test { .push_verify() .into_script(); assert_eq!(format!("{:x}", checkmultisig), "af"); - let checkmultisig2 = Builder::from(vec![0xae]) - .push_verify() - .into_script(); + let checkmultisig2 = Builder::from(vec![0xae]).push_verify().into_script(); assert_eq!(format!("{:x}", checkmultisig2), "af"); let trick_slice = Builder::new() @@ -1243,11 +1306,9 @@ mod test { .push_verify() .into_script(); assert_eq!(format!("{:x}", trick_slice), "01ae69"); - let trick_slice2 = Builder::from(vec![0x01, 0xae]) - .push_verify() - .into_script(); + let trick_slice2 = Builder::from(vec![0x01, 0xae]).push_verify().into_script(); assert_eq!(format!("{:x}", trick_slice2), "01ae69"); - } + } #[test] fn script_serialize() { @@ -1278,7 +1339,10 @@ mod test { fn script_hashes() { let script = hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac"); assert_eq!(script.script_hash().to_hex(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea"); - assert_eq!(script.wscript_hash().to_hex(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324"); + assert_eq!( + script.wscript_hash().to_hex(), + "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324" + ); } #[test] @@ -1287,14 +1351,28 @@ mod test { assert_eq!(hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").is_provably_unspendable(), false); assert_eq!(hex_script!("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").is_provably_unspendable(), false); // p2pkhash - assert_eq!(hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_provably_unspendable(), false); - assert_eq!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_provably_unspendable(), true); + assert_eq!( + hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac") + .is_provably_unspendable(), + false + ); + assert_eq!( + hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87") + .is_provably_unspendable(), + true + ); } #[test] fn op_return_test() { - assert_eq!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_op_return(), true); - assert_eq!(hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_op_return(), false); + assert_eq!( + hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_op_return(), + true + ); + assert_eq!( + hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_op_return(), + false + ); assert_eq!(hex_script!("").is_op_return(), false); } @@ -1312,10 +1390,14 @@ mod test { #[test] fn script_asm() { - assert_eq!(hex_script!("6363636363686868686800").asm(), - "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0"); - assert_eq!(hex_script!("6363636363686868686800").asm(), - "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0"); + assert_eq!( + hex_script!("6363636363686868686800").asm(), + "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0" + ); + assert_eq!( + hex_script!("6363636363686868686800").asm(), + "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0" + ); assert_eq!(hex_script!("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").asm(), "OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG"); // Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1 @@ -1323,20 +1405,13 @@ mod test { "OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae"); // Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a // which triggerred overflow bugs on 32-bit machines in script formatting in the past. - assert_eq!(hex_script!("01").asm(), - "OP_PUSHBYTES_1 "); - assert_eq!(hex_script!("0201").asm(), - "OP_PUSHBYTES_2 "); - assert_eq!(hex_script!("4c").asm(), - ""); - assert_eq!(hex_script!("4c0201").asm(), - "OP_PUSHDATA1 "); - assert_eq!(hex_script!("4d").asm(), - ""); - assert_eq!(hex_script!("4dffff01").asm(), - "OP_PUSHDATA2 "); - assert_eq!(hex_script!("4effffffff01").asm(), - "OP_PUSHDATA4 "); + assert_eq!(hex_script!("01").asm(), "OP_PUSHBYTES_1 "); + assert_eq!(hex_script!("0201").asm(), "OP_PUSHBYTES_2 "); + assert_eq!(hex_script!("4c").asm(), ""); + assert_eq!(hex_script!("4c0201").asm(), "OP_PUSHDATA1 "); + assert_eq!(hex_script!("4d").asm(), ""); + assert_eq!(hex_script!("4dffff01").asm(), "OP_PUSHDATA2 "); + assert_eq!(hex_script!("4effffffff01").asm(), "OP_PUSHDATA4 "); } #[test] @@ -1353,7 +1428,10 @@ mod test { #[test] fn script_p2pk() { - assert!(hex_script!("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").is_p2pk()); + assert!(hex_script!( + "21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac" + ) + .is_p2pk()); assert!(hex_script!("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").is_p2pk()); } @@ -1362,7 +1440,8 @@ mod test { // Test vectors taken from Core tests/data/script_tests.json // bare p2wsh let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac"); - let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); + let expected_witout = + hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); assert!(redeem_script.to_v0_p2wsh().is_v0_p2wsh()); assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout); @@ -1374,7 +1453,8 @@ mod test { // p2sh-p2wsh let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac"); - let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); + let expected_witout = + hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); let expected_out = hex_script!("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887"); assert!(redeem_script.to_p2sh().is_p2sh()); assert!(redeem_script.to_p2sh().to_v0_p2wsh().is_v0_p2wsh()); @@ -1387,19 +1467,21 @@ mod test { let zero = hex_script!("00"); let zeropush = hex_script!("0100"); - let nonminimal = hex_script!("4c0169b2"); // PUSHDATA1 for no reason - let minimal = hex_script!("0169b2"); // minimal - let nonminimal_alt = hex_script!("026900b2"); // non-minimal number but minimal push (should be OK) + let nonminimal = hex_script!("4c0169b2"); // PUSHDATA1 for no reason + let minimal = hex_script!("0169b2"); // minimal + let nonminimal_alt = hex_script!("026900b2"); // non-minimal number but minimal push (should be OK) let v_zero: Result, Error> = zero.instructions_minimal().collect(); let v_zeropush: Result, Error> = zeropush.instructions_minimal().collect(); let v_min: Result, Error> = minimal.instructions_minimal().collect(); let v_nonmin: Result, Error> = nonminimal.instructions_minimal().collect(); - let v_nonmin_alt: Result, Error> = nonminimal_alt.instructions_minimal().collect(); + let v_nonmin_alt: Result, Error> = + nonminimal_alt.instructions_minimal().collect(); let slop_v_min: Result, Error> = minimal.instructions().collect(); let slop_v_nonmin: Result, Error> = nonminimal.instructions().collect(); - let slop_v_nonmin_alt: Result, Error> = nonminimal_alt.instructions().collect(); + let slop_v_nonmin_alt: Result, Error> = + nonminimal_alt.instructions().collect(); assert_eq!(v_zero.unwrap(), vec![Instruction::PushBytes(&[])]); assert_eq!(v_zeropush.unwrap(), vec![Instruction::PushBytes(&[0])]); @@ -1421,7 +1503,7 @@ mod test { assert_eq!(v_nonmin_alt.unwrap(), slop_v_nonmin_alt.unwrap()); } - #[test] + #[test] fn script_ord() { let script_1 = Builder::new().push_slice(&[1, 2, 3, 4]).into_script(); let script_2 = Builder::new().push_int(10).into_script(); @@ -1440,14 +1522,18 @@ mod test { assert!(script_2 > script_1); } - #[test] - #[cfg(feature = "bitcoinconsensus")] - fn test_bitcoinconsensus () { - // a random segwit transaction from the blockchain using native segwit - let spent = Builder::from(Vec::from_hex("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d").unwrap()).into_script(); - let spending = Vec::from_hex("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap(); - spent.verify(0, ::Amount::from_sat(18393430), spending.as_slice()).unwrap(); - } + #[test] + #[cfg(feature = "bitcoinconsensus")] + fn test_bitcoinconsensus() { + // a random segwit transaction from the blockchain using native segwit + let spent = Builder::from( + Vec::from_hex("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d") + .unwrap(), + ) + .into_script(); + let spending = Vec::from_hex("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap(); + spent.verify(0, ::Amount::from_sat(18393430), spending.as_slice()).unwrap(); + } #[test] fn defult_dust_value_tests() { @@ -1512,4 +1598,3 @@ mod test { assert!(read_scriptbool(&v)); } } - diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index d4cd54d6bc..ee5d6e923e 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -23,34 +23,30 @@ //! This module provides the structures and functions needed to support transactions. //! -use prelude::*; - -use io; -use core::{fmt, str, default::Default}; -#[cfg(feature = "std")] use std::error; - -use hashes::{self, Hash, sha256d}; -use hashes::hex::FromHex; +use core::default::Default; +use core::{fmt, str}; +#[cfg(feature = "std")] +use std::error; -use util::endian; use blockdata::constants::WITNESS_SCALE_FACTOR; -#[cfg(feature="bitcoinconsensus")] use blockdata::script; +#[cfg(feature = "bitcoinconsensus")] +use blockdata::script; use blockdata::script::Script; use blockdata::witness::Witness; -use consensus::{encode, Decodable, Encodable}; use consensus::encode::MAX_VEC_SIZE; +use consensus::{encode, Decodable, Encodable}; use hash_types::{Sighash, Txid, Wtxid}; -use VarInt; - +use hashes::hex::FromHex; +use hashes::{self, sha256d, Hash}; +use prelude::*; +use util::endian; #[cfg(doc)] use util::sighash::SchnorrSighashType; +use {io, VarInt}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. const UINT256_ONE: [u8; 32] = [ - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; /// A reference to a transaction output. @@ -75,10 +71,7 @@ impl OutPoint { /// This value is used for coinbase transactions because they don't have any previous outputs. #[inline] pub fn null() -> OutPoint { - OutPoint { - txid: Default::default(), - vout: u32::max_value(), - } + OutPoint { txid: Default::default(), vout: u32::max_value() } } /// Checks if an `OutPoint` is "null". @@ -135,7 +128,9 @@ impl fmt::Display for ParseOutPointError { ParseOutPointError::Vout(ref e) => write!(f, "error parsing vout: {}", e), ParseOutPointError::Format => write!(f, "OutPoint not in : format"), ParseOutPointError::TooLong => write!(f, "vout should be at most 10 digits"), - ParseOutPointError::VoutNotCanonical => write!(f, "no leading zeroes or + allowed in vout part"), + ParseOutPointError::VoutNotCanonical => { + write!(f, "no leading zeroes or + allowed in vout part") + } } } } @@ -143,7 +138,7 @@ impl fmt::Display for ParseOutPointError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for ParseOutPointError { - fn cause(&self) -> Option<&dyn error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { match *self { ParseOutPointError::Txid(ref e) => Some(e), ParseOutPointError::Vout(ref e) => Some(e), @@ -168,7 +163,8 @@ impl ::core::str::FromStr for OutPoint { type Err = ParseOutPointError; fn from_str(s: &str) -> Result { - if s.len() > 75 { // 64 + 1 + 10 + if s.len() > 75 { + // 64 + 1 + 10 return Err(ParseOutPointError::TooLong); } let find = s.find(':'); @@ -181,7 +177,7 @@ impl ::core::str::FromStr for OutPoint { } Ok(OutPoint { txid: Txid::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?, - vout: parse_vout(&s[colon+1..])?, + vout: parse_vout(&s[colon + 1..])?, }) } } @@ -205,7 +201,7 @@ pub struct TxIn { /// Encodable/Decodable, as it is (de)serialized at the end of the full /// Transaction. It *is* (de)serialized with the rest of the TxIn in other /// (de)serialization routines. - pub witness: Witness + pub witness: Witness, } impl Default for TxIn { @@ -226,13 +222,16 @@ pub struct TxOut { /// The value of the output, in satoshis. pub value: u64, /// The script which must be satisfied for the output to be spent. - pub script_pubkey: Script + pub script_pubkey: Script, } // This is used as a "null txout" in consensus signing code. impl Default for TxOut { fn default() -> TxOut { - TxOut { value: 0xffffffffffffffff, script_pubkey: Script::new() } + TxOut { + value: 0xffffffffffffffff, + script_pubkey: Script::new(), + } } } @@ -287,7 +286,15 @@ impl Transaction { let cloned_tx = Transaction { version: self.version, lock_time: self.lock_time, - input: self.input.iter().map(|txin| TxIn { script_sig: Script::new(), witness: Witness::default(), .. *txin }).collect(), + input: self + .input + .iter() + .map(|txin| TxIn { + script_sig: Script::new(), + witness: Witness::default(), + ..*txin + }) + .collect(), output: self.output.clone(), }; cloned_tx.txid().into() @@ -345,7 +352,7 @@ impl Transaction { sighash_type: U, ) -> Result<(), encode::Error> { let sighash_type: u32 = sighash_type.into(); - assert!(input_index < self.input.len()); // Panic on OOB + assert!(input_index < self.input.len()); // Panic on OOB if self.is_invalid_use_of_sighash_single(sighash_type, input_index) { // We cannot correctly handle the SIGHASH_SINGLE bug here because usage of this function @@ -353,10 +360,11 @@ impl Transaction { // handling of the SIGHASH_SINGLE bug is to return the 'one array' - either implement // this behaviour manually or use `signature_hash()`. writer.write(b"[not a transaction] SIGHASH_SINGLE bug")?; - return Ok(()) + return Ok(()); } - let (sighash, anyone_can_pay) = EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag(); + let (sighash, anyone_can_pay) = + EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag(); // Build tx to sign let mut tx = Transaction { @@ -378,8 +386,19 @@ impl Transaction { for (n, input) in self.input.iter().enumerate() { tx.input.push(TxIn { previous_output: input.previous_output, - script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() }, - sequence: if n != input_index && (sighash == EcdsaSighashType::Single || sighash == EcdsaSighashType::None) { 0 } else { input.sequence }, + script_sig: if n == input_index { + script_pubkey.clone() + } else { + Script::new() + }, + sequence: if n != input_index + && (sighash == EcdsaSighashType::Single + || sighash == EcdsaSighashType::None) + { + 0 + } else { + input.sequence + }, witness: Witness::default(), }); } @@ -388,14 +407,16 @@ impl Transaction { tx.output = match sighash { EcdsaSighashType::All => self.output.clone(), EcdsaSighashType::Single => { - let output_iter = self.output.iter() - .take(input_index + 1) // sign all outputs up to and including this one, but erase - .enumerate() // all of them except for this one - .map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() }); + let output_iter = self + .output + .iter() + .take(input_index + 1) // sign all outputs up to and including this one, but erase + .enumerate() // all of them except for this one + .map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() }); output_iter.collect() } EcdsaSighashType::None => vec![], - _ => unreachable!() + _ => unreachable!(), }; // hash the result tx.consensus_encode(&mut writer)?; @@ -431,7 +452,7 @@ impl Transaction { &self, input_index: usize, script_pubkey: &Script, - sighash_u32: u32 + sighash_u32: u32, ) -> Sighash { if self.is_invalid_use_of_sighash_single(sighash_u32, input_index) { return Sighash::from_slice(&UINT256_ONE).expect("const-size array"); @@ -537,7 +558,8 @@ impl Transaction { let mut input_weight = 0; let mut inputs_with_witnesses = 0; for input in &self.input { - input_weight += scale_factor*(32 + 4 + 4 + // outpoint (32+4) + nSequence + input_weight += scale_factor + * (32 + 4 + 4 + // outpoint (32+4) + nSequence VarInt(input.script_sig.len() as u64).len() + input.script_sig.len()); if !input.witness.is_empty() { @@ -563,34 +585,40 @@ impl Transaction { if inputs_with_witnesses == 0 { non_input_size * scale_factor + input_weight } else { - non_input_size * scale_factor + input_weight + self.input.len() - inputs_with_witnesses + 2 + non_input_size * scale_factor + input_weight + self.input.len() - inputs_with_witnesses + + 2 } } /// Shorthand for [`Self::verify_with_flags`] with flag [`bitcoinconsensus::VERIFY_ALL`]. - #[cfg(feature="bitcoinconsensus")] + #[cfg(feature = "bitcoinconsensus")] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))] pub fn verify(&self, spent: S) -> Result<(), script::Error> where - S: FnMut(&OutPoint) -> Option + S: FnMut(&OutPoint) -> Option, { self.verify_with_flags(spent, ::bitcoinconsensus::VERIFY_ALL) } /// Verify that this transaction is able to spend its inputs. /// The `spent` closure should not return the same [`TxOut`] twice! - #[cfg(feature="bitcoinconsensus")] + #[cfg(feature = "bitcoinconsensus")] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))] pub fn verify_with_flags(&self, mut spent: S, flags: F) -> Result<(), script::Error> where S: FnMut(&OutPoint) -> Option, - F: Into + F: Into, { let tx = encode::serialize(&*self); let flags: u32 = flags.into(); for (idx, input) in self.input.iter().enumerate() { if let Some(output) = spent(&input.previous_output) { - output.script_pubkey.verify_with_flags(idx, ::Amount::from_sat(output.value), tx.as_slice(), flags)?; + output.script_pubkey.verify_with_flags( + idx, + ::Amount::from_sat(output.value), + tx.as_slice(), + flags, + )?; } else { return Err(script::Error::UnknownSpentOutput(input.previous_output.clone())); } @@ -746,20 +774,20 @@ pub type SigHashType = EcdsaSighashType; #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum EcdsaSighashType { /// 0x1: Sign all outputs. - All = 0x01, + All = 0x01, /// 0x2: Sign no outputs --- anyone can choose the destination. - None = 0x02, + None = 0x02, /// 0x3: Sign the output whose index matches this input's index. If none exists, /// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`. /// (This rule is probably an unintentional C++ism, but it's consensus so we have /// to follow it.) - Single = 0x03, + Single = 0x03, /// 0x81: Sign all outputs but only this input. - AllPlusAnyoneCanPay = 0x81, + AllPlusAnyoneCanPay = 0x81, /// 0x82: Sign no outputs and only this input. - NonePlusAnyoneCanPay = 0x82, + NonePlusAnyoneCanPay = 0x82, /// 0x83: Sign one output and only this input (see `Single` for what "one output" means). - SinglePlusAnyoneCanPay = 0x83 + SinglePlusAnyoneCanPay = 0x83, } serde_string_impl!(EcdsaSighashType, "a EcdsaSighashType data"); @@ -802,12 +830,12 @@ impl EcdsaSighashType { EcdsaSighashType::Single => (EcdsaSighashType::Single, false), EcdsaSighashType::AllPlusAnyoneCanPay => (EcdsaSighashType::All, true), EcdsaSighashType::NonePlusAnyoneCanPay => (EcdsaSighashType::None, true), - EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true) + EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true), } } /// Creates a [`EcdsaSighashType`] from a raw `u32`. - #[deprecated(since="0.28.0", note="please use `from_consensus`")] + #[deprecated(since = "0.28.0", note = "please use `from_consensus`")] pub fn from_u32_consensus(n: u32) -> EcdsaSighashType { EcdsaSighashType::from_consensus(n) } @@ -837,12 +865,12 @@ impl EcdsaSighashType { 0x83 => EcdsaSighashType::SinglePlusAnyoneCanPay, // catchalls x if x & 0x80 == 0x80 => EcdsaSighashType::AllPlusAnyoneCanPay, - _ => EcdsaSighashType::All + _ => EcdsaSighashType::All, } } /// Creates a [`EcdsaSighashType`] from a raw `u32`. - #[deprecated(since="0.28.0", note="please use `from_standard`")] + #[deprecated(since = "0.28.0", note = "please use `from_standard`")] pub fn from_u32_standard(n: u32) -> Result { EcdsaSighashType::from_standard(n) } @@ -861,14 +889,16 @@ impl EcdsaSighashType { 0x81 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay), 0x82 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay), 0x83 => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay), - non_standard => Err(NonStandardSighashType(non_standard)) + non_standard => Err(NonStandardSighashType(non_standard)), } } /// Converts [`EcdsaSighashType`] to a `u32` sighash flag. /// /// The returned value is guaranteed to be a valid according to standardness rules. - pub fn to_u32(self) -> u32 { self as u32 } + pub fn to_u32(self) -> u32 { + self as u32 + } } /// Error returned for failure during parsing one of the sighash types. @@ -892,52 +922,93 @@ impl ::std::error::Error for SighashTypeParseError {} #[cfg(test)] mod tests { - use super::*; - use core::str::FromStr; + use blockdata::constants::WITNESS_SCALE_FACTOR; use blockdata::script::Script; - use consensus::encode::serialize; - use consensus::encode::deserialize; - - use hashes::Hash; - use hashes::hex::FromHex; - + use consensus::encode::{deserialize, serialize}; use hash_types::*; - use super::EcdsaSighashType; + use hashes::hex::FromHex; + use hashes::Hash; use util::sighash::SighashCache; + use super::{EcdsaSighashType, *}; + #[test] fn test_outpoint() { - assert_eq!(OutPoint::from_str("i don't care"), - Err(ParseOutPointError::Format)); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:1:1"), - Err(ParseOutPointError::Format)); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:"), - Err(ParseOutPointError::Format)); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:11111111111"), - Err(ParseOutPointError::TooLong)); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:01"), - Err(ParseOutPointError::VoutNotCanonical)); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"), - Err(ParseOutPointError::VoutNotCanonical)); - assert_eq!(OutPoint::from_str("i don't care:1"), - Err(ParseOutPointError::Txid(Txid::from_hex("i don't care").unwrap_err()))); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"), - Err(ParseOutPointError::Txid(Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X").unwrap_err()))); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"), - Err(ParseOutPointError::Vout(u32::from_str("lol").unwrap_err()))); - - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"), - Ok(OutPoint{ - txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), - vout: 42, - })); - assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"), - Ok(OutPoint{ - txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), - vout: 0, - })); + assert_eq!(OutPoint::from_str("i don't care"), Err(ParseOutPointError::Format)); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:1:1" + ), + Err(ParseOutPointError::Format) + ); + assert_eq!( + OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:"), + Err(ParseOutPointError::Format) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:11111111111" + ), + Err(ParseOutPointError::TooLong) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:01" + ), + Err(ParseOutPointError::VoutNotCanonical) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42" + ), + Err(ParseOutPointError::VoutNotCanonical) + ); + assert_eq!( + OutPoint::from_str("i don't care:1"), + Err(ParseOutPointError::Txid(Txid::from_hex("i don't care").unwrap_err())) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1" + ), + Err(ParseOutPointError::Txid( + Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X") + .unwrap_err() + )) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol" + ), + Err(ParseOutPointError::Vout(u32::from_str("lol").unwrap_err())) + ); + + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42" + ), + Ok(OutPoint { + txid: Txid::from_hex( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + ) + .unwrap(), + vout: 42, + }) + ); + assert_eq!( + OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0" + ), + Ok(OutPoint { + txid: Txid::from_hex( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + ) + .unwrap(), + vout: 0, + }) + ); } #[test] @@ -957,12 +1028,12 @@ mod tests { } #[test] - fn test_is_coinbase () { - use network::constants::Network; + fn test_is_coinbase() { use blockdata::constants; + use network::constants::Network; let genesis = constants::genesis_block(Network::Bitcoin); - assert! (genesis.txdata[0].is_coin_base()); + assert!(genesis.txdata[0].is_coin_base()); let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert!(!tx.is_coin_base()); @@ -980,17 +1051,23 @@ mod tests { assert_eq!(realtx.input.len(), 1); // In particular this one is easy to get backward -- in bitcoin hashes are encoded // as little-endian 256-bit numbers rather than as data strings. - assert_eq!(format!("{:x}", realtx.input[0].previous_output.txid), - "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string()); + assert_eq!( + format!("{:x}", realtx.input[0].previous_output.txid), + "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string() + ); assert_eq!(realtx.input[0].previous_output.vout, 1); assert_eq!(realtx.output.len(), 1); assert_eq!(realtx.lock_time, 0); - assert_eq!(format!("{:x}", realtx.txid()), - "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); - assert_eq!(format!("{:x}", realtx.wtxid()), - "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); - assert_eq!(realtx.weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR); + assert_eq!( + format!("{:x}", realtx.txid()), + "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string() + ); + assert_eq!( + format!("{:x}", realtx.wtxid()), + "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string() + ); + assert_eq!(realtx.weight(), tx_bytes.len() * WITNESS_SCALE_FACTOR); assert_eq!(realtx.size(), tx_bytes.len()); assert_eq!(realtx.vsize(), tx_bytes.len()); assert_eq!(realtx.strippedsize(), tx_bytes.len()); @@ -1014,16 +1091,22 @@ mod tests { assert_eq!(realtx.input.len(), 1); // In particular this one is easy to get backward -- in bitcoin hashes are encoded // as little-endian 256-bit numbers rather than as data strings. - assert_eq!(format!("{:x}", realtx.input[0].previous_output.txid), - "7cac3cf9a112cf04901a51d605058615d56ffe6d04b45270e89d1720ea955859".to_string()); + assert_eq!( + format!("{:x}", realtx.input[0].previous_output.txid), + "7cac3cf9a112cf04901a51d605058615d56ffe6d04b45270e89d1720ea955859".to_string() + ); assert_eq!(realtx.input[0].previous_output.vout, 1); assert_eq!(realtx.output.len(), 1); assert_eq!(realtx.lock_time, 0); - assert_eq!(format!("{:x}", realtx.txid()), - "f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string()); - assert_eq!(format!("{:x}", realtx.wtxid()), - "80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string()); + assert_eq!( + format!("{:x}", realtx.txid()), + "f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string() + ); + assert_eq!( + format!("{:x}", realtx.wtxid()), + "80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string() + ); const EXPECTED_WEIGHT: usize = 442; assert_eq!(realtx.weight(), EXPECTED_WEIGHT); assert_eq!(realtx.size(), tx_bytes.len()); @@ -1038,7 +1121,7 @@ mod tests { // Construct a transaction without the witness data. let mut tx_without_witness = realtx.clone(); tx_without_witness.input.iter_mut().for_each(|input| input.witness.clear()); - assert_eq!(tx_without_witness.weight(), expected_strippedsize*WITNESS_SCALE_FACTOR); + assert_eq!(tx_without_witness.weight(), expected_strippedsize * WITNESS_SCALE_FACTOR); assert_eq!(tx_without_witness.size(), expected_strippedsize); assert_eq!(tx_without_witness.vsize(), expected_strippedsize); assert_eq!(tx_without_witness.strippedsize(), expected_strippedsize); @@ -1079,7 +1162,10 @@ mod tests { let mut tx: Transaction = deserialize(&tx_bytes).unwrap(); let old_ntxid = tx.ntxid(); - assert_eq!(format!("{:x}", old_ntxid), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"); + assert_eq!( + format!("{:x}", old_ntxid), + "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d" + ); // changing sigs does not affect it tx.input[0].script_sig = Script::new(); assert_eq!(old_ntxid, tx.ntxid()); @@ -1123,8 +1209,14 @@ mod tests { ).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); - assert_eq!(format!("{:x}", tx.wtxid()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); - assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); + assert_eq!( + format!("{:x}", tx.wtxid()), + "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4" + ); + assert_eq!( + format!("{:x}", tx.txid()), + "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec" + ); assert_eq!(tx.weight(), 2718); // non-segwit tx from my mempool @@ -1138,8 +1230,14 @@ mod tests { ).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); - assert_eq!(format!("{:x}", tx.wtxid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); - assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); + assert_eq!( + format!("{:x}", tx.wtxid()), + "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd" + ); + assert_eq!( + format!("{:x}", tx.txid()), + "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd" + ); } #[test] @@ -1172,7 +1270,7 @@ mod tests { ("SIGHASH_SINGLE", EcdsaSighashType::Single), ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay), ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay), - ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay) + ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay), ]; for (s, sht) in sighashtypes { assert_eq!(sht.to_string(), s); @@ -1191,7 +1289,10 @@ mod tests { "SigHash_NONE", ]; for s in sht_mistakes { - assert_eq!(EcdsaSighashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s)); + assert_eq!( + EcdsaSighashType::from_str(s).unwrap_err().to_string(), + format!("Unrecognized SIGHASH string '{}'", s) + ); } } @@ -1200,9 +1301,15 @@ mod tests { fn test_sighashtype_standard() { let nonstandard_hashtype = 0x04; // This type is not well defined, by consensus it becomes ALL - assert_eq!(EcdsaSighashType::from_u32_consensus(nonstandard_hashtype), EcdsaSighashType::All); + assert_eq!( + EcdsaSighashType::from_u32_consensus(nonstandard_hashtype), + EcdsaSighashType::All + ); // But it's policy-invalid to use it! - assert_eq!(EcdsaSighashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSighashType(0x04))); + assert_eq!( + EcdsaSighashType::from_u32_standard(nonstandard_hashtype), + Err(NonStandardSighashType(0x04)) + ); } #[test] @@ -1219,7 +1326,7 @@ mod tests { version: 1, lock_time: 0, input: input, - output: output, // TODO: Use Vec::from([TxOut]) once we bump MSRV. + output: output, // TODO: Use Vec::from([TxOut]) once we bump MSRV. }; let script = Script::new(); let got = tx.signature_hash(1, &script, SIGHASH_SINGLE); @@ -1228,7 +1335,13 @@ mod tests { assert_eq!(got, want) } - fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i32, expected_result: &str) { + fn run_test_sighash( + tx: &str, + script: &str, + input_index: usize, + hash_type: i32, + expected_result: &str, + ) { let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap(); let script = Script::from(Vec::from_hex(script).unwrap()); let mut raw_expected = Vec::from_hex(expected_result).unwrap(); @@ -1544,12 +1657,13 @@ mod tests { } #[test] - #[cfg(feature="bitcoinconsensus")] - fn test_transaction_verify () { - use hashes::hex::FromHex; + #[cfg(feature = "bitcoinconsensus")] + fn test_transaction_verify() { use std::collections::HashMap; + use blockdata::script; use blockdata::witness::Witness; + use hashes::hex::FromHex; // a random recent segwit transaction from blockchain using both old and segwit inputs let mut spending: Transaction = deserialize(Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700") @@ -1568,36 +1682,44 @@ mod tests { let mut spent2 = spent.clone(); let mut spent3 = spent.clone(); - spending.verify(|point: &OutPoint| { - if let Some(tx) = spent.remove(&point.txid) { - return tx.output.get(point.vout as usize).cloned(); - } - None - }).unwrap(); + spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent.remove(&point.txid) { + return tx.output.get(point.vout as usize).cloned(); + } + None + }) + .unwrap(); // test that we fail with repeated use of same input let mut double_spending = spending.clone(); let re_use = double_spending.input[0].clone(); double_spending.input.push(re_use); - assert!(double_spending.verify(|point: &OutPoint| { - if let Some(tx) = spent2.remove(&point.txid) { - return tx.output.get(point.vout as usize).cloned(); - } - None - }).is_err()); + assert!(double_spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent2.remove(&point.txid) { + return tx.output.get(point.vout as usize).cloned(); + } + None + }) + .is_err()); // test that we get a failure if we corrupt a signature let mut witness: Vec<_> = spending.input[1].witness.to_vec(); witness[0][10] = 42; spending.input[1].witness = Witness::from_vec(witness); - match spending.verify(|point: &OutPoint| { - if let Some(tx) = spent3.remove(&point.txid) { - return tx.output.get(point.vout as usize).cloned(); - } - None - }).err().unwrap() { - script::Error::BitcoinConsensus(_) => {}, + match spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent3.remove(&point.txid) { + return tx.output.get(point.vout as usize).cloned(); + } + None + }) + .err() + .unwrap() + { + script::Error::BitcoinConsensus(_) => {} _ => panic!("Wrong error type"), } } @@ -1605,11 +1727,12 @@ mod tests { #[cfg(all(test, feature = "unstable"))] mod benches { - use super::Transaction; - use EmptyWrite; use consensus::{deserialize, Encodable}; use hashes::hex::FromHex; use test::{black_box, Bencher}; + use EmptyWrite; + + use super::Transaction; const SOME_TX: &'static str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 3c700007da..d10cf0ccc2 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -7,10 +7,9 @@ use consensus::encode::{Error, MAX_VEC_SIZE}; use consensus::{Decodable, Encodable, WriteExt}; use io::{self, Read, Write}; use prelude::*; -use VarInt; - #[cfg(feature = "serde")] use serde; +use VarInt; /// The Witness is the data used to unlock bitcoins since the [segwit upgrade](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki) /// @@ -90,12 +89,7 @@ impl Decodable for Witness { cursor += element_size; } content.truncate(cursor); - Ok(Witness { - content, - witness_elements, - last, - second_to_last, - }) + Ok(Witness { content, witness_elements, last, second_to_last }) } } } @@ -120,7 +114,6 @@ impl Encodable for Witness { } impl Witness { - /// Create a new empty [`Witness`] pub fn new() -> Self { Witness::default() @@ -130,10 +123,8 @@ impl Witness { pub fn from_vec(vec: Vec>) -> Self { let witness_elements = vec.len(); - let content_size: usize = vec - .iter() - .map(|el| el.len() + VarInt(el.len() as u64).len()) - .sum(); + let content_size: usize = + vec.iter().map(|el| el.len() + VarInt(el.len() as u64).len()).sum(); let mut content = vec![0u8; content_size]; let mut cursor = 0usize; let mut last = 0; @@ -150,12 +141,7 @@ impl Witness { cursor += el.len(); } - Witness { - witness_elements, - content, - last, - second_to_last, - } + Witness { witness_elements, content, last, second_to_last } } /// Convenience method to create an array of byte-arrays from this witness @@ -180,9 +166,7 @@ impl Witness { /// Returns the bytes required when this Witness is consensus encoded pub fn serialized_len(&self) -> usize { - self.iter() - .map(|el| VarInt(el.len() as u64).len() + el.len()) - .sum::() + self.iter().map(|el| VarInt(el.len() as u64).len() + el.len()).sum::() + VarInt(self.witness_elements as u64).len() } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 4c24748b86..e7458c335b 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -27,24 +27,24 @@ //! typically big-endian decimals, etc.) //! -use prelude::*; - -use core::{fmt, mem, u32, convert::From}; -#[cfg(feature = "std")] use std::error; - -use hashes::{sha256d, Hash, sha256}; -use hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; - -use io::{self, Cursor, Read}; +use core::convert::From; +use core::{fmt, mem, u32}; +#[cfg(feature = "std")] +use std::error; -use util::endian; -use util::psbt; -use util::taproot::TapLeafHash; +use blockdata::transaction::{Transaction, TxIn, TxOut}; +use hash_types::{BlockHash, FilterHash, FilterHeader, TxMerkleNode}; use hashes::hex::ToHex; - -use blockdata::transaction::{TxOut, Transaction, TxIn}; +use hashes::{sha256, sha256d, Hash}; +use io::{self, Cursor, Read}; #[cfg(feature = "std")] -use network::{message_blockdata::Inventory, address::{Address, AddrV2Message}}; +use network::{ + address::{AddrV2Message, Address}, + message_blockdata::Inventory, +}; +use prelude::*; +use util::taproot::TapLeafHash; +use util::{endian, psbt}; /// Encoding error #[derive(Debug)] @@ -89,17 +89,21 @@ impl fmt::Display for Error { match *self { Error::Io(ref e) => write!(f, "I/O error: {}", e), Error::Psbt(ref e) => write!(f, "PSBT error: {}", e), - Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, - "unexpected network magic: expected {}, actual {}", e, a), - Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, - "allocation of oversized vector: requested {}, maximum {}", r, m), - Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, - "invalid checksum: expected {}, actual {}", e.to_hex(), a.to_hex()), + Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => { + write!(f, "unexpected network magic: expected {}, actual {}", e, a) + } + Error::OversizedVectorAllocation { requested: ref r, max: ref m } => { + write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m) + } + Error::InvalidChecksum { expected: ref e, actual: ref a } => { + write!(f, "invalid checksum: expected {}, actual {}", e.to_hex(), a.to_hex()) + } Error::NonMinimalVarInt => write!(f, "non-minimal varint"), Error::UnknownNetworkMagic(ref m) => write!(f, "unknown network magic: {}", m), Error::ParseFailed(ref e) => write!(f, "parse failed: {}", e), - Error::UnsupportedSegwitFlag(ref swflag) => write!(f, - "unsupported segwit version: {}", swflag), + Error::UnsupportedSegwitFlag(ref swflag) => { + write!(f, "unsupported segwit version: {}", swflag) + } } } } @@ -107,7 +111,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { match *self { Error::Io(ref e) => Some(e), Error::Psbt(ref e) => Some(e), @@ -172,7 +176,6 @@ pub fn deserialize_partial(data: &[u8]) -> Result<(T, usize), Erro Ok((rv, consumed)) } - /// Extensions of `Write` to encode data as per Bitcoin consensus pub trait WriteExt { /// Output a 64-bit uint @@ -233,7 +236,7 @@ macro_rules! encoder_fn { fn $name(&mut self, v: $val_type) -> Result<(), io::Error> { self.write_all(&endian::$writefn(v)) } - } + }; } macro_rules! decoder_fn { @@ -245,7 +248,7 @@ macro_rules! decoder_fn { self.read_exact(&mut val[..]).map_err(Error::Io)?; Ok(endian::$readfn(&val)) } - } + }; } impl WriteExt for W { @@ -346,14 +349,14 @@ macro_rules! impl_int_encodable { Ok(mem::size_of::<$ty>()) } } - } + }; } -impl_int_encodable!(u8, read_u8, emit_u8); +impl_int_encodable!(u8, read_u8, emit_u8); impl_int_encodable!(u16, read_u16, emit_u16); impl_int_encodable!(u32, read_u32, emit_u32); impl_int_encodable!(u64, read_u64, emit_u64); -impl_int_encodable!(i8, read_i8, emit_i8); +impl_int_encodable!(i8, read_i8, emit_i8); impl_int_encodable!(i16, read_i16, emit_i16); impl_int_encodable!(i32, read_i32, emit_i32); impl_int_encodable!(i64, read_i64, emit_i64); @@ -365,10 +368,10 @@ impl VarInt { #[inline] pub fn len(&self) -> usize { match self.0 { - 0..=0xFC => { 1 } - 0xFD..=0xFFFF => { 3 } - 0x10000..=0xFFFFFFFF => { 5 } - _ => { 9 } + 0..=0xFC => 1, + 0xFD..=0xFFFF => 3, + 0x10000..=0xFFFFFFFF => 5, + _ => 9, } } } @@ -380,22 +383,22 @@ impl Encodable for VarInt { 0..=0xFC => { (self.0 as u8).consensus_encode(s)?; Ok(1) - }, + } 0xFD..=0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s)?; Ok(3) - }, + } 0x10000..=0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s)?; Ok(5) - }, + } _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s)?; Ok(9) - }, + } } } } @@ -429,7 +432,7 @@ impl Decodable for VarInt { Ok(VarInt(x as u64)) } } - n => Ok(VarInt(n as u64)) + n => Ok(VarInt(n as u64)), } } } @@ -489,7 +492,6 @@ impl Decodable for Cow<'static, str> { } } - // Arrays macro_rules! impl_array { ( $size:expr ) => { @@ -535,7 +537,9 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] fn consensus_encode(&self, mut s: S) -> Result { - for c in self.iter() { c.consensus_encode(&mut s)?; } + for c in self.iter() { + c.consensus_encode(&mut s)?; + } Ok(16) } } @@ -562,7 +566,10 @@ macro_rules! impl_vec { .checked_mul(mem::size_of::<$type>()) .ok_or(self::Error::ParseFailed("Invalid length"))?; if byte_size > MAX_VEC_SIZE { - return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) + return Err(self::Error::OversizedVectorAllocation { + requested: byte_size, + max: MAX_VEC_SIZE, + }); } let mut ret = Vec::with_capacity(len as usize); let mut d = d.take(MAX_VEC_SIZE as u64); @@ -572,7 +579,7 @@ macro_rules! impl_vec { Ok(ret) } } - } + }; } impl_vec!(BlockHash); impl_vec!(FilterHash); @@ -585,17 +592,22 @@ impl_vec!(Vec); impl_vec!(u64); impl_vec!(TapLeafHash); -#[cfg(feature = "std")] impl_vec!(Inventory); -#[cfg(feature = "std")] impl_vec!((u32, Address)); -#[cfg(feature = "std")] impl_vec!(AddrV2Message); +#[cfg(feature = "std")] +impl_vec!(Inventory); +#[cfg(feature = "std")] +impl_vec!((u32, Address)); +#[cfg(feature = "std")] +impl_vec!(AddrV2Message); -pub(crate) fn consensus_encode_with_size(data: &[u8], mut s: S) -> Result { +pub(crate) fn consensus_encode_with_size( + data: &[u8], + mut s: S, +) -> Result { let vi_len = VarInt(data.len() as u64).consensus_encode(&mut s)?; s.emit_slice(data)?; Ok(vi_len + data.len()) } - impl Encodable for Vec { #[inline] fn consensus_encode(&self, s: S) -> Result { @@ -608,7 +620,10 @@ impl Decodable for Vec { fn consensus_decode(mut d: D) -> Result { let len = VarInt::consensus_decode(&mut d)?.0 as usize; if len > MAX_VEC_SIZE { - return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) + return Err(self::Error::OversizedVectorAllocation { + requested: len, + max: MAX_VEC_SIZE, + }); } let mut ret = vec![0u8; len]; d.read_slice(&mut ret)?; @@ -630,7 +645,6 @@ impl Decodable for Box<[u8]> { } } - /// Do a double-SHA256 on some data and return the first 4 bytes fn sha2_checksum(data: &[u8]) -> [u8; 4] { let checksum = ::hash(data); @@ -655,7 +669,7 @@ impl Decodable for CheckedData { if len > MAX_VEC_SIZE as u32 { return Err(self::Error::OversizedVectorAllocation { requested: len as usize, - max: MAX_VEC_SIZE + max: MAX_VEC_SIZE, }); } let checksum = <[u8; 4]>::consensus_decode(&mut d)?; @@ -663,10 +677,7 @@ impl Decodable for CheckedData { d.read_slice(&mut ret)?; let expected_checksum = sha2_checksum(&ret); if expected_checksum != checksum { - Err(self::Error::InvalidChecksum { - expected: expected_checksum, - actual: checksum, - }) + Err(self::Error::InvalidChecksum { expected: expected_checksum, actual: checksum }) } else { Ok(CheckedData(ret)) } @@ -772,15 +783,19 @@ impl Decodable for TapLeafHash { // Tests #[cfg(test)] mod tests { - use super::*; - use core::{mem::{self, discriminant}, fmt}; - use super::{deserialize, serialize, Error, CheckedData, VarInt}; - use super::{Transaction, BlockHash, FilterHash, TxMerkleNode, TxOut, TxIn}; - use consensus::{Encodable, deserialize_partial, Decodable}; - use util::endian::{u64_to_array_le, u32_to_array_le, u16_to_array_le}; - use secp256k1::rand::{thread_rng, Rng}; + use core::fmt; + use core::mem::{self, discriminant}; + + use consensus::{deserialize_partial, Decodable, Encodable}; #[cfg(feature = "std")] - use network::{Address, message_blockdata::Inventory}; + use network::{message_blockdata::Inventory, Address}; + use secp256k1::rand::{thread_rng, Rng}; + use util::endian::{u16_to_array_le, u32_to_array_le, u64_to_array_le}; + + use super::{ + deserialize, serialize, BlockHash, CheckedData, Error, FilterHash, Transaction, TxIn, + TxMerkleNode, TxOut, VarInt, *, + }; #[test] fn serialize_int_test() { @@ -823,7 +838,10 @@ mod tests { assert_eq!(serialize(&-256i64), vec![0u8, 255, 255, 255, 255, 255, 255, 255]); assert_eq!(serialize(&-5000i64), vec![120u8, 236, 255, 255, 255, 255, 255, 255]); assert_eq!(serialize(&-500000i64), vec![224u8, 94, 248, 255, 255, 255, 255, 255]); - assert_eq!(serialize(&-723401728380766730i64), vec![246u8, 245, 245, 245, 245, 245, 245, 245]); + assert_eq!( + serialize(&-723401728380766730i64), + vec![246u8, 245, 245, 245, 245, 245, 245, 245] + ); assert_eq!(serialize(&1i64), vec![1u8, 0, 0, 0, 0, 0, 0, 0]); assert_eq!(serialize(&256i64), vec![0u8, 1, 0, 0, 0, 0, 0, 0]); assert_eq!(serialize(&5000i64), vec![136u8, 19, 0, 0, 0, 0, 0, 0]); @@ -838,8 +856,14 @@ mod tests { assert_eq!(serialize(&VarInt(0xFD)), vec![0xFDu8, 0xFD, 0]); assert_eq!(serialize(&VarInt(0xFFF)), vec![0xFDu8, 0xFF, 0xF]); assert_eq!(serialize(&VarInt(0xF0F0F0F)), vec![0xFEu8, 0xF, 0xF, 0xF, 0xF]); - assert_eq!(serialize(&VarInt(0xF0F0F0F0F0E0)), vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0]); - assert_eq!(test_varint_encode(0xFF, &u64_to_array_le(0x100000000)).unwrap(), VarInt(0x100000000)); + assert_eq!( + serialize(&VarInt(0xF0F0F0F0F0E0)), + vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0] + ); + assert_eq!( + test_varint_encode(0xFF, &u64_to_array_le(0x100000000)).unwrap(), + VarInt(0x100000000) + ); assert_eq!(test_varint_encode(0xFE, &u64_to_array_le(0x10000)).unwrap(), VarInt(0x10000)); assert_eq!(test_varint_encode(0xFD, &u64_to_array_le(0xFD)).unwrap(), VarInt(0xFD)); @@ -850,7 +874,7 @@ mod tests { test_varint_len(VarInt(0xFFFF), 3); test_varint_len(VarInt(0x10000), 5); test_varint_len(VarInt(0xFFFFFFFF), 5); - test_varint_len(VarInt(0xFFFFFFFF+1), 9); + test_varint_len(VarInt(0xFFFFFFFF + 1), 9); test_varint_len(VarInt(u64::max_value()), 9); } @@ -863,35 +887,60 @@ mod tests { fn test_varint_encode(n: u8, x: &[u8]) -> Result { let mut input = [0u8; 9]; input[0] = n; - input[1..x.len()+1].copy_from_slice(x); - deserialize_partial::(&input).map(|t|t.0) + input[1..x.len() + 1].copy_from_slice(x); + deserialize_partial::(&input).map(|t| t.0) } #[test] fn deserialize_nonminimal_vec() { // Check the edges for variant int - assert_eq!(discriminant(&test_varint_encode(0xFF, &u64_to_array_le(0x100000000-1)).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFE, &u32_to_array_le(0x10000-1)).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFD, &u16_to_array_le(0xFD-1)).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); + assert_eq!( + discriminant(&test_varint_encode(0xFF, &u64_to_array_le(0x100000000 - 1)).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFE, &u32_to_array_le(0x10000 - 1)).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFD, &u16_to_array_le(0xFD - 1)).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&Error::NonMinimalVarInt) + ); let mut vec_256 = vec![0; 259]; vec_256[0] = 0xfd; @@ -955,12 +1004,18 @@ mod tests { // u64 assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABu64)); - assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), Some(0x99000099CDAB0DA0u64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(0x99000099CDAB0DA0u64) + ); let failure64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); assert!(failure64.is_err()); // TODO: test negative numbers assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABi64)); - assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), Some(-0x66ffff663254f260i64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(-0x66ffff663254f260i64) + ); let failurei64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); assert!(failurei64.is_err()); } @@ -970,13 +1025,18 @@ mod tests { assert_eq!(deserialize(&[3u8, 2, 3, 4]).ok(), Some(vec![2u8, 3, 4])); assert!((deserialize(&[4u8, 2, 3, 4, 5, 6]) as Result, _>).is_err()); // found by cargo fuzz - assert!(deserialize::>(&[0xff,0xff,0xff,0xff,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0xa,0xa,0x3a]).is_err()); + assert!(deserialize::>(&[ + 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0xa, 0xa, 0x3a + ]) + .is_err()); let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, "")); // Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive, // by making sure it fails with IO Error and not an `OversizedVectorAllocation` Error. - let err = deserialize::(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err(); + let err = + deserialize::(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err(); assert_eq!(discriminant(&err), discriminant(&rand_io_err)); test_len_is_max_vec::(); @@ -994,7 +1054,11 @@ mod tests { test_len_is_max_vec::(); } - fn test_len_is_max_vec() where Vec: Decodable, T: fmt::Debug { + fn test_len_is_max_vec() + where + Vec: Decodable, + T: fmt::Debug, + { let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, "")); let varint = VarInt((super::MAX_VEC_SIZE / mem::size_of::()) as u64); let err = deserialize::>(&serialize(&varint)).unwrap_err(); @@ -1003,7 +1067,10 @@ mod tests { #[test] fn deserialize_strbuf_test() { - assert_eq!(deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some("Andrew".to_string())); + assert_eq!( + deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), + Some("Andrew".to_string()) + ); assert_eq!( deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some(Cow::Borrowed("Andrew")) @@ -1012,7 +1079,8 @@ mod tests { #[test] fn deserialize_checkeddata_test() { - let cd: Result = deserialize(&[5u8, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); + let cd: Result = + deserialize(&[5u8, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); assert_eq!(cd.ok(), Some(CheckedData(vec![1u8, 2, 3, 4, 5]))); } @@ -1047,7 +1115,7 @@ mod tests { let mut data = Vec::with_capacity(256); let mut data64 = Vec::with_capacity(256); for _ in 0..10 { - round_trip!{bool, i8, u8, i16, u16, i32, u32, i64, u64, + round_trip! {bool, i8, u8, i16, u16, i32, u32, i64, u64, (bool, i8, u16, i32), (u64, i64, u32, i32, u16, i16), (i8, u8, i16, u16, i32, u32, i64, u64), [u8; 2], [u8; 4], [u8; 8], [u8; 12], [u8; 16], [u8; 32]}; @@ -1058,10 +1126,7 @@ mod tests { data64.resize(len, 0u64); let mut arr33 = [0u8; 33]; let mut arr16 = [0u16; 8]; - round_trip_bytes!{(Vec, data), ([u8; 33], arr33), ([u16; 8], arr16), (Vec, data64)}; - - + round_trip_bytes! {(Vec, data), ([u8; 33], arr33), ([u16; 8], arr16), (Vec, data64)}; } } } - diff --git a/src/consensus/mod.rs b/src/consensus/mod.rs index cdf8e6bb52..d6ff655561 100644 --- a/src/consensus/mod.rs +++ b/src/consensus/mod.rs @@ -21,6 +21,7 @@ pub mod encode; pub mod params; -pub use self::encode::{Encodable, Decodable, WriteExt, ReadExt}; -pub use self::encode::{serialize, deserialize, deserialize_partial}; +pub use self::encode::{ + deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt, +}; pub use self::params::Params; diff --git a/src/consensus/params.rs b/src/consensus/params.rs index 48d9e3e6e8..35107e171e 100644 --- a/src/consensus/params.rs +++ b/src/consensus/params.rs @@ -122,7 +122,7 @@ impl Params { }, Network::Signet => Params { network: Network::Signet, - bip16_time: 1333238400, // Apr 1 2012 + bip16_time: 1333238400, // Apr 1 2012 bip34_height: 1, bip65_height: 1, bip66_height: 1, diff --git a/src/internal_macros.rs b/src/internal_macros.rs index e1bfe7525a..97ea6ea6fc 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -65,23 +65,33 @@ macro_rules! impl_array_newtype { /// Returns the length of the object as an array #[inline] - pub fn len(&self) -> usize { $len } + pub fn len(&self) -> usize { + $len + } /// Returns whether the object, as an array, is empty. Always false. #[inline] - pub fn is_empty(&self) -> bool { false } + pub fn is_empty(&self) -> bool { + false + } /// Returns the underlying bytes. #[inline] - pub fn as_bytes(&self) -> &[$ty; $len] { &self.0 } + pub fn as_bytes(&self) -> &[$ty; $len] { + &self.0 + } /// Returns the underlying bytes. #[inline] - pub fn to_bytes(&self) -> [$ty; $len] { self.0.clone() } + pub fn to_bytes(&self) -> [$ty; $len] { + self.0.clone() + } /// Returns the underlying bytes. #[inline] - pub fn into_bytes(self) -> [$ty; $len] { self.0 } + pub fn into_bytes(self) -> [$ty; $len] { + self.0 + } } impl<'a> ::core::convert::From<&'a [$ty]> for $thing { @@ -104,7 +114,7 @@ macro_rules! impl_array_newtype { &self.0[index] } } - } + }; } macro_rules! display_from_debug { @@ -114,7 +124,7 @@ macro_rules! display_from_debug { ::core::fmt::Debug::fmt(self, f) } } - } + }; } #[cfg(test)] @@ -135,8 +145,8 @@ macro_rules! serde_string_impl { where D: $crate::serde::de::Deserializer<'de>, { - use ::core::fmt::{self, Formatter}; - use ::core::str::FromStr; + use core::fmt::{self, Formatter}; + use core::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { @@ -379,8 +389,7 @@ macro_rules! serde_struct_human_string_impl { /// - core::str::FromStr /// - hashes::hex::FromHex macro_rules! impl_bytes_newtype { - ($t:ident, $len:expr) => ( - + ($t:ident, $len:expr) => { impl ::core::fmt::LowerHex for $t { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { for &ch in self.0.iter() { @@ -405,9 +414,9 @@ macro_rules! impl_bytes_newtype { impl $crate::hashes::hex::FromHex for $t { fn from_byte_iter(iter: I) -> Result where - I: ::core::iter::Iterator> - + ::core::iter::ExactSizeIterator - + ::core::iter::DoubleEndedIterator, + I: ::core::iter::Iterator> + + ::core::iter::ExactSizeIterator + + ::core::iter::DoubleEndedIterator, { if iter.len() == $len { let mut ret = [0; $len]; @@ -450,7 +459,10 @@ macro_rules! impl_bytes_newtype { impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor { type Value = $t; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + fn expecting( + &self, + formatter: &mut ::core::fmt::Formatter, + ) -> ::core::fmt::Result { formatter.write_str("an ASCII hex string") } @@ -461,7 +473,10 @@ macro_rules! impl_bytes_newtype { if let Ok(hex) = ::core::str::from_utf8(v) { $crate::hashes::hex::FromHex::from_hex(hex).map_err(E::custom) } else { - return Err(E::invalid_value($crate::serde::de::Unexpected::Bytes(v), &self)); + return Err(E::invalid_value( + $crate::serde::de::Unexpected::Bytes(v), + &self, + )); } } @@ -480,7 +495,10 @@ macro_rules! impl_bytes_newtype { impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor { type Value = $t; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + fn expecting( + &self, + formatter: &mut ::core::fmt::Formatter, + ) -> ::core::fmt::Result { formatter.write_str("a bytestring") } @@ -502,7 +520,7 @@ macro_rules! impl_bytes_newtype { } } } - ) + }; } macro_rules! user_enum { diff --git a/src/lib.rs b/src/lib.rs index 6676ecdba3..f2a73a92f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,12 +41,9 @@ //! #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] - // Experimental features we need #![cfg_attr(all(test, feature = "unstable"), feature(test))] - #![cfg_attr(docsrs, feature(doc_cfg))] - // Coding conventions #![forbid(unsafe_code)] #![deny(non_upper_case_globals)] @@ -64,9 +61,11 @@ compile_error!("at least one of the `std` or `no-std` features must be enabled") // Disable 16-bit support at least for now as we can't guarantee it yet. #[cfg(target_pointer_width = "16")] -compile_error!("rust-bitcoin currently only supports architectures with pointers wider +compile_error!( + "rust-bitcoin currently only supports architectures with pointers wider than 16 bits, let us know if you want 16-bit support. Note that we do - NOT guarantee that we will implement it!"); + NOT guarantee that we will implement it!" +); #[cfg(feature = "no-std")] #[macro_use] @@ -78,9 +77,10 @@ extern crate core2; extern crate core; // for Rust 1.29 and no-std tests // Re-exported dependencies. -#[macro_use] pub extern crate bitcoin_hashes as hashes; -pub extern crate secp256k1; +#[macro_use] +pub extern crate bitcoin_hashes as hashes; pub extern crate bech32; +pub extern crate secp256k1; #[cfg(feature = "no-std")] extern crate hashbrown; @@ -89,12 +89,19 @@ extern crate hashbrown; #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] pub extern crate base64; -#[cfg(feature="bitcoinconsensus")] extern crate bitcoinconsensus; -#[cfg(feature = "serde")] #[macro_use] extern crate serde; -#[cfg(all(test, feature = "serde"))] extern crate serde_json; -#[cfg(all(test, feature = "serde"))] extern crate serde_test; -#[cfg(all(test, feature = "serde"))] extern crate bincode; -#[cfg(all(test, feature = "unstable"))] extern crate test; +#[cfg(feature = "bitcoinconsensus")] +extern crate bitcoinconsensus; +#[cfg(feature = "serde")] +#[macro_use] +extern crate serde; +#[cfg(all(test, feature = "serde"))] +extern crate bincode; +#[cfg(all(test, feature = "serde"))] +extern crate serde_json; +#[cfg(all(test, feature = "serde"))] +extern crate serde_test; +#[cfg(all(test, feature = "unstable"))] +extern crate test; #[cfg(target_pointer_width = "16")] compile_error!("rust-bitcoin cannot be used on 16-bit architectures"); @@ -110,44 +117,34 @@ mod serde_utils; #[macro_use] pub mod network; pub mod blockdata; -pub mod util; pub mod consensus; +pub mod util; #[rustfmt::skip] // `hash_newtype` statements are easier to read on a single line. pub mod hash_types; pub mod policy; -pub use hash_types::*; -pub use blockdata::block::Block; -pub use blockdata::block::BlockHeader; +#[cfg(feature = "std")] +use std::io; + +pub use blockdata::block::{Block, BlockHeader}; pub use blockdata::script::Script; -pub use blockdata::transaction::Transaction; -pub use blockdata::transaction::TxIn; -pub use blockdata::transaction::TxOut; -pub use blockdata::transaction::OutPoint; -pub use blockdata::transaction::EcdsaSighashType; +#[allow(deprecated)] +pub use blockdata::transaction::SigHashType; +pub use blockdata::transaction::{EcdsaSighashType, OutPoint, Transaction, TxIn, TxOut}; pub use blockdata::witness::Witness; pub use consensus::encode::VarInt; +#[cfg(not(feature = "std"))] +use core2::io; +pub use hash_types::*; pub use network::constants::Network; -pub use util::Error; -pub use util::address::Address; -pub use util::address::AddressType; -pub use util::amount::Amount; -pub use util::amount::Denomination; -pub use util::amount::SignedAmount; -pub use util::merkleblock::MerkleBlock; -pub use util::sighash::SchnorrSighashType; - +pub use util::address::{Address, AddressType}; +pub use util::amount::{Amount, Denomination, SignedAmount}; pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError}; +pub use util::key::{KeyPair, PrivateKey, PublicKey, XOnlyPublicKey}; +pub use util::merkleblock::MerkleBlock; pub use util::schnorr::{self, SchnorrSig, SchnorrSigError}; -pub use util::key::{PrivateKey, PublicKey, XOnlyPublicKey, KeyPair}; -pub use util::psbt; -#[allow(deprecated)] -pub use blockdata::transaction::SigHashType; - -#[cfg(feature = "std")] -use std::io; -#[cfg(not(feature = "std"))] -use core2::io; +pub use util::sighash::SchnorrSighashType; +pub use util::{psbt, Error}; #[cfg(not(feature = "std"))] mod io_extras { @@ -201,11 +198,13 @@ mod prelude { pub use std::collections::HashSet; } -#[cfg(all(test, feature = "unstable"))] use tests::EmptyWrite; +#[cfg(all(test, feature = "unstable"))] +use tests::EmptyWrite; #[cfg(all(test, feature = "unstable"))] mod tests { use core::fmt::Arguments; + use io::{IoSlice, Result, Write}; #[derive(Default, Clone, Debug, PartialEq, Eq)] diff --git a/src/network/address.rs b/src/network/address.rs index e9a1a3d673..259fe7ac93 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -18,14 +18,13 @@ //! network addresses in Bitcoin messages. //! -use prelude::*; - use core::{fmt, iter}; -use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6, Ipv4Addr, ToSocketAddrs}; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; +use consensus::encode::{self, Decodable, Encodable, ReadExt, VarInt, WriteExt}; use io; use network::constants::ServiceFlags; -use consensus::encode::{self, Decodable, Encodable, VarInt, ReadExt, WriteExt}; +use prelude::*; /// A message which can be sent on the Bitcoin network #[derive(Clone, PartialEq, Eq, Hash)] @@ -35,17 +34,17 @@ pub struct Address { /// Network byte-order ipv6 address, or ipv4-mapped ipv6 address pub address: [u16; 8], /// Network port - pub port: u16 + pub port: u16, } const ONION: [u16; 3] = [0xFD87, 0xD87E, 0xEB43]; impl Address { /// Create an address message for a socket - pub fn new(socket :&SocketAddr, services: ServiceFlags) -> Address { + pub fn new(socket: &SocketAddr, services: ServiceFlags) -> Address { let (address, port) = match *socket { SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()), - SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()) + SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()), }; Address { address, port, services } } @@ -58,7 +57,8 @@ impl Address { if addr[0..3] == ONION { return Err(io::Error::from(io::ErrorKind::AddrNotAvailable)); } - let ipv6 = Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); + let ipv6 = + Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); if let Some(ipv4) = ipv6.to_ipv4() { Ok(SocketAddr::V4(SocketAddrV4::new(ipv4, self.port))) } else { @@ -96,7 +96,7 @@ impl Decodable for Address { Ok(Address { services: Decodable::consensus_decode(&mut d)?, address: addr_to_be(Decodable::consensus_decode(&mut d)?), - port: u16::swap_bytes(Decodable::consensus_decode(d)?) + port: u16::swap_bytes(Decodable::consensus_decode(d)?), }) } } @@ -106,10 +106,16 @@ impl fmt::Debug for Address { let ipv6 = Ipv6Addr::from(self.address); match ipv6.to_ipv4() { - Some(addr) => write!(f, "Address {{services: {}, address: {}, port: {}}}", - self.services, addr, self.port), - None => write!(f, "Address {{services: {}, address: {}, port: {}}}", - self.services, ipv6, self.port) + Some(addr) => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, addr, self.port + ), + None => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, ipv6, self.port + ), } } } @@ -142,7 +148,11 @@ pub enum AddrV2 { impl Encodable for AddrV2 { fn consensus_encode(&self, e: W) -> Result { - fn encode_addr(mut e: W, network: u8, bytes: &[u8]) -> Result { + fn encode_addr( + mut e: W, + network: u8, + bytes: &[u8], + ) -> Result { let len = network.consensus_encode(&mut e)? + VarInt(bytes.len() as u64).consensus_encode(&mut e)? + bytes.len(); @@ -156,7 +166,7 @@ impl Encodable for AddrV2 { AddrV2::TorV3(ref bytes) => encode_addr(e, 4, bytes)?, AddrV2::I2p(ref bytes) => encode_addr(e, 5, bytes)?, AddrV2::Cjdns(ref addr) => encode_addr(e, 6, &addr.octets())?, - AddrV2::Unknown(network, ref bytes) => encode_addr(e, network, bytes)? + AddrV2::Unknown(network, ref bytes) => encode_addr(e, network, bytes)?, }) } } @@ -175,43 +185,49 @@ impl Decodable for AddrV2 { } let addr: [u8; 4] = Decodable::consensus_decode(&mut d)?; AddrV2::Ipv4(Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3])) - }, + } 2 => { if len != 16 { return Err(encode::Error::ParseFailed("Invalid IPv6 address")); } let addr: [u16; 8] = addr_to_be(Decodable::consensus_decode(&mut d)?); if addr[0..3] == ONION { - return Err(encode::Error::ParseFailed("OnionCat address sent with IPv6 network id")); + return Err(encode::Error::ParseFailed( + "OnionCat address sent with IPv6 network id", + )); } if addr[0..6] == [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF] { - return Err(encode::Error::ParseFailed("IPV4 wrapped address sent with IPv6 network id")); + return Err(encode::Error::ParseFailed( + "IPV4 wrapped address sent with IPv6 network id", + )); } - AddrV2::Ipv6(Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7])) - }, + AddrV2::Ipv6(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } 3 => { if len != 10 { return Err(encode::Error::ParseFailed("Invalid TorV2 address")); } let id = Decodable::consensus_decode(&mut d)?; AddrV2::TorV2(id) - }, + } 4 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid TorV3 address")); } let pubkey = Decodable::consensus_decode(&mut d)?; AddrV2::TorV3(pubkey) - }, + } 5 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid I2P address")); } let hash = Decodable::consensus_decode(&mut d)?; AddrV2::I2p(hash) - }, + } 6 => { - if len != 16 { + if len != 16 { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); } let addr: [u16; 8] = Decodable::consensus_decode(&mut d)?; @@ -220,8 +236,10 @@ impl Decodable for AddrV2 { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); } let addr = addr_to_be(addr); - AddrV2::Cjdns(Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7])) - }, + AddrV2::Cjdns(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } _ => { // len already checked above to be <= 512 let mut addr = vec![0u8; len as usize]; @@ -242,7 +260,7 @@ pub struct AddrV2Message { /// Network ID + Network Address pub addr: AddrV2, /// Network port, 0 if not applicable - pub port: u16 + pub port: u16, } impl AddrV2Message { @@ -293,12 +311,13 @@ impl ToSocketAddrs for AddrV2Message { #[cfg(test)] mod test { use core::str::FromStr; - use super::{AddrV2Message, AddrV2, Address}; - use network::constants::ServiceFlags; - use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; - use hashes::hex::FromHex; + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use consensus::encode::{deserialize, serialize}; + use hashes::hex::FromHex; + use network::constants::ServiceFlags; + + use super::{AddrV2, AddrV2Message, Address}; #[test] #[rustfmt::skip] @@ -337,41 +356,47 @@ mod test { #[test] fn deserialize_address_test() { - let mut addr: Result = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, - 0, 1, 0x20, 0x8d]); + let mut addr: Result = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + 0x20, 0x8d, + ]); assert!(addr.is_ok()); let full = addr.unwrap(); assert!(match full.socket_addr().unwrap() { - SocketAddr::V4(_) => true, - _ => false - } - ); + SocketAddr::V4(_) => true, + _ => false, + }); assert_eq!(full.services, ServiceFlags::NETWORK); assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]); assert_eq!(full.port, 8333); - addr = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]); + addr = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + ]); assert!(addr.is_err()); } #[test] - fn test_socket_addr () { - let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111,222,123,4)), 5555); + fn test_socket_addr() { + let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111, 222, 123, 4)), 5555); let a4 = Address::new(&s4, ServiceFlags::NETWORK | ServiceFlags::WITNESS); assert_eq!(a4.socket_addr().unwrap(), s4); - let s6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, - 0x5555, 0x6666, 0x7777, 0x8888)), 9999); + let s6 = SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, + )), + 9999, + ); let a6 = Address::new(&s6, ServiceFlags::NETWORK | ServiceFlags::WITNESS); assert_eq!(a6.socket_addr().unwrap(), s6); } #[test] - fn onion_test () { + fn onion_test() { let onionaddr = SocketAddr::new( - IpAddr::V6( - Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), 1111); + IpAddr::V6(Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), + 1111, + ); let addr = Address::new(&onionaddr, ServiceFlags::NONE); assert!(addr.socket_addr().is_err()); } @@ -383,17 +408,32 @@ mod test { let ip = AddrV2::Ipv4(Ipv4Addr::new(1, 2, 3, 4)); assert_eq!(serialize(&ip), Vec::from_hex("010401020304").unwrap()); - let ip = AddrV2::Ipv6(Ipv6Addr::from_str("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b").unwrap()); + let ip = + AddrV2::Ipv6(Ipv6Addr::from_str("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b").unwrap()); let ip = AddrV2::TorV2(FromHex::from_hex("f1f2f3f4f5f6f7f8f9fa").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("030af1f2f3f4f5f6f7f8f9fa").unwrap()); - let ip = AddrV2::TorV3(FromHex::from_hex("53cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88").unwrap()); - assert_eq!(serialize(&ip), Vec::from_hex("042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88").unwrap()); + let ip = AddrV2::TorV3( + FromHex::from_hex("53cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + Vec::from_hex("042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + .unwrap() + ); - let ip = AddrV2::I2p(FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()); - assert_eq!(serialize(&ip), Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()); + let ip = AddrV2::I2p( + FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap() + ); let ip = AddrV2::Cjdns(Ipv6Addr::from_str("fc00:1:2:3:4:5:6:7").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("0610fc000001000200030004000500060007").unwrap()); @@ -420,17 +460,27 @@ mod test { assert!(deserialize::(&Vec::from_hex("01fd010201020304").unwrap()).is_err()); // Valid IPv6. - let ip: AddrV2 = deserialize(&Vec::from_hex("02100102030405060708090a0b0c0d0e0f10").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::Ipv6(Ipv6Addr::from_str("102:304:506:708:90a:b0c:d0e:f10").unwrap())); + let ip: AddrV2 = + deserialize(&Vec::from_hex("02100102030405060708090a0b0c0d0e0f10").unwrap()).unwrap(); + assert_eq!( + ip, + AddrV2::Ipv6(Ipv6Addr::from_str("102:304:506:708:90a:b0c:d0e:f10").unwrap()) + ); // Invalid IPv6, with bogus length. assert!(deserialize::(&Vec::from_hex("020400").unwrap()).is_err()); // Invalid IPv6, contains embedded IPv4. - assert!(deserialize::(&Vec::from_hex("021000000000000000000000ffff01020304").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("021000000000000000000000ffff01020304").unwrap() + ) + .is_err()); // Invalid IPv6, contains embedded TORv2. - assert!(deserialize::(&Vec::from_hex("0210fd87d87eeb430102030405060708090a").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("0210fd87d87eeb430102030405060708090a").unwrap() + ) + .is_err()); // Valid TORv2. let ip: AddrV2 = deserialize(&Vec::from_hex("030af1f2f3f4f5f6f7f8f9fa").unwrap()).unwrap(); @@ -440,31 +490,61 @@ mod test { assert!(deserialize::(&Vec::from_hex("030700").unwrap()).is_err()); // Valid TORv3. - let ip: AddrV2 = deserialize(&Vec::from_hex("042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::TorV3(FromHex::from_hex("79bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f").unwrap())); + let ip: AddrV2 = deserialize( + &Vec::from_hex("042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f") + .unwrap(), + ) + .unwrap(); + assert_eq!( + ip, + AddrV2::TorV3( + FromHex::from_hex( + "79bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f" + ) + .unwrap() + ) + ); // Invalid TORv3, with bogus length. assert!(deserialize::(&Vec::from_hex("040000").unwrap()).is_err()); // Valid I2P. - let ip: AddrV2 = deserialize(&Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::I2p(FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap())); + let ip: AddrV2 = deserialize( + &Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap(), + ) + .unwrap(); + assert_eq!( + ip, + AddrV2::I2p( + FromHex::from_hex( + "a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87" + ) + .unwrap() + ) + ); // Invalid I2P, with bogus length. assert!(deserialize::(&Vec::from_hex("050300").unwrap()).is_err()); // Valid CJDNS. - let ip: AddrV2 = deserialize(&Vec::from_hex("0610fc000001000200030004000500060007").unwrap()).unwrap(); + let ip: AddrV2 = + deserialize(&Vec::from_hex("0610fc000001000200030004000500060007").unwrap()).unwrap(); assert_eq!(ip, AddrV2::Cjdns(Ipv6Addr::from_str("fc00:1:2:3:4:5:6:7").unwrap())); // Invalid CJDNS, incorrect marker - assert!(deserialize::(&Vec::from_hex("0610fd000001000200030004000500060007").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("0610fd000001000200030004000500060007").unwrap() + ) + .is_err()); // Invalid CJDNS, with bogus length. assert!(deserialize::(&Vec::from_hex("060100").unwrap()).is_err()); // Unknown, with extreme length. - assert!(deserialize::(&Vec::from_hex("aafe0000000201020304050607").unwrap()).is_err()); + assert!( + deserialize::(&Vec::from_hex("aafe0000000201020304050607").unwrap()).is_err() + ); // Unknown, with reasonable length. let ip: AddrV2 = deserialize(&Vec::from_hex("aa0401020304").unwrap()).unwrap(); @@ -480,10 +560,25 @@ mod test { let raw = Vec::from_hex("0261bc6649019902abab208d79627683fd4804010409090909208d").unwrap(); let addresses: Vec = deserialize(&raw).unwrap(); - assert_eq!(addresses, vec![ - AddrV2Message{services: ServiceFlags::NETWORK, time: 0x4966bc61, port: 8333, addr: AddrV2::Unknown(153, Vec::from_hex("abab").unwrap())}, - AddrV2Message{services: ServiceFlags::NETWORK_LIMITED | ServiceFlags::WITNESS | ServiceFlags::COMPACT_FILTERS, time: 0x83766279, port: 8333, addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9))}, - ]); + assert_eq!( + addresses, + vec![ + AddrV2Message { + services: ServiceFlags::NETWORK, + time: 0x4966bc61, + port: 8333, + addr: AddrV2::Unknown(153, Vec::from_hex("abab").unwrap()) + }, + AddrV2Message { + services: ServiceFlags::NETWORK_LIMITED + | ServiceFlags::WITNESS + | ServiceFlags::COMPACT_FILTERS, + time: 0x83766279, + port: 8333, + addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9)) + }, + ] + ); assert_eq!(serialize(&addresses), raw); } diff --git a/src/network/constants.rs b/src/network/constants.rs index 149940f63a..94802d000b 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -37,10 +37,11 @@ //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); //! ``` -use core::{fmt, ops, convert::From}; +use core::convert::From; +use core::{fmt, ops}; +use consensus::encode::{self, Decodable, Encodable}; use io; -use consensus::encode::{self, Encodable, Decodable}; /// Version of the protocol as appearing in network message headers /// This constant is used to signal to other peers which features you support. @@ -92,7 +93,7 @@ impl Network { 0x0709110B => Some(Network::Testnet), 0x40CF030A => Some(Network::Signet), 0xDAB5BFFA => Some(Network::Regtest), - _ => None + _ => None, } } @@ -112,7 +113,7 @@ impl Network { match self { Network::Bitcoin => 0xD9B4BEF9, Network::Testnet => 0x0709110B, - Network::Signet => 0x40CF030A, + Network::Signet => 0x40CF030A, Network::Regtest => 0xDAB5BFFA, } } @@ -212,7 +213,7 @@ impl fmt::Display for ServiceFlags { write!(f, stringify!($f))?; flags.remove(ServiceFlags::$f); } - } + }; } write!(f, "ServiceFlags(")?; write_flag!(NETWORK); @@ -288,9 +289,10 @@ impl Decodable for ServiceFlags { #[cfg(test)] mod tests { - use super::{Network, ServiceFlags}; use consensus::encode::{deserialize, serialize}; + use super::{Network, ServiceFlags}; + #[test] fn serialize_test() { assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]); @@ -302,7 +304,6 @@ mod tests { assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic())); assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic())); assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic())); - } #[test] diff --git a/src/network/message.rs b/src/network/message.rs index a1e92ae300..640c1397bb 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -18,19 +18,15 @@ //! are used for (de)serializing Bitcoin objects for transmission on the network. //! -use prelude::*; - -use core::{mem, fmt, iter}; +use core::{fmt, iter, mem}; -use io; -use blockdata::block; -use blockdata::transaction; -use network::address::{Address, AddrV2Message}; -use network::{message_network, message_bloom}; -use network::message_blockdata; -use network::message_filter; +use blockdata::{block, transaction}; use consensus::encode::{CheckedData, Decodable, Encodable, VarInt, MAX_VEC_SIZE}; use consensus::{encode, serialize}; +use io; +use network::address::{AddrV2Message, Address}; +use network::{message_blockdata, message_bloom, message_filter, message_network}; +use prelude::*; use util::merkleblock::MerkleBlock; /// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message. @@ -88,11 +84,13 @@ impl Decodable for CommandString { #[inline] fn consensus_decode(d: D) -> Result { let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?; - let rv = iter::FromIterator::from_iter( - rawbytes - .iter() - .filter_map(|&u| if u > 0 { Some(u as char) } else { None }) - ); + let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| { + if u > 0 { + Some(u as char) + } else { + None + } + })); Ok(CommandString(rv)) } } @@ -107,7 +105,12 @@ pub struct CommandStringError { impl fmt::Display for CommandStringError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "the command string '{}' has length {} which is larger than 12", self.cow, self.cow.len()) + write!( + f, + "the command string '{}' has length {} which is larger than 12", + self.cow, + self.cow.len() + ) } } @@ -121,7 +124,7 @@ pub struct RawNetworkMessage { /// Magic bytes to identify the network these messages are meant for pub magic: u32, /// The actual message data - pub payload: NetworkMessage + pub payload: NetworkMessage, } /// A Network message payload. Proper documentation is available on at @@ -202,7 +205,7 @@ pub enum NetworkMessage { command: CommandString, /// The payload of this message. payload: Vec, - } + }, } impl NetworkMessage { @@ -214,33 +217,33 @@ impl NetworkMessage { pub fn cmd(&self) -> &'static str { match *self { NetworkMessage::Version(_) => "version", - NetworkMessage::Verack => "verack", - NetworkMessage::Addr(_) => "addr", - NetworkMessage::Inv(_) => "inv", + NetworkMessage::Verack => "verack", + NetworkMessage::Addr(_) => "addr", + NetworkMessage::Inv(_) => "inv", NetworkMessage::GetData(_) => "getdata", NetworkMessage::NotFound(_) => "notfound", NetworkMessage::GetBlocks(_) => "getblocks", NetworkMessage::GetHeaders(_) => "getheaders", - NetworkMessage::MemPool => "mempool", - NetworkMessage::Tx(_) => "tx", - NetworkMessage::Block(_) => "block", + NetworkMessage::MemPool => "mempool", + NetworkMessage::Tx(_) => "tx", + NetworkMessage::Block(_) => "block", NetworkMessage::Headers(_) => "headers", NetworkMessage::SendHeaders => "sendheaders", - NetworkMessage::GetAddr => "getaddr", - NetworkMessage::Ping(_) => "ping", - NetworkMessage::Pong(_) => "pong", + NetworkMessage::GetAddr => "getaddr", + NetworkMessage::Ping(_) => "ping", + NetworkMessage::Pong(_) => "pong", NetworkMessage::MerkleBlock(_) => "merkleblock", NetworkMessage::FilterLoad(_) => "filterload", - NetworkMessage::FilterAdd(_) => "filteradd", - NetworkMessage::FilterClear => "filterclear", + NetworkMessage::FilterAdd(_) => "filteradd", + NetworkMessage::FilterClear => "filterclear", NetworkMessage::GetCFilters(_) => "getcfilters", NetworkMessage::CFilter(_) => "cfilter", NetworkMessage::GetCFHeaders(_) => "getcfheaders", NetworkMessage::CFHeaders(_) => "cfheaders", NetworkMessage::GetCFCheckpt(_) => "getcfcheckpt", NetworkMessage::CFCheckpt(_) => "cfcheckpt", - NetworkMessage::Alert(_) => "alert", - NetworkMessage::Reject(_) => "reject", + NetworkMessage::Alert(_) => "alert", + NetworkMessage::Reject(_) => "reject", NetworkMessage::FeeFilter(_) => "feefilter", NetworkMessage::WtxidRelay => "wtxidrelay", NetworkMessage::AddrV2(_) => "addrv2", @@ -253,7 +256,7 @@ impl NetworkMessage { pub fn command(&self) -> CommandString { match *self { NetworkMessage::Unknown { command: ref c, .. } => c.clone(), - _ => CommandString::try_from(self.cmd()).expect("cmd returns valid commands") + _ => CommandString::try_from(self.cmd()).expect("cmd returns valid commands"), } } } @@ -296,27 +299,27 @@ impl Encodable for RawNetworkMessage { len += self.command().consensus_encode(&mut s)?; len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), - NetworkMessage::Addr(ref dat) => serialize(dat), - NetworkMessage::Inv(ref dat) => serialize(dat), + NetworkMessage::Addr(ref dat) => serialize(dat), + NetworkMessage::Inv(ref dat) => serialize(dat), NetworkMessage::GetData(ref dat) => serialize(dat), NetworkMessage::NotFound(ref dat) => serialize(dat), NetworkMessage::GetBlocks(ref dat) => serialize(dat), NetworkMessage::GetHeaders(ref dat) => serialize(dat), - NetworkMessage::Tx(ref dat) => serialize(dat), - NetworkMessage::Block(ref dat) => serialize(dat), + NetworkMessage::Tx(ref dat) => serialize(dat), + NetworkMessage::Block(ref dat) => serialize(dat), NetworkMessage::Headers(ref dat) => serialize(&HeaderSerializationWrapper(dat)), - NetworkMessage::Ping(ref dat) => serialize(dat), - NetworkMessage::Pong(ref dat) => serialize(dat), - NetworkMessage::MerkleBlock(ref dat) => serialize(dat), - NetworkMessage::FilterLoad(ref dat) => serialize(dat), - NetworkMessage::FilterAdd(ref dat) => serialize(dat), + NetworkMessage::Ping(ref dat) => serialize(dat), + NetworkMessage::Pong(ref dat) => serialize(dat), + NetworkMessage::MerkleBlock(ref dat) => serialize(dat), + NetworkMessage::FilterLoad(ref dat) => serialize(dat), + NetworkMessage::FilterAdd(ref dat) => serialize(dat), NetworkMessage::GetCFilters(ref dat) => serialize(dat), NetworkMessage::CFilter(ref dat) => serialize(dat), NetworkMessage::GetCFHeaders(ref dat) => serialize(dat), NetworkMessage::CFHeaders(ref dat) => serialize(dat), NetworkMessage::GetCFCheckpt(ref dat) => serialize(dat), NetworkMessage::CFCheckpt(ref dat) => serialize(dat), - NetworkMessage::Alert(ref dat) => serialize(dat), + NetworkMessage::Alert(ref dat) => serialize(dat), NetworkMessage::Reject(ref dat) => serialize(dat), NetworkMessage::FeeFilter(ref data) => serialize(data), NetworkMessage::AddrV2(ref dat) => serialize(dat), @@ -328,7 +331,8 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::FilterClear | NetworkMessage::SendAddrV2 => vec![], NetworkMessage::Unknown { payload: ref data, .. } => serialize(data), - }).consensus_encode(&mut s)?; + }) + .consensus_encode(&mut s)?; Ok(len) } } @@ -340,16 +344,21 @@ impl Decodable for HeaderDeserializationWrapper { fn consensus_decode(mut d: D) -> Result { let len = VarInt::consensus_decode(&mut d)?.0; let byte_size = (len as usize) - .checked_mul(mem::size_of::()) - .ok_or(encode::Error::ParseFailed("Invalid length"))?; + .checked_mul(mem::size_of::()) + .ok_or(encode::Error::ParseFailed("Invalid length"))?; if byte_size > MAX_VEC_SIZE { - return Err(encode::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) + return Err(encode::Error::OversizedVectorAllocation { + requested: byte_size, + max: MAX_VEC_SIZE, + }); } let mut ret = Vec::with_capacity(len as usize); for _ in 0..len { ret.push(Decodable::consensus_decode(&mut d)?); if u8::consensus_decode(&mut d)? != 0u8 { - return Err(encode::Error::ParseFailed("Headers message should not contain transactions")); + return Err(encode::Error::ParseFailed( + "Headers message should not contain transactions", + )); } } Ok(HeaderDeserializationWrapper(ret)) @@ -365,71 +374,73 @@ impl Decodable for RawNetworkMessage { let mut mem_d = io::Cursor::new(raw_payload); let payload = match &cmd.0[..] { "version" => NetworkMessage::Version(Decodable::consensus_decode(&mut mem_d)?), - "verack" => NetworkMessage::Verack, - "addr" => NetworkMessage::Addr(Decodable::consensus_decode(&mut mem_d)?), - "inv" => NetworkMessage::Inv(Decodable::consensus_decode(&mut mem_d)?), + "verack" => NetworkMessage::Verack, + "addr" => NetworkMessage::Addr(Decodable::consensus_decode(&mut mem_d)?), + "inv" => NetworkMessage::Inv(Decodable::consensus_decode(&mut mem_d)?), "getdata" => NetworkMessage::GetData(Decodable::consensus_decode(&mut mem_d)?), "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode(&mut mem_d)?), "getblocks" => NetworkMessage::GetBlocks(Decodable::consensus_decode(&mut mem_d)?), "getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode(&mut mem_d)?), "mempool" => NetworkMessage::MemPool, - "block" => NetworkMessage::Block(Decodable::consensus_decode(&mut mem_d)?), + "block" => NetworkMessage::Block(Decodable::consensus_decode(&mut mem_d)?), "headers" => NetworkMessage::Headers( - HeaderDeserializationWrapper::consensus_decode(&mut mem_d)?.0 + HeaderDeserializationWrapper::consensus_decode(&mut mem_d)?.0, ), "sendheaders" => NetworkMessage::SendHeaders, "getaddr" => NetworkMessage::GetAddr, - "ping" => NetworkMessage::Ping(Decodable::consensus_decode(&mut mem_d)?), - "pong" => NetworkMessage::Pong(Decodable::consensus_decode(&mut mem_d)?), + "ping" => NetworkMessage::Ping(Decodable::consensus_decode(&mut mem_d)?), + "pong" => NetworkMessage::Pong(Decodable::consensus_decode(&mut mem_d)?), "merkleblock" => NetworkMessage::MerkleBlock(Decodable::consensus_decode(&mut mem_d)?), "filterload" => NetworkMessage::FilterLoad(Decodable::consensus_decode(&mut mem_d)?), "filteradd" => NetworkMessage::FilterAdd(Decodable::consensus_decode(&mut mem_d)?), "filterclear" => NetworkMessage::FilterClear, - "tx" => NetworkMessage::Tx(Decodable::consensus_decode(&mut mem_d)?), + "tx" => NetworkMessage::Tx(Decodable::consensus_decode(&mut mem_d)?), "getcfilters" => NetworkMessage::GetCFilters(Decodable::consensus_decode(&mut mem_d)?), "cfilter" => NetworkMessage::CFilter(Decodable::consensus_decode(&mut mem_d)?), - "getcfheaders" => NetworkMessage::GetCFHeaders(Decodable::consensus_decode(&mut mem_d)?), + "getcfheaders" => { + NetworkMessage::GetCFHeaders(Decodable::consensus_decode(&mut mem_d)?) + } "cfheaders" => NetworkMessage::CFHeaders(Decodable::consensus_decode(&mut mem_d)?), - "getcfcheckpt" => NetworkMessage::GetCFCheckpt(Decodable::consensus_decode(&mut mem_d)?), + "getcfcheckpt" => { + NetworkMessage::GetCFCheckpt(Decodable::consensus_decode(&mut mem_d)?) + } "cfcheckpt" => NetworkMessage::CFCheckpt(Decodable::consensus_decode(&mut mem_d)?), "reject" => NetworkMessage::Reject(Decodable::consensus_decode(&mut mem_d)?), - "alert" => NetworkMessage::Alert(Decodable::consensus_decode(&mut mem_d)?), + "alert" => NetworkMessage::Alert(Decodable::consensus_decode(&mut mem_d)?), "feefilter" => NetworkMessage::FeeFilter(Decodable::consensus_decode(&mut mem_d)?), "wtxidrelay" => NetworkMessage::WtxidRelay, "addrv2" => NetworkMessage::AddrV2(Decodable::consensus_decode(&mut mem_d)?), "sendaddrv2" => NetworkMessage::SendAddrV2, - _ => NetworkMessage::Unknown { - command: cmd, - payload: mem_d.into_inner(), - } + _ => NetworkMessage::Unknown { command: cmd, payload: mem_d.into_inner() }, }; - Ok(RawNetworkMessage { - magic, - payload, - }) + Ok(RawNetworkMessage { magic, payload }) } } #[cfg(test)] mod test { use std::net::Ipv4Addr; - use super::{RawNetworkMessage, NetworkMessage, CommandString}; - use network::constants::ServiceFlags; + + use blockdata::block::{Block, BlockHeader}; + use blockdata::script::Script; + use blockdata::transaction::Transaction; use consensus::encode::{deserialize, deserialize_partial, serialize}; use hashes::hex::FromHex; use hashes::sha256d::Hash; use hashes::Hash as HashTrait; - use network::address::{Address, AddrV2, AddrV2Message}; - use super::message_network::{Reject, RejectReason, VersionMessage}; - use network::message_blockdata::{Inventory, GetBlocksMessage, GetHeadersMessage}; - use blockdata::block::{Block, BlockHeader}; - use network::message_filter::{GetCFilters, CFilter, GetCFHeaders, CFHeaders, GetCFCheckpt, CFCheckpt}; - use blockdata::transaction::Transaction; - use blockdata::script::Script; - use network::message_bloom::{FilterAdd, FilterLoad, BloomFlags}; + use network::address::{AddrV2, AddrV2Message, Address}; + use network::constants::ServiceFlags; + use network::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory}; + use network::message_bloom::{BloomFlags, FilterAdd, FilterLoad}; + use network::message_filter::{ + CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters, + }; use MerkleBlock; - fn hash(slice: [u8;32]) -> Hash { + use super::message_network::{Reject, RejectReason, VersionMessage}; + use super::{CommandString, NetworkMessage, RawNetworkMessage}; + + fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() } @@ -440,18 +451,30 @@ mod test { let tx: Transaction = deserialize(&Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap(); let block: Block = deserialize(&include_bytes!("../../test_data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap(); let header: BlockHeader = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap(); - let script: Script = deserialize(&Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap()).unwrap(); + let script: Script = deserialize( + &Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap(), + ) + .unwrap(); let merkle_block: MerkleBlock = deserialize(&Vec::from_hex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101").unwrap()).unwrap(); let msgs = vec![ NetworkMessage::Version(version_msg), NetworkMessage::Verack, - NetworkMessage::Addr(vec![(45, Address::new(&([123,255,000,100], 833).into(), ServiceFlags::NETWORK))]), + NetworkMessage::Addr(vec![( + 45, + Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK), + )]), NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]), NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]), NetworkMessage::NotFound(vec![Inventory::Error]), - NetworkMessage::GetBlocks(GetBlocksMessage::new(vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], hash([5u8; 32]).into())), - NetworkMessage::GetHeaders(GetHeadersMessage::new(vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()], hash([50u8; 32]).into())), + NetworkMessage::GetBlocks(GetBlocksMessage::new( + vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], + hash([5u8; 32]).into(), + )), + NetworkMessage::GetHeaders(GetHeadersMessage::new( + vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()], + hash([50u8; 32]).into(), + )), NetworkMessage::MemPool, NetworkMessage::Tx(tx), NetworkMessage::Block(block), @@ -461,29 +484,67 @@ mod test { NetworkMessage::Ping(15), NetworkMessage::Pong(23), NetworkMessage::MerkleBlock(merkle_block), - NetworkMessage::FilterLoad(FilterLoad {filter: Vec::from_hex("03614e9b050000000000000001").unwrap(), hash_funcs: 1, tweak: 2, flags: BloomFlags::All}), - NetworkMessage::FilterAdd(FilterAdd {data: script.as_bytes().to_vec()}), - NetworkMessage::FilterAdd(FilterAdd {data: hash([29u8; 32]).to_vec()}), + NetworkMessage::FilterLoad(FilterLoad { + filter: Vec::from_hex("03614e9b050000000000000001").unwrap(), + hash_funcs: 1, + tweak: 2, + flags: BloomFlags::All, + }), + NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }), + NetworkMessage::FilterAdd(FilterAdd { data: hash([29u8; 32]).to_vec() }), NetworkMessage::FilterClear, - NetworkMessage::GetCFilters(GetCFilters{filter_type: 2, start_height: 52, stop_hash: hash([42u8; 32]).into()}), - NetworkMessage::CFilter(CFilter{filter_type: 7, block_hash: hash([25u8; 32]).into(), filter: vec![1,2,3]}), - NetworkMessage::GetCFHeaders(GetCFHeaders{filter_type: 4, start_height: 102, stop_hash: hash([47u8; 32]).into()}), - NetworkMessage::CFHeaders(CFHeaders{filter_type: 13, stop_hash: hash([53u8; 32]).into(), previous_filter_header: hash([12u8; 32]).into(), filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()]}), - NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}), - NetworkMessage::CFCheckpt(CFCheckpt{filter_type: 27, stop_hash: hash([77u8; 32]).into(), filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()]}), - NetworkMessage::Alert(vec![45,66,3,2,6,8,9,12,3,130]), - NetworkMessage::Reject(Reject{message: CommandString::try_from("Test reject").unwrap(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}), + NetworkMessage::GetCFilters(GetCFilters { + filter_type: 2, + start_height: 52, + stop_hash: hash([42u8; 32]).into(), + }), + NetworkMessage::CFilter(CFilter { + filter_type: 7, + block_hash: hash([25u8; 32]).into(), + filter: vec![1, 2, 3], + }), + NetworkMessage::GetCFHeaders(GetCFHeaders { + filter_type: 4, + start_height: 102, + stop_hash: hash([47u8; 32]).into(), + }), + NetworkMessage::CFHeaders(CFHeaders { + filter_type: 13, + stop_hash: hash([53u8; 32]).into(), + previous_filter_header: hash([12u8; 32]).into(), + filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()], + }), + NetworkMessage::GetCFCheckpt(GetCFCheckpt { + filter_type: 17, + stop_hash: hash([25u8; 32]).into(), + }), + NetworkMessage::CFCheckpt(CFCheckpt { + filter_type: 27, + stop_hash: hash([77u8; 32]).into(), + filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()], + }), + NetworkMessage::Alert(vec![45, 66, 3, 2, 6, 8, 9, 12, 3, 130]), + NetworkMessage::Reject(Reject { + message: CommandString::try_from("Test reject").unwrap(), + ccode: RejectReason::Duplicate, + reason: "Cause".into(), + hash: hash([255u8; 32]), + }), NetworkMessage::FeeFilter(1000), NetworkMessage::WtxidRelay, - NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]), + NetworkMessage::AddrV2(vec![AddrV2Message { + addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), + port: 0, + services: ServiceFlags::NONE, + time: 0, + }]), NetworkMessage::SendAddrV2, ]; for msg in msgs { - let raw_msg = RawNetworkMessage {magic: 57, payload: msg}; + let raw_msg = RawNetworkMessage { magic: 57, payload: msg }; assert_eq!(deserialize::(&serialize(&raw_msg)).unwrap(), raw_msg); } - } #[test] @@ -497,12 +558,14 @@ mod test { assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); // Test deserializing - let cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); + let cs: Result = + deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); assert!(cs.is_ok()); assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned()); assert_eq!(cs.unwrap(), CommandString::try_from("Andrew").unwrap()); - let short_cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]); + let short_cs: Result = + deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]); assert!(short_cs.is_err()); } @@ -525,7 +588,6 @@ mod test { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); } - #[test] #[rustfmt::skip] fn serialize_mempool_test() { @@ -552,9 +614,12 @@ mod test { 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); - let preimage = RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr }; + let preimage = RawNetworkMessage { + magic: 0xd9b4bef9, + payload: NetworkMessage::GetAddr, + }; assert!(msg.is_ok()); - let msg : RawNetworkMessage = msg.unwrap(); + let msg: RawNetworkMessage = msg.unwrap(); assert_eq!(preimage.magic, msg.magic); assert_eq!(preimage.payload, msg.payload); } @@ -585,7 +650,13 @@ mod test { assert_eq!(msg.magic, 0xd9b4bef9); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); - assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); assert_eq!(version_msg.timestamp, 1548554224); assert_eq!(version_msg.nonce, 13952548347456104954); assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/"); @@ -623,7 +694,13 @@ mod test { assert_eq!(msg.magic, 0xd9b4bef9); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); - assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); assert_eq!(version_msg.timestamp, 1548554224); assert_eq!(version_msg.nonce, 13952548347456104954); assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/"); diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 28913df9fa..65465e4707 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -18,15 +18,12 @@ //! Bitcoin data (blocks and transactions) around. //! -use prelude::*; - -use io; - -use hashes::sha256d; - -use network::constants; use consensus::encode::{self, Decodable, Encodable}; use hash_types::{BlockHash, Txid, Wtxid}; +use hashes::sha256d; +use io; +use network::constants; +use prelude::*; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] @@ -49,7 +46,7 @@ pub enum Inventory { inv_type: u32, /// The hash of the inventory item hash: [u8; 32], - } + }, } impl Encodable for Inventory { @@ -58,7 +55,7 @@ impl Encodable for Inventory { macro_rules! encode_inv { ($code:expr, $item:expr) => { u32::consensus_encode(&$code, &mut s)? + $item.consensus_encode(&mut s)? - } + }; } Ok(match *self { Inventory::Error => encode_inv!(0, sha256d::Hash::default()), @@ -86,7 +83,7 @@ impl Decodable for Inventory { tp => Inventory::Unknown { inv_type: tp, hash: Decodable::consensus_decode(&mut d)?, - } + }, }) } } @@ -116,7 +113,7 @@ pub struct GetHeadersMessage { /// if possible and block 1 otherwise. pub locator_hashes: Vec, /// References the header to stop at, or zero to just fetch the maximum 2000 headers - pub stop_hash: BlockHash + pub stop_hash: BlockHash, } impl GetBlocksMessage { @@ -147,17 +144,19 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); #[cfg(test)] mod tests { - use super::{Vec, GetHeadersMessage, GetBlocksMessage}; + use core::default::Default; + use consensus::encode::{deserialize, serialize}; use hashes::hex::FromHex; - use consensus::encode::{deserialize, serialize}; - use core::default::Default; + use super::{GetBlocksMessage, GetHeadersMessage, Vec}; #[test] fn getblocks_message_test() { let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let genhash = + Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") + .unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); @@ -173,7 +172,9 @@ mod tests { #[test] fn getheaders_message_test() { let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let genhash = + Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") + .unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); @@ -186,4 +187,3 @@ mod tests { assert_eq!(serialize(&real_decode), from_sat); } } - diff --git a/src/network/message_bloom.rs b/src/network/message_bloom.rs index e3307a03e8..1ab8d627b5 100644 --- a/src/network/message_bloom.rs +++ b/src/network/message_bloom.rs @@ -3,10 +3,10 @@ //! This module describes BIP37 Connection Bloom filtering network messages. //! -use consensus::encode; -use consensus::{Decodable, Encodable, ReadExt}; use std::io; +use consensus::{encode, Decodable, Encodable, ReadExt}; + /// `filterload` message sets the current bloom filter #[derive(Clone, PartialEq, Eq, Debug)] pub struct FilterLoad { diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 4422ad0cd5..23ed140c84 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -18,16 +18,13 @@ //! capabilities. //! -use prelude::*; - +use consensus::{encode, Decodable, Encodable, ReadExt}; +use hashes::sha256d; use io; - use network::address::Address; use network::constants::{self, ServiceFlags}; -use consensus::{Encodable, Decodable, ReadExt}; -use consensus::encode; use network::message::CommandString; -use hashes::sha256d; +use prelude::*; /// Some simple messages @@ -53,7 +50,7 @@ pub struct VersionMessage { /// Whether the receiving peer should relay messages to the sender; used /// if the sender is bandwidth-limited and would like to support bloom /// filtering. Defaults to false. - pub relay: bool + pub relay: bool, } impl VersionMessage { @@ -81,9 +78,18 @@ impl VersionMessage { } } -impl_consensus_encoding!(VersionMessage, version, services, timestamp, - receiver, sender, nonce, - user_agent, start_height, relay); +impl_consensus_encoding!( + VersionMessage, + version, + services, + timestamp, + receiver, + sender, + nonce, + user_agent, + start_height, + relay +); /// message rejection reason as a code #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -103,7 +109,7 @@ pub enum RejectReason { /// insufficient fee Fee = 0x42, /// checkpoint - Checkpoint = 0x43 + Checkpoint = 0x43, } impl Encodable for RejectReason { @@ -124,7 +130,7 @@ impl Decodable for RejectReason { 0x41 => RejectReason::Dust, 0x42 => RejectReason::Fee, 0x43 => RejectReason::Checkpoint, - _ => return Err(encode::Error::ParseFailed("unknown reject code")) + _ => return Err(encode::Error::ParseFailed("unknown reject code")), }) } } @@ -139,19 +145,18 @@ pub struct Reject { /// reason of rejectection pub reason: Cow<'static, str>, /// reference to rejected item - pub hash: sha256d::Hash + pub hash: sha256d::Hash, } impl_consensus_encoding!(Reject, message, ccode, reason, hash); #[cfg(test)] mod tests { - use super::VersionMessage; - + use consensus::encode::{deserialize, serialize}; use hashes::hex::FromHex; use network::constants::ServiceFlags; - use consensus::encode::{deserialize, serialize}; + use super::VersionMessage; #[test] fn version_message_test() { diff --git a/src/network/mod.rs b/src/network/mod.rs index e52a0ed5c9..f8fa3a54ca 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -18,9 +18,11 @@ //! of Bitcoin data and network messages. //! -use io; use core::fmt; -#[cfg(feature = "std")] use std::error; +#[cfg(feature = "std")] +use std::error; + +use io; pub mod constants; @@ -41,10 +43,10 @@ pub mod message_blockdata; pub mod message_bloom; #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub mod message_network; +pub mod message_filter; #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub mod message_filter; +pub mod message_network; #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub mod stream_reader; diff --git a/src/network/stream_reader.rs b/src/network/stream_reader.rs index 59d7aaf31c..712091300d 100644 --- a/src/network/stream_reader.rs +++ b/src/network/stream_reader.rs @@ -23,9 +23,9 @@ //! use core::fmt; -use io::{Read, BufReader}; use consensus::{encode, Decodable}; +use io::{BufReader, Read}; /// Struct used to configure stream reader function pub struct StreamReader { @@ -41,15 +41,19 @@ impl fmt::Debug for StreamReader { impl StreamReader { /// Constructs new stream reader for a given input stream `stream` - #[deprecated(since = "0.28.0", note = "wrap your stream into a buffered reader if necessary and use consensus_encode directly")] + #[deprecated( + since = "0.28.0", + note = "wrap your stream into a buffered reader if necessary and use consensus_encode directly" + )] pub fn new(stream: R, _buffer_size: Option) -> StreamReader { - StreamReader { - stream: BufReader::new(stream), - } + StreamReader { stream: BufReader::new(stream) } } /// Reads stream and parses next message from its current input - #[deprecated(since = "0.28.0", note = "wrap your stream into a buffered reader if necessary and use consensus_encode directly")] + #[deprecated( + since = "0.28.0", + note = "wrap your stream into a buffered reader if necessary and use consensus_encode directly" + )] pub fn read_next(&mut self) -> Result { Decodable::consensus_decode(&mut self.stream) } @@ -58,15 +62,16 @@ impl StreamReader { #[allow(deprecated)] #[cfg(test)] mod test { + use std::net::{Shutdown, TcpListener, TcpStream}; use std::thread; + use std::thread::JoinHandle; use std::time::Duration; + use io::{BufReader, Write}; - use std::net::{TcpListener, TcpStream, Shutdown}; - use std::thread::JoinHandle; use network::constants::ServiceFlags; + use network::message::{NetworkMessage, RawNetworkMessage}; use super::StreamReader; - use network::message::{NetworkMessage, RawNetworkMessage}; // First, let's define some byte arrays for sample messages - dumps are taken from live // Bitcoin Core node v0.17.1 with Wireshark @@ -138,7 +143,13 @@ mod test { assert_eq!(msg.magic, 0xd9b4bef9); if let NetworkMessage::Version(ref version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); - assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); assert_eq!(version_msg.timestamp, 1548554224); assert_eq!(version_msg.nonce, 13952548347456104954); assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/"); @@ -235,7 +246,8 @@ mod test { // Setting up TCP connection emulation let (handle, istream) = serve_tcp(vec![ // single message split in two parts to emulate real network conditions - MSG_VERSION[..24].to_vec(), MSG_VERSION[24..].to_vec() + MSG_VERSION[..24].to_vec(), + MSG_VERSION[24..].to_vec(), ]); let stream = istream; let mut reader = StreamReader::new(stream, None); @@ -253,9 +265,11 @@ mod test { // Setting up TCP connection emulation let (handle, istream) = serve_tcp(vec![ // Real-world Bitcoin core communication case for /Satoshi:0.17.1/ - MSG_VERSION[..23].to_vec(), MSG_VERSION[23..].to_vec(), + MSG_VERSION[..23].to_vec(), + MSG_VERSION[23..].to_vec(), MSG_VERACK.to_vec(), - MSG_ALERT[..24].to_vec(), MSG_ALERT[24..].to_vec() + MSG_ALERT[..24].to_vec(), + MSG_ALERT[24..].to_vec(), ]); let stream = istream; let mut reader = StreamReader::new(stream, None); @@ -267,7 +281,11 @@ mod test { // Reading and checking the second message (Verack) let msg: RawNetworkMessage = reader.read_next().unwrap(); assert_eq!(msg.magic, 0xd9b4bef9); - assert_eq!(msg.payload, NetworkMessage::Verack, "Wrong message type, expected VerackMessage"); + assert_eq!( + msg.payload, + NetworkMessage::Verack, + "Wrong message type, expected VerackMessage" + ); // Reading and checking the third message (Alert) let msg = reader.read_next().unwrap(); @@ -279,15 +297,18 @@ mod test { #[test] fn read_block_from_file_test() { - use io; use consensus::serialize; use hashes::hex::FromHex; - use Block; + use {io, Block}; let normal_data = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap(); let cutoff_data = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap(); - let prevhash = Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); - let merkle = Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); + let prevhash = + Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000") + .unwrap(); + let merkle = + Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c") + .unwrap(); let stream = io::BufReader::new(&normal_data[..]); let mut reader = StreamReader::new(stream, None); diff --git a/src/policy.rs b/src/policy.rs index 0a86565385..00edd7f94c 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -24,9 +24,10 @@ //! These values were taken from bitcoind v0.21.1 (194b9b8792d9b0798fdb570b79fa51f1d1f5ebaf). //! -use super::blockdata::constants::{MAX_BLOCK_SIGOPS_COST, WITNESS_SCALE_FACTOR}; use core::cmp; +use super::blockdata::constants::{MAX_BLOCK_SIGOPS_COST, WITNESS_SCALE_FACTOR}; + /// Maximum weight of a transaction for it to be relayed by most nodes on the network pub const MAX_STANDARD_TX_WEIGHT: u32 = 400_000; diff --git a/src/serde_utils.rs b/src/serde_utils.rs index da4011e51e..7d988fa4b4 100644 --- a/src/serde_utils.rs +++ b/src/serde_utils.rs @@ -9,8 +9,8 @@ pub mod btreemap_byte_values { // NOTE: This module can be exactly copied to use with HashMap. - use prelude::*; use hashes::hex::{FromHex, ToHex}; + use prelude::*; use serde; pub fn serialize(v: &BTreeMap>, s: S) -> Result @@ -37,7 +37,7 @@ pub mod btreemap_byte_values { D: serde::Deserializer<'de>, T: serde::Deserialize<'de> + ::core::hash::Hash + Eq + Ord, { - use ::core::marker::PhantomData; + use core::marker::PhantomData; struct Visitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for Visitor @@ -50,9 +50,10 @@ pub mod btreemap_byte_values { write!(f, "a map with hexadecimal values") } - fn visit_map>(self, mut a: A) - -> Result - { + fn visit_map>( + self, + mut a: A, + ) -> Result { let mut ret = BTreeMap::new(); while let Some((key, value)) = a.next_entry()? { ret.insert(key, FromHex::from_hex(value).map_err(serde::de::Error::custom)?); @@ -106,7 +107,7 @@ pub mod btreemap_as_seq { T: serde::Deserialize<'de> + ::core::hash::Hash + Eq + Ord, U: serde::Deserialize<'de>, { - use ::core::marker::PhantomData; + use core::marker::PhantomData; struct Visitor(PhantomData<(T, U)>); impl<'de, T, U> serde::de::Visitor<'de> for Visitor @@ -120,9 +121,10 @@ pub mod btreemap_as_seq { write!(f, "a sequence of pairs") } - fn visit_seq>(self, mut a: A) - -> Result - { + fn visit_seq>( + self, + mut a: A, + ) -> Result { let mut ret = BTreeMap::new(); while let Some((key, value)) = a.next_element()? { ret.insert(key, value); @@ -154,16 +156,14 @@ pub mod btreemap_as_seq_byte_values { #[derive(Debug, Deserialize)] struct OwnedPair( T, - #[serde(deserialize_with = "::serde_utils::hex_bytes::deserialize")] - Vec, + #[serde(deserialize_with = "::serde_utils::hex_bytes::deserialize")] Vec, ); /// A custom key-value pair type that serialized the bytes as hex. #[derive(Debug, Serialize)] struct BorrowedPair<'a, T: 'static>( &'a T, - #[serde(serialize_with = "::serde_utils::hex_bytes::serialize")] - &'a [u8], + #[serde(serialize_with = "::serde_utils::hex_bytes::serialize")] &'a [u8], ); pub fn serialize(v: &BTreeMap>, s: S) -> Result @@ -190,7 +190,7 @@ pub mod btreemap_as_seq_byte_values { D: serde::Deserializer<'de>, T: serde::Deserialize<'de> + ::core::hash::Hash + Eq + Ord, { - use ::core::marker::PhantomData; + use core::marker::PhantomData; struct Visitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for Visitor @@ -203,9 +203,10 @@ pub mod btreemap_as_seq_byte_values { write!(f, "a sequence of pairs") } - fn visit_seq>(self, mut a: A) - -> Result - { + fn visit_seq>( + self, + mut a: A, + ) -> Result { let mut ret = BTreeMap::new(); while let Option::Some(OwnedPair(key, value)) = a.next_element()? { ret.insert(key, value); @@ -232,7 +233,8 @@ pub mod hex_bytes { pub fn serialize(bytes: &T, s: S) -> Result where - T: serde::Serialize + AsRef<[u8]>, S: serde::Serializer + T: serde::Serialize + AsRef<[u8]>, + S: serde::Serializer, { // Don't do anything special when not human readable. if !s.is_human_readable() { @@ -244,7 +246,8 @@ pub mod hex_bytes { pub fn deserialize<'de, D, B>(d: D) -> Result where - D: serde::Deserializer<'de>, B: serde::Deserialize<'de> + FromHex, + D: serde::Deserializer<'de>, + B: serde::Deserialize<'de> + FromHex, { struct Visitor(::core::marker::PhantomData); diff --git a/src/util/address.rs b/src/util/address.rs index 982ae118f3..ca3cc43776 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -32,25 +32,28 @@ //! let address = Address::p2pkh(&public_key, Network::Bitcoin); //! ``` -use prelude::*; - use core::fmt; use core::num::ParseIntError; use core::str::FromStr; -#[cfg(feature = "std")] use std::error; +#[cfg(feature = "std")] +use std::error; -use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; use bech32; -use hashes::{sha256, Hash, HashEngine}; +use blockdata::constants::{ + MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, + SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST, +}; +use blockdata::script::Instruction; +use blockdata::{opcodes, script}; use hash_types::{PubkeyHash, ScriptHash}; -use blockdata::{script, opcodes}; -use blockdata::constants::{PUBKEY_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, SCRIPT_ADDRESS_PREFIX_TEST, MAX_SCRIPT_ELEMENT_SIZE}; +use hashes::{sha256, Hash, HashEngine}; use network::constants::Network; +use prelude::*; +use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; use util::base58; -use util::taproot::TapBranchHash; use util::key::PublicKey; -use blockdata::script::Instruction; -use util::schnorr::{TapTweak, UntweakedPublicKey, TweakedPublicKey}; +use util::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use util::taproot::TapBranchHash; /// Address error. #[derive(Debug, PartialEq, Eq, Clone)] @@ -66,7 +69,7 @@ pub enum Error { /// Bech32 variant that is required by the used Witness version. expected: bech32::Variant, /// The actual Bech32 variant encoded in the address representation. - found: bech32::Variant + found: bech32::Variant, }, /// Script version must be 0 to 16 inclusive. InvalidWitnessVersion(u8), @@ -81,7 +84,7 @@ pub enum Error { /// An uncompressed pubkey was used where it is not allowed. UncompressedPubkey, /// Address size more than 520 bytes is not allowed. - ExcessiveScriptSize + ExcessiveScriptSize, } impl fmt::Display for Error { @@ -105,7 +108,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { match *self { Error::Base58(ref e) => Some(e), Error::Bech32(ref e) => Some(e), @@ -224,7 +227,6 @@ impl fmt::Display for WitnessVersion { } } - impl FromStr for WitnessVersion { type Err = Error; @@ -290,9 +292,13 @@ impl WitnessVersion { pub fn from_opcode(opcode: opcodes::All) -> Result { match opcode.into_u8() { 0 => Ok(WitnessVersion::V0), - version if version >= opcodes::all::OP_PUSHNUM_1.into_u8() && version <= opcodes::all::OP_PUSHNUM_16.into_u8() => - WitnessVersion::from_num(version - opcodes::all::OP_PUSHNUM_1.into_u8() + 1), - _ => Err(Error::MalformedWitnessVersion) + version + if version >= opcodes::all::OP_PUSHNUM_1.into_u8() + && version <= opcodes::all::OP_PUSHNUM_16.into_u8() => + { + WitnessVersion::from_num(version - opcodes::all::OP_PUSHNUM_1.into_u8() + 1) + } + _ => Err(Error::MalformedWitnessVersion), } } @@ -343,7 +349,7 @@ impl From for opcodes::All { fn from(version: WitnessVersion) -> opcodes::All { match version { WitnessVersion::V0 => opcodes::all::OP_PUSHBYTES_0, - no => opcodes::All::from(opcodes::all::OP_PUSHNUM_1.into_u8() + no.into_num() - 1) + no => opcodes::All::from(opcodes::all::OP_PUSHNUM_1.into_u8() + no.into_num() - 1), } } } @@ -498,10 +504,7 @@ impl<'a> fmt::Display for AddressEncoding<'a> { prefixed[1..].copy_from_slice(&hash[..]); base58::check_encode_slice_to_fmt(fmt, &prefixed[..]) } - Payload::WitnessProgram { - version, - program: prog, - } => { + Payload::WitnessProgram { version, program: prog } => { let mut upper_writer; let writer = if fmt.alternate() { upper_writer = UpperWriter(fmt); @@ -534,10 +537,7 @@ impl Address { /// This is the preferred non-witness type address. #[inline] pub fn p2pkh(pk: &PublicKey, network: Network) -> Address { - Address { - network, - payload: Payload::p2pkh(pk), - } + Address { network, payload: Payload::p2pkh(pk) } } /// Creates a pay to script hash P2SH address from a script. @@ -546,10 +546,7 @@ impl Address { /// these days. #[inline] pub fn p2sh(script: &script::Script, network: Network) -> Result { - Ok(Address { - network, - payload: Payload::p2sh(script)?, - }) + Ok(Address { network, payload: Payload::p2sh(script)? }) } /// Creates a witness pay to public key address from a public key. @@ -559,10 +556,7 @@ impl Address { /// # Errors /// Will only return an error if an uncompressed public key is provided. pub fn p2wpkh(pk: &PublicKey, network: Network) -> Result { - Ok(Address { - network, - payload: Payload::p2wpkh(pk)?, - }) + Ok(Address { network, payload: Payload::p2wpkh(pk)? }) } /// Creates a pay to script address that embeds a witness pay to public key. @@ -572,28 +566,19 @@ impl Address { /// # Errors /// Will only return an Error if an uncompressed public key is provided. pub fn p2shwpkh(pk: &PublicKey, network: Network) -> Result { - Ok(Address { - network, - payload: Payload::p2shwpkh(pk)?, - }) + Ok(Address { network, payload: Payload::p2shwpkh(pk)? }) } /// Creates a witness pay to script hash address. pub fn p2wsh(script: &script::Script, network: Network) -> Address { - Address { - network, - payload: Payload::p2wsh(script), - } + Address { network, payload: Payload::p2wsh(script) } } /// Creates a pay to script address that embeds a witness pay to script hash address. /// /// This is a segwit address type that looks familiar (as p2sh) to legacy clients. pub fn p2shwsh(script: &script::Script, network: Network) -> Address { - Address { - network, - payload: Payload::p2shwsh(script), - } + Address { network, payload: Payload::p2shwsh(script) } } /// Creates a pay to taproot address from an untweaked key. @@ -601,7 +586,7 @@ impl Address { secp: &Secp256k1, internal_key: UntweakedPublicKey, merkle_root: Option, - network: Network + network: Network, ) -> Address { Address { network: network, @@ -627,10 +612,7 @@ impl Address { match self.payload { Payload::PubkeyHash(_) => Some(AddressType::P2pkh), Payload::ScriptHash(_) => Some(AddressType::P2sh), - Payload::WitnessProgram { - version, - program: ref prog, - } => { + Payload::WitnessProgram { version, program: ref prog } => { // BIP-141 p2wpkh or p2wsh addresses. match version { WitnessVersion::V0 => match prog.len() { @@ -655,10 +637,7 @@ impl Address { /// Constructs an [`Address`] from an output script (`scriptPubkey`). pub fn from_script(script: &script::Script, network: Network) -> Option
{ - Some(Address { - payload: Payload::from_script(script)?, - network, - }) + Some(Address { payload: Payload::from_script(script)?, network }) } /// Generates a script pubkey spending to this address. @@ -704,14 +683,14 @@ impl Address { pub fn is_valid_for_network(&self, network: Network) -> bool { let is_legacy = match self.address_type() { Some(AddressType::P2pkh) | Some(AddressType::P2sh) => true, - _ => false + _ => false, }; match (self.network, network) { (a, b) if a == b => true, (Network::Bitcoin, _) | (_, Network::Bitcoin) => false, (Network::Regtest, _) | (_, Network::Regtest) if !is_legacy => false, - (Network::Testnet, _) | (Network::Regtest, _) | (Network::Signet, _) => true + (Network::Testnet, _) | (Network::Regtest, _) | (Network::Signet, _) => true, } } @@ -725,7 +704,9 @@ impl Address { let payload = self.payload_as_bytes(); let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); - (*pubkey_hash == *payload) || (xonly_pubkey.serialize() == *payload) || (*segwit_redeem_hash(&pubkey_hash) == *payload) + (*pubkey_hash == *payload) + || (xonly_pubkey.serialize() == *payload) + || (*segwit_redeem_hash(&pubkey_hash) == *payload) } /// Returns true if the supplied xonly public key can be used to derive the address. @@ -838,10 +819,7 @@ impl FromStr for Address { } return Ok(Address { - payload: Payload::WitnessProgram { - version, - program, - }, + payload: Payload::WitnessProgram { version, program }, network, }); } @@ -875,10 +853,7 @@ impl FromStr for Address { x => return Err(Error::Base58(base58::Error::InvalidAddressVersion(x))), }; - Ok(Address { - network, - payload, - }) + Ok(Address { network, payload }) } } @@ -900,12 +875,11 @@ fn segwit_redeem_hash(pubkey_hash: &[u8]) -> ::hashes::hash160::Hash { mod tests { use core::str::FromStr; - use hashes::hex::{FromHex, ToHex}; - use blockdata::script::Script; + use hashes::hex::{FromHex, ToHex}; use network::constants::Network::{Bitcoin, Testnet}; - use util::key::PublicKey; use secp256k1::XOnlyPublicKey; + use util::key::PublicKey; use super::*; @@ -935,7 +909,9 @@ mod tests { fn test_p2pkh_address_58() { let addr = Address { network: Bitcoin, - payload: Payload::PubkeyHash(hex_pubkeyhash!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")), + payload: Payload::PubkeyHash(hex_pubkeyhash!( + "162c5ea71c0b23f5b9022ef047c4a86470a5b070" + )), }; assert_eq!( @@ -964,7 +940,9 @@ mod tests { fn test_p2sh_address_58() { let addr = Address { network: Bitcoin, - payload: Payload::ScriptHash(hex_scripthash!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")), + payload: Payload::ScriptHash(hex_scripthash!( + "162c5ea71c0b23f5b9022ef047c4a86470a5b070" + )), }; assert_eq!( @@ -986,7 +964,7 @@ mod tests { } #[test] - fn test_p2sh_parse_for_large_script(){ + fn test_p2sh_parse_for_large_script() { let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123"); assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize)); } @@ -994,7 +972,8 @@ mod tests { #[test] fn test_p2wpkh() { // stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20 - let mut key = hex_key!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"); + let mut key = + hex_key!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"); let addr = Address::p2wpkh(&key, Bitcoin).unwrap(); assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); assert_eq!(addr.address_type(), Some(AddressType::P2wpkh)); @@ -1021,7 +1000,8 @@ mod tests { #[test] fn test_p2shwpkh() { // stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01 - let mut key = hex_key!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"); + let mut key = + hex_key!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"); let addr = Address::p2shwpkh(&key, Bitcoin).unwrap(); assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); @@ -1049,10 +1029,7 @@ mod tests { "654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4" ); let addr = Address { - payload: Payload::WitnessProgram { - version: WitnessVersion::V13, - program: program, - }, + payload: Payload::WitnessProgram { version: WitnessVersion::V13, program: program }, network: Network::Bitcoin, }; roundtrips(&addr); @@ -1064,11 +1041,20 @@ mod tests { ("1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY", Some(AddressType::P2pkh)), ("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k", Some(AddressType::P2sh)), ("bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw", Some(AddressType::P2wpkh)), - ("bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", Some(AddressType::P2wsh)), - ("bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", Some(AddressType::P2tr)), + ( + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", + Some(AddressType::P2wsh), + ), + ( + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", + Some(AddressType::P2tr), + ), // Related to future extensions, addresses are valid but have no type // segwit v1 and len != 32 - ("bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y", None), + ( + "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y", + None, + ), // segwit v2 ("bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", None), ]; @@ -1125,7 +1111,6 @@ mod tests { "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j", // Empty data section "bc1gmk9yu", - // 2. BIP-173 test vectors // Invalid human-readable part "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", @@ -1221,14 +1206,21 @@ mod tests { #[test] fn test_qr_string() { - for el in ["132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"].iter() { + for el in + ["132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"].iter() + { let addr = Address::from_str(el).unwrap(); assert_eq!(addr.to_qr_uri(), format!("bitcoin:{}", el)); } - for el in ["bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl", "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej"].iter() { + for el in [ + "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl", + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", + ] + .iter() + { let addr = Address::from_str(el).unwrap(); - assert_eq!(addr.to_qr_uri(), format!("BITCOIN:{}", el.to_ascii_uppercase()) ); + assert_eq!(addr.to_qr_uri(), format!("BITCOIN:{}", el.to_ascii_uppercase())); } } @@ -1236,49 +1228,40 @@ mod tests { fn test_valid_networks() { let legacy_payload = &[ Payload::PubkeyHash(PubkeyHash::default()), - Payload::ScriptHash(ScriptHash::default()) + Payload::ScriptHash(ScriptHash::default()), ]; - let segwit_payload = (0..=16).map(|version| { - Payload::WitnessProgram { + let segwit_payload = (0..=16) + .map(|version| Payload::WitnessProgram { version: WitnessVersion::from_num(version).unwrap(), - program: vec![] - } - }).collect::>(); + program: vec![], + }) + .collect::>(); - const LEGACY_EQUIVALENCE_CLASSES: &[&[Network]] = &[ - &[Network::Bitcoin], - &[Network::Testnet, Network::Regtest, Network::Signet], - ]; - const SEGWIT_EQUIVALENCE_CLASSES: &[&[Network]] = &[ - &[Network::Bitcoin], - &[Network::Regtest], - &[Network::Testnet, Network::Signet], - ]; + const LEGACY_EQUIVALENCE_CLASSES: &[&[Network]] = + &[&[Network::Bitcoin], &[Network::Testnet, Network::Regtest, Network::Signet]]; + const SEGWIT_EQUIVALENCE_CLASSES: &[&[Network]] = + &[&[Network::Bitcoin], &[Network::Regtest], &[Network::Testnet, Network::Signet]]; fn test_addr_type(payloads: &[Payload], equivalence_classes: &[&[Network]]) { for pl in payloads { for addr_net in equivalence_classes.iter().map(|ec| ec.iter()).flatten() { - for valid_net in equivalence_classes.iter() + for valid_net in equivalence_classes + .iter() .filter(|ec| ec.contains(addr_net)) .map(|ec| ec.iter()) .flatten() { - let addr = Address { - payload: pl.clone(), - network: *addr_net - }; + let addr = Address { payload: pl.clone(), network: *addr_net }; assert!(addr.is_valid_for_network(*valid_net)); } - for invalid_net in equivalence_classes.iter() + for invalid_net in equivalence_classes + .iter() .filter(|ec| !ec.contains(addr_net)) .map(|ec| ec.iter()) .flatten() { - let addr = Address { - payload: pl.clone(), - network: *addr_net - }; + let addr = Address { payload: pl.clone(), network: *addr_net }; assert!(!addr.is_valid_for_network(*invalid_net)); } } @@ -1292,10 +1275,16 @@ mod tests { #[test] fn p2tr_from_untweaked() { //Test case from BIP-086 - let internal_key = XOnlyPublicKey::from_str("cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115").unwrap(); + let internal_key = XOnlyPublicKey::from_str( + "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115", + ) + .unwrap(); let secp = Secp256k1::verification_only(); let address = Address::p2tr(&secp, internal_key, None, Network::Bitcoin); - assert_eq!(address.to_string(), "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"); + assert_eq!( + address.to_string(), + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr" + ); assert_eq!(address.address_type(), Some(AddressType::P2tr)); roundtrips(&address); } @@ -1311,7 +1300,10 @@ mod tests { let result = address.is_related_to_pubkey(&pubkey); assert!(result); - let unused_pubkey = PublicKey::from_str("02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c").expect("pubkey"); + let unused_pubkey = PublicKey::from_str( + "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c", + ) + .expect("pubkey"); assert!(!address.is_related_to_pubkey(&unused_pubkey)) } @@ -1326,7 +1318,10 @@ mod tests { let result = address.is_related_to_pubkey(&pubkey); assert!(result); - let unused_pubkey = PublicKey::from_str("02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c").expect("pubkey"); + let unused_pubkey = PublicKey::from_str( + "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c", + ) + .expect("pubkey"); assert!(!address.is_related_to_pubkey(&unused_pubkey)) } @@ -1341,7 +1336,10 @@ mod tests { let result = address.is_related_to_pubkey(&pubkey); assert!(result); - let unused_pubkey = PublicKey::from_str("02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c").expect("pubkey"); + let unused_pubkey = PublicKey::from_str( + "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c", + ) + .expect("pubkey"); assert!(!address.is_related_to_pubkey(&unused_pubkey)) } @@ -1356,36 +1354,50 @@ mod tests { let result = address.is_related_to_pubkey(&pubkey); assert!(result); - let unused_pubkey = PublicKey::from_str("02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c").expect("pubkey"); + let unused_pubkey = PublicKey::from_str( + "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c", + ) + .expect("pubkey"); assert!(!address.is_related_to_pubkey(&unused_pubkey)) } #[test] - fn test_is_related_to_pubkey_p2tr(){ + fn test_is_related_to_pubkey_p2tr() { let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin); - assert_eq!(address, Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e").expect("address")); + assert_eq!( + address, + Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e") + .expect("address") + ); let result = address.is_related_to_pubkey(&pubkey); assert!(result); - let unused_pubkey = PublicKey::from_str("02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c").expect("pubkey"); + let unused_pubkey = PublicKey::from_str( + "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c", + ) + .expect("pubkey"); assert!(!address.is_related_to_pubkey(&unused_pubkey)); } #[test] - fn test_is_related_to_xonly_pubkey(){ + fn test_is_related_to_xonly_pubkey() { let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin); - assert_eq!(address, Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e").expect("address")); + assert_eq!( + address, + Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e") + .expect("address") + ); let result = address.is_related_to_xonly_pubkey(&xonly_pubkey); assert!(result); diff --git a/src/util/amount.rs b/src/util/amount.rs index c9cca68463..255ec35a9d 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -14,10 +14,12 @@ //! We refer to the documentation on the types for more information. //! -use prelude::*; - -use core::{ops, default, str::FromStr, cmp::Ordering}; +use core::cmp::Ordering; use core::fmt::{self, Write}; +use core::str::FromStr; +use core::{default, ops}; + +use prelude::*; /// A set of denominations in which amounts can be expressed. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] @@ -82,13 +84,15 @@ impl FromStr for Denomination { /// /// Due to ambiguity between mega and milli, pico and peta we prohibit usage of leading capital 'M', 'P'. fn from_str(s: &str) -> Result { - use self::ParseAmountError::*; use self::Denomination as D; + use self::ParseAmountError::*; let starts_with_uppercase = || s.starts_with(char::is_uppercase); match denomination_from_str(s) { None => Err(UnknownDenomination(s.to_owned())), - Some(D::MilliBitcoin) | Some(D::PicoBitcoin) | Some(D::MilliSatoshi) if starts_with_uppercase() => { + Some(D::MilliBitcoin) | Some(D::PicoBitcoin) | Some(D::MilliSatoshi) + if starts_with_uppercase() => + { Err(PossiblyConfusingDenomination(s.to_owned())) } Some(D::NanoBitcoin) | Some(D::MicroBitcoin) if starts_with_uppercase() => { @@ -159,7 +163,7 @@ pub enum ParseAmountError { /// The denomination was unknown. UnknownDenomination(String), /// The denomination has multiple possible interpretations. - PossiblyConfusingDenomination(String) + PossiblyConfusingDenomination(String), } impl fmt::Display for ParseAmountError { @@ -171,7 +175,9 @@ impl fmt::Display for ParseAmountError { ParseAmountError::InvalidFormat => f.write_str("invalid number format"), ParseAmountError::InputTooLarge => f.write_str("input string was too large"), ParseAmountError::InvalidCharacter(c) => write!(f, "invalid character in input: {}", c), - ParseAmountError::UnknownDenomination(ref d) => write!(f, "unknown denomination: {}", d), + ParseAmountError::UnknownDenomination(ref d) => { + write!(f, "unknown denomination: {}", d) + } ParseAmountError::PossiblyConfusingDenomination(ref d) => { let (letter, upper, lower) = match d.chars().next() { Some('M') => ('M', "Mega", "milli"), @@ -723,7 +729,7 @@ impl SignedAmount { pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result { let sats = self.as_sat().checked_abs().map(|a: i64| a as u64).unwrap_or_else(|| { // We could also hard code this into `9223372036854775808` - u64::max_value() - self.as_sat() as u64 +1 + u64::max_value() - self.as_sat() as u64 + 1 }); fmt_satoshi_in(sats, self.is_negative(), f, denom) } @@ -774,7 +780,6 @@ impl SignedAmount { self.0.is_negative() } - /// Get the absolute value of this [SignedAmount]. /// Returns [None] if overflow occurred. (`self == min_value()`) pub fn checked_abs(self) -> Option { @@ -946,18 +951,21 @@ pub trait CheckedSum: private::SumSeal { fn checked_sum(self) -> Option; } -impl CheckedSum for T where T: Iterator { +impl CheckedSum for T +where + T: Iterator, +{ fn checked_sum(mut self) -> Option { let first = Some(self.next().unwrap_or_default()); - self.fold( - first, - |acc, item| acc.and_then(|acc| acc.checked_add(item)) - ) + self.fold(first, |acc, item| acc.and_then(|acc| acc.checked_add(item))) } } -impl CheckedSum for T where T: Iterator { +impl CheckedSum for T +where + T: Iterator, +{ fn checked_sum(mut self) -> Option { let first = Some(self.next().unwrap_or_default()); @@ -966,13 +974,13 @@ impl CheckedSum for T where T: Iterator { } mod private { - use ::{Amount, SignedAmount}; + use {Amount, SignedAmount}; /// Used to seal the `CheckedSum` trait pub trait SumSeal {} - impl SumSeal for T where T: Iterator {} - impl SumSeal for T where T: Iterator {} + impl SumSeal for T where T: Iterator {} + impl SumSeal for T where T: Iterator {} } #[cfg(feature = "serde")] @@ -1101,11 +1109,12 @@ pub mod serde { //! Serialize and deserialize [`Option`](crate::Amount) as real numbers denominated in satoshi. //! Use with `#[serde(default, with = "amount::serde::as_sat::opt")]`. - use serde::{Deserializer, Serializer, de}; - use util::amount::serde::SerdeAmountForOpt; use core::fmt; use core::marker::PhantomData; + use serde::{de, Deserializer, Serializer}; + use util::amount::serde::SerdeAmountForOpt; + pub fn serialize( a: &Option, s: S, @@ -1165,11 +1174,12 @@ pub mod serde { //! Serialize and deserialize [Option] as JSON numbers denominated in BTC. //! Use with `#[serde(default, with = "amount::serde::as_btc::opt")]`. - use serde::{Deserializer, Serializer, de}; - use util::amount::serde::SerdeAmountForOpt; use core::fmt; use core::marker::PhantomData; + use serde::{de, Deserializer, Serializer}; + use util::amount::serde::SerdeAmountForOpt; + pub fn serialize( a: &Option, s: S, @@ -1213,14 +1223,15 @@ pub mod serde { #[cfg(test)] mod tests { - use super::*; + use core::str::FromStr; #[cfg(feature = "std")] use std::panic; - use core::str::FromStr; #[cfg(feature = "serde")] use serde_test; + use super::*; + #[test] fn add_sub_mul_div() { let sat = Amount::from_sat; @@ -1360,13 +1371,22 @@ mod tests { // make sure satoshi > i64::max_value() is checked. let amount = Amount::from_sat(i64::max_value() as u64); assert_eq!(Amount::from_str_in(&amount.to_string_in(sat), sat), Ok(amount)); - assert_eq!(Amount::from_str_in(&(amount+Amount(1)).to_string_in(sat), sat), Err(E::TooBig)); + assert_eq!( + Amount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat), + Err(E::TooBig) + ); assert_eq!(p("12.000", Denomination::MilliSatoshi), Err(E::TooPrecise)); // exactly 50 chars. - assert_eq!(p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin), Err(E::TooBig)); + assert_eq!( + p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin), + Err(E::TooBig) + ); // more than 50 chars. - assert_eq!(p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin), Err(E::InputTooLarge)); + assert_eq!( + p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin), + Err(E::InputTooLarge) + ); } #[test] @@ -1398,9 +1418,9 @@ mod tests { let ua = Amount::from_sat; assert_eq!(Amount::max_value().to_signed(), Err(E::TooBig)); - assert_eq!(ua(i64::max_value() as u64).to_signed(), Ok(sa(i64::max_value()))); + assert_eq!(ua(i64::max_value() as u64).to_signed(), Ok(sa(i64::max_value()))); assert_eq!(ua(0).to_signed(), Ok(sa(0))); - assert_eq!(ua(1).to_signed(), Ok( sa(1))); + assert_eq!(ua(1).to_signed(), Ok(sa(1))); assert_eq!(ua(1).to_signed(), Ok(sa(1))); assert_eq!(ua(i64::max_value() as u64 + 1).to_signed(), Err(E::TooBig)); @@ -1409,7 +1429,10 @@ mod tests { assert_eq!(sa(0).to_unsigned().unwrap().to_signed(), Ok(sa(0))); assert_eq!(sa(1).to_unsigned().unwrap().to_signed(), Ok(sa(1))); - assert_eq!(sa(i64::max_value()).to_unsigned().unwrap().to_signed(), Ok(sa(i64::max_value()))); + assert_eq!( + sa(i64::max_value()).to_unsigned().unwrap().to_signed(), + Ok(sa(i64::max_value())) + ); } #[test] @@ -1469,30 +1492,65 @@ mod tests { assert_eq!("2535830000", Amount::from_sat(253583).to_string_in(D::PicoBitcoin)); assert_eq!("-100000000", SignedAmount::from_sat(-10_000).to_string_in(D::PicoBitcoin)); - - assert_eq!(ua_str(&ua_sat(0).to_string_in(D::Satoshi), D::Satoshi), Ok(ua_sat(0))); assert_eq!(ua_str(&ua_sat(500).to_string_in(D::Bitcoin), D::Bitcoin), Ok(ua_sat(500))); - assert_eq!(ua_str(&ua_sat(21_000_000).to_string_in(D::Bit), D::Bit), Ok(ua_sat(21_000_000))); - assert_eq!(ua_str(&ua_sat(1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(ua_sat(1))); - assert_eq!(ua_str(&ua_sat(1_000_000_000_000).to_string_in(D::MilliBitcoin), D::MilliBitcoin), Ok(ua_sat(1_000_000_000_000))); - assert_eq!(ua_str(&ua_sat(u64::max_value()).to_string_in(D::MilliBitcoin), D::MilliBitcoin), Err(ParseAmountError::TooBig)); + assert_eq!( + ua_str(&ua_sat(21_000_000).to_string_in(D::Bit), D::Bit), + Ok(ua_sat(21_000_000)) + ); + assert_eq!( + ua_str(&ua_sat(1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), + Ok(ua_sat(1)) + ); + assert_eq!( + ua_str(&ua_sat(1_000_000_000_000).to_string_in(D::MilliBitcoin), D::MilliBitcoin), + Ok(ua_sat(1_000_000_000_000)) + ); + assert_eq!( + ua_str(&ua_sat(u64::max_value()).to_string_in(D::MilliBitcoin), D::MilliBitcoin), + Err(ParseAmountError::TooBig) + ); - assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(sa_sat(-1))); + assert_eq!( + sa_str(&sa_sat(-1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), + Ok(sa_sat(-1)) + ); - assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig)); + assert_eq!( + sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::MicroBitcoin), + Err(ParseAmountError::TooBig) + ); // Test an overflow bug in `abs()` - assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig)); - - assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin), Ok(sa_sat(-1))); - assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise)); - assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise)); - - assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin), Ok(sa_sat(-1))); - assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise)); - assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise)); + assert_eq!( + sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::MicroBitcoin), + Err(ParseAmountError::TooBig) + ); + assert_eq!( + sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin), + Ok(sa_sat(-1)) + ); + assert_eq!( + sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::NanoBitcoin), + Err(ParseAmountError::TooPrecise) + ); + assert_eq!( + sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::NanoBitcoin), + Err(ParseAmountError::TooPrecise) + ); + assert_eq!( + sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin), + Ok(sa_sat(-1)) + ); + assert_eq!( + sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::PicoBitcoin), + Err(ParseAmountError::TooPrecise) + ); + assert_eq!( + sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::PicoBitcoin), + Err(ParseAmountError::TooPrecise) + ); } #[test] @@ -1516,7 +1574,6 @@ mod tests { #[cfg(feature = "serde")] #[test] fn serde_as_sat() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] struct T { #[serde(with = "::util::amount::serde::as_sat")] @@ -1592,15 +1649,12 @@ mod tests { amt: Some(Amount::from_sat(2__500_000_00)), samt: Some(SignedAmount::from_sat(-2__500_000_00)), }; - let without = T { - amt: None, - samt: None, - }; + let without = T { amt: None, samt: None }; // Test Roundtripping for s in [&with, &without].iter() { let v = serde_json::to_string(s).unwrap(); - let w : T = serde_json::from_str(&v).unwrap(); + let w: T = serde_json::from_str(&v).unwrap(); assert_eq!(w, **s); } @@ -1635,15 +1689,12 @@ mod tests { amt: Some(Amount::from_sat(2__500_000_00)), samt: Some(SignedAmount::from_sat(-2__500_000_00)), }; - let without = T { - amt: None, - samt: None, - }; + let without = T { amt: None, samt: None }; // Test Roundtripping for s in [&with, &without].iter() { let v = serde_json::to_string(s).unwrap(); - let w : T = serde_json::from_str(&v).unwrap(); + let w: T = serde_json::from_str(&v).unwrap(); assert_eq!(w, **s); } @@ -1666,18 +1717,14 @@ mod tests { assert_eq!(Amount::from_sat(0), vec![].into_iter().sum::()); assert_eq!(SignedAmount::from_sat(0), vec![].into_iter().sum::()); - let amounts = vec![ - Amount::from_sat(42), - Amount::from_sat(1337), - Amount::from_sat(21) - ]; + let amounts = vec![Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)]; let sum = amounts.into_iter().sum::(); assert_eq!(Amount::from_sat(1400), sum); let amounts = vec![ SignedAmount::from_sat(-42), SignedAmount::from_sat(1337), - SignedAmount::from_sat(21) + SignedAmount::from_sat(21), ]; let sum = amounts.into_iter().sum::(); assert_eq!(SignedAmount::from_sat(1316), sum); @@ -1688,26 +1735,19 @@ mod tests { assert_eq!(Some(Amount::from_sat(0)), vec![].into_iter().checked_sum()); assert_eq!(Some(SignedAmount::from_sat(0)), vec![].into_iter().checked_sum()); - let amounts = vec![ - Amount::from_sat(42), - Amount::from_sat(1337), - Amount::from_sat(21) - ]; + let amounts = vec![Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)]; let sum = amounts.into_iter().checked_sum(); assert_eq!(Some(Amount::from_sat(1400)), sum); - let amounts = vec![ - Amount::from_sat(u64::max_value()), - Amount::from_sat(1337), - Amount::from_sat(21) - ]; + let amounts = + vec![Amount::from_sat(u64::max_value()), Amount::from_sat(1337), Amount::from_sat(21)]; let sum = amounts.into_iter().checked_sum(); assert_eq!(None, sum); let amounts = vec![ SignedAmount::from_sat(i64::min_value()), SignedAmount::from_sat(-1), - SignedAmount::from_sat(21) + SignedAmount::from_sat(21), ]; let sum = amounts.into_iter().checked_sum(); assert_eq!(None, sum); @@ -1715,7 +1755,7 @@ mod tests { let amounts = vec![ SignedAmount::from_sat(i64::max_value()), SignedAmount::from_sat(1), - SignedAmount::from_sat(21) + SignedAmount::from_sat(21), ]; let sum = amounts.into_iter().checked_sum(); assert_eq!(None, sum); @@ -1723,7 +1763,7 @@ mod tests { let amounts = vec![ SignedAmount::from_sat(42), SignedAmount::from_sat(3301), - SignedAmount::from_sat(21) + SignedAmount::from_sat(21), ]; let sum = amounts.into_iter().checked_sum(); assert_eq!(Some(SignedAmount::from_sat(3364)), sum); @@ -1732,7 +1772,10 @@ mod tests { #[test] fn denomination_string_acceptable_forms() { // Non-exhaustive list of valid forms. - let valid = vec!["BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI","Satoshi", "Satoshis", "satoshis", "SAT", "Sat", "sats", "bit", "bits", "nBTC", "pBTC"]; + let valid = vec![ + "BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI", "Satoshi", "Satoshis", + "satoshis", "SAT", "Sat", "sats", "bit", "bits", "nBTC", "pBTC", + ]; for denom in valid.iter() { assert!(Denomination::from_str(denom).is_ok()); } @@ -1741,11 +1784,12 @@ mod tests { #[test] fn disallow_confusing_forms() { // Non-exhaustive list of confusing forms. - let confusing = vec!["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"]; + let confusing = + vec!["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"]; for denom in confusing.iter() { - match Denomination::from_str(denom) { + match Denomination::from_str(denom) { Ok(_) => panic!("from_str should error for {}", denom), - Err(ParseAmountError::PossiblyConfusingDenomination(_)) => {}, + Err(ParseAmountError::PossiblyConfusingDenomination(_)) => {} Err(e) => panic!("unexpected error: {}", e), } } @@ -1756,12 +1800,11 @@ mod tests { // Non-exhaustive list of unknown forms. let unknown = vec!["NBTC", "UBTC", "ABC", "abc"]; for denom in unknown.iter() { - match Denomination::from_str(denom) { + match Denomination::from_str(denom) { Ok(_) => panic!("from_str should error for {}", denom), - Err(ParseAmountError::UnknownDenomination(_)) => {}, + Err(ParseAmountError::UnknownDenomination(_)) => {} Err(e) => panic!("unexpected error: {}", e), } } } } - diff --git a/src/util/base58.rs b/src/util/base58.rs index 5118d1e63b..25ae6a6f69 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -18,13 +18,11 @@ //! strings respectively. //! -use prelude::*; - -use core::{fmt, str, iter, slice}; +use core::{fmt, iter, slice, str}; -use hashes::{sha256d, Hash, hex}; +use hashes::{hex, sha256d, Hash}; +use prelude::*; use secp256k1; - use util::{endian, key}; /// An error that might occur during base58 decoding @@ -48,20 +46,26 @@ pub enum Error { Secp256k1(secp256k1::Error), /// Hex decoding error // TODO: Remove this as part of crate-smashing, there should not be any key related errors in this module - Hex(hex::Error) + Hex(hex::Error), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::BadByte(b) => write!(f, "invalid base58 character 0x{:x}", b), - Error::BadChecksum(exp, actual) => write!(f, "base58ck checksum 0x{:x} does not match expected 0x{:x}", actual, exp), + Error::BadChecksum(exp, actual) => { + write!(f, "base58ck checksum 0x{:x} does not match expected 0x{:x}", actual, exp) + } Error::InvalidLength(ell) => write!(f, "length {} invalid for this base58 type", ell), - Error::InvalidAddressVersion(ref v) => write!(f, "address version {} is invalid for this base58 type", v), - Error::InvalidExtendedKeyVersion(ref v) => write!(f, "extended key version {:#04x?} is invalid for this base58 type", v), + Error::InvalidAddressVersion(ref v) => { + write!(f, "address version {} is invalid for this base58 type", v) + } + Error::InvalidExtendedKeyVersion(ref v) => { + write!(f, "extended key version {:#04x?} is invalid for this base58 type", v) + } Error::TooShort(_) => write!(f, "base58ck data not even long enough for a checksum"), Error::Secp256k1(ref e) => fmt::Display::fmt(&e, f), - Error::Hex(ref e) => write!(f, "Hexadecimal decoding error: {}", e) + Error::Hex(ref e) => write!(f, "Hexadecimal decoding error: {}", e), } } } @@ -141,7 +145,9 @@ pub fn from(data: &str) -> Result, Error> { } let mut carry = match BASE58_DIGITS[d58 as usize] { Some(d58) => d58 as u32, - None => { return Err(Error::BadByte(d58)); } + None => { + return Err(Error::BadByte(d58)); + } }; for d256 in scratch.iter_mut().rev() { carry += *d256 as u32 * 58; @@ -152,9 +158,7 @@ pub fn from(data: &str) -> Result, Error> { } // Copy leading zeroes directly - let mut ret: Vec = data.bytes().take_while(|&x| x == BASE58_CHARS[0]) - .map(|_| 0) - .collect(); + let mut ret: Vec = data.bytes().take_while(|&x| x == BASE58_CHARS[0]).map(|_| 0).collect(); // Copy rest of string ret.extend(scratch.into_iter().skip_while(|&x| x == 0)); Ok(ret) @@ -179,8 +183,8 @@ pub fn from_check(data: &str) -> Result, Error> { fn format_iter(writer: &mut W, data: I) -> Result<(), fmt::Error> where - I: Iterator + Clone, - W: fmt::Write + I: Iterator + Clone, + W: fmt::Write, { let mut ret = SmallVec::new(); @@ -220,14 +224,13 @@ where fn encode_iter(data: I) -> String where - I: Iterator + Clone, + I: Iterator + Clone, { let mut ret = String::new(); format_iter(&mut ret, data).expect("writing into string shouldn't fail"); ret } - /// Directly encode a slice as base58 pub fn encode_slice(data: &[u8]) -> String { encode_iter(data.iter().cloned()) @@ -237,20 +240,14 @@ pub fn encode_slice(data: &[u8]) -> String { /// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.) pub fn check_encode_slice(data: &[u8]) -> String { let checksum = sha256d::Hash::hash(data); - encode_iter( - data.iter() - .cloned() - .chain(checksum[0..4].iter().cloned()) - ) + encode_iter(data.iter().cloned().chain(checksum[0..4].iter().cloned())) } /// Obtain a string with the base58check encoding of a slice /// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.) pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result { let checksum = sha256d::Hash::hash(data); - let iter = data.iter() - .cloned() - .chain(checksum[0..4].iter().cloned()); + let iter = data.iter().cloned().chain(checksum[0..4].iter().cloned()); format_iter(fmt, iter) } @@ -261,16 +258,17 @@ impl From for Error { key::Error::Secp256k1(e) => Error::Secp256k1(e), key::Error::Base58(e) => e, key::Error::InvalidKeyPrefix(_) => Error::Secp256k1(secp256k1::Error::InvalidPublicKey), - key::Error::Hex(e) => Error::Hex(e) + key::Error::Hex(e) => Error::Hex(e), } } } #[cfg(test)] mod tests { - use super::*; use hashes::hex::FromHex; + use super::*; + #[test] fn test_base58_encode() { // Basics @@ -284,9 +282,13 @@ mod tests { assert_eq!(&encode_slice(&[0, 0, 0, 0, 13, 36][..]), "1111211"); // Long input (>100 bytes => has to use heap) - let res = encode_slice(&"BitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBit\ - coinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoin".as_bytes()); - let exp = "ZqC5ZdfpZRi7fjA8hbhX5pEE96MdH9hEaC1YouxscPtbJF16qVWksHWR4wwvx7MotFcs2ChbJqK8KJ9X\ + let res = encode_slice( + &"BitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBit\ + coinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoin" + .as_bytes(), + ); + let exp = + "ZqC5ZdfpZRi7fjA8hbhX5pEE96MdH9hEaC1YouxscPtbJF16qVWksHWR4wwvx7MotFcs2ChbJqK8KJ9X\ wZznwWn1JFDhhTmGo9v6GjAVikzCsBWZehu7bm22xL8b5zBR5AsBygYRwbFJsNwNkjpyFuDKwmsUTKvkULCvucPJrN5\ QUdxpGakhqkZFL7RU4yT"; assert_eq!(&res, exp); @@ -309,8 +311,10 @@ mod tests { assert_eq!(from("111211").ok(), Some(vec![0u8, 0, 0, 13, 36])); // Addresses - assert_eq!(from_check("1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH").ok(), - Some(Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap())); + assert_eq!( + from_check("1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH").ok(), + Some(Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap()) + ); // Non Base58 char. assert_eq!(from("¢").unwrap_err(), Error::BadByte(194)); } @@ -325,8 +329,6 @@ mod tests { // Check that empty slice passes roundtrip. assert_eq!(from_check(&check_encode_slice(&[])), Ok(vec![])); // Check that `len > 4` is enforced. - assert_eq!(from_check(&encode_slice(&[1,2,3])), Err(Error::TooShort(3))); - + assert_eq!(from_check(&encode_slice(&[1, 2, 3])), Err(Error::TooShort(3))); } } - diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 7cd2ab9c8d..8148260d03 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -19,15 +19,15 @@ //! signatures, which are placed in the scriptSig. //! -use hashes::Hash; -use hash_types::Sighash; +use core::ops::{Deref, DerefMut}; + use blockdata::script::Script; +use blockdata::transaction::{EcdsaSighashType, Transaction, TxIn}; use blockdata::witness::Witness; -use blockdata::transaction::{Transaction, TxIn, EcdsaSighashType}; use consensus::{encode, Encodable}; - +use hash_types::Sighash; +use hashes::Hash; use io; -use core::ops::{Deref, DerefMut}; use util::sighash; /// Parts of a sighash which are common across inputs or signatures, and which are @@ -92,10 +92,7 @@ impl SighashComponents { self.tx_version.consensus_encode(&mut enc).expect("engines don't error"); self.hash_prevouts.consensus_encode(&mut enc).expect("engines don't error"); self.hash_sequence.consensus_encode(&mut enc).expect("engines don't error"); - txin - .previous_output - .consensus_encode(&mut enc) - .expect("engines don't error"); + txin.previous_output.consensus_encode(&mut enc).expect("engines don't error"); script_code.consensus_encode(&mut enc).expect("engines don't error"); value.consensus_encode(&mut enc).expect("engines don't error"); txin.sequence.consensus_encode(&mut enc).expect("engines don't error"); @@ -145,7 +142,7 @@ impl> SigHashCache { input_index: usize, script_code: &Script, value: u64, - sighash_type: EcdsaSighashType + sighash_type: EcdsaSighashType, ) -> Sighash { let mut enc = Sighash::engine(); self.encode_signing_data_to(&mut enc, input_index, script_code, value, sighash_type) @@ -188,14 +185,15 @@ impl> SigHashCache { #[allow(deprecated)] mod tests { use std::str::FromStr; - use hash_types::Sighash; + use blockdata::script::Script; use blockdata::transaction::Transaction; use consensus::encode::deserialize; + use hash_types::Sighash; + use hashes::hex::FromHex; use network::constants::Network; use util::address::Address; use util::key::PublicKey; - use hashes::hex::FromHex; use super::*; @@ -205,7 +203,14 @@ mod tests { witness_script } - fn run_test_sighash_bip143(tx: &str, script: &str, input_index: usize, value: u64, hash_type: u32, expected_result: &str) { + fn run_test_sighash_bip143( + tx: &str, + script: &str, + input_index: usize, + value: u64, + hash_type: u32, + expected_result: &str, + ) { let tx: Transaction = deserialize(&Vec::::from_hex(tx).unwrap()[..]).unwrap(); let script = Script::from(Vec::::from_hex(script).unwrap()); let raw_expected = Sighash::from_hex(expected_result).unwrap(); @@ -227,7 +232,8 @@ mod tests { ).unwrap()[..], ).unwrap(); - let witness_script = p2pkh_hex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"); + let witness_script = + p2pkh_hex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"); let value = 600_000_000; let comp = SighashComponents::new(&tx); @@ -237,13 +243,16 @@ mod tests { tx_version: 1, tx_locktime: 17, hash_prevouts: hex_hash!( - Sighash, "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37" + Sighash, + "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37" ), hash_sequence: hex_hash!( - Sighash, "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b" + Sighash, + "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b" ), hash_outputs: hex_hash!( - Sighash, "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5" + Sighash, + "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5" ), } ); @@ -264,7 +273,8 @@ mod tests { ).unwrap()[..], ).unwrap(); - let witness_script = p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873"); + let witness_script = + p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873"); let value = 1_000_000_000; let comp = SighashComponents::new(&tx); assert_eq!( @@ -273,13 +283,16 @@ mod tests { tx_version: 1, tx_locktime: 1170, hash_prevouts: hex_hash!( - Sighash, "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a" + Sighash, + "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a" ), hash_sequence: hex_hash!( - Sighash, "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198" + Sighash, + "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198" ), hash_outputs: hex_hash!( - Sighash, "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83" + Sighash, + "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83" ), } ); @@ -316,13 +329,16 @@ mod tests { tx_version: 1, tx_locktime: 0, hash_prevouts: hex_hash!( - Sighash, "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0" + Sighash, + "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0" ), hash_sequence: hex_hash!( - Sighash, "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044" + Sighash, + "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044" ), hash_outputs: hex_hash!( - Sighash, "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc" + Sighash, + "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc" ), } ); diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 1dc67ca1c2..3ed364050b 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -45,20 +45,18 @@ //! ``` //! -use prelude::*; - -use io::{self as io, Cursor}; -use core::fmt::{self, Display, Formatter}; use core::cmp::{self, Ordering}; - -use hashes::{Hash, siphash24}; -use hash_types::{BlockHash, FilterHash, FilterHeader}; +use core::fmt::{self, Display, Formatter}; use blockdata::block::Block; use blockdata::script::Script; use blockdata::transaction::OutPoint; -use consensus::{Decodable, Encodable}; use consensus::encode::VarInt; +use consensus::{Decodable, Encodable}; +use hash_types::{BlockHash, FilterHash, FilterHeader}; +use hashes::{siphash24, Hash}; +use io::{self as io, Cursor}; +use prelude::*; use util::endian; /// Golomb encoding parameter as in BIP-158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 @@ -82,7 +80,7 @@ impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { match *self { Error::UtxoMissing(ref coin) => write!(f, "unresolved UTXO {}", coin), - Error::Io(ref io) => write!(f, "{}", io) + Error::Io(ref io) => write!(f, "{}", io), } } } @@ -93,12 +91,11 @@ impl From for Error { } } - /// a computed or read block filter #[derive(Debug, Clone, PartialEq, Eq)] pub struct BlockFilter { /// Golomb encoded filter - pub content: Vec + pub content: Vec, } impl FilterHash { @@ -119,13 +116,15 @@ impl BlockFilter { } /// create a new filter from pre-computed data - pub fn new (content: &[u8]) -> BlockFilter { + pub fn new(content: &[u8]) -> BlockFilter { BlockFilter { content: content.to_vec() } } /// Compute a SCRIPT_FILTER that contains spent and output scripts pub fn new_script_filter(block: &Block, script_for_coin: M) -> Result - where M: Fn(&OutPoint) -> Result { + where + M: Fn(&OutPoint) -> Result, + { let mut out = Vec::new(); { let mut writer = BlockFilterWriter::new(&mut out, block); @@ -137,13 +136,21 @@ impl BlockFilter { } /// match any query pattern - pub fn match_any(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { + pub fn match_any( + &self, + block_hash: &BlockHash, + query: &mut dyn Iterator, + ) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_any(&mut Cursor::new(self.content.as_slice()), query) } /// match all query pattern - pub fn match_all(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { + pub fn match_all( + &self, + block_hash: &BlockHash, + query: &mut dyn Iterator, + ) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_all(&mut Cursor::new(self.content.as_slice()), query) } @@ -178,14 +185,20 @@ impl<'a> BlockFilterWriter<'a> { /// Add consumed output scripts of a block to filter pub fn add_input_scripts(&mut self, script_for_coin: M) -> Result<(), Error> - where M: Fn(&OutPoint) -> Result { - for script in self.block.txdata.iter() + where + M: Fn(&OutPoint) -> Result, + { + for script in self + .block + .txdata + .iter() .skip(1) // skip coinbase .flat_map(|t| t.input.iter().map(|i| &i.previous_output)) - .map(script_for_coin) { + .map(script_for_coin) + { match script { Ok(script) => self.add_element(script.as_bytes()), - Err(e) => return Err(e) + Err(e) => return Err(e), } } Ok(()) @@ -202,10 +215,9 @@ impl<'a> BlockFilterWriter<'a> { } } - /// Reads and interpret a block filter pub struct BlockFilterReader { - reader: GCSFilterReader + reader: GCSFilterReader, } impl BlockFilterReader { @@ -218,21 +230,28 @@ impl BlockFilterReader { } /// match any query pattern - pub fn match_any(&self, reader: &mut dyn io::Read, query: &mut dyn Iterator) -> Result { + pub fn match_any( + &self, + reader: &mut dyn io::Read, + query: &mut dyn Iterator, + ) -> Result { self.reader.match_any(reader, query) } /// match all query pattern - pub fn match_all(&self, reader: &mut dyn io::Read, query: &mut dyn Iterator) -> Result { + pub fn match_all( + &self, + reader: &mut dyn io::Read, + query: &mut dyn Iterator, + ) -> Result { self.reader.match_all(reader, query) } } - /// Golomb-Rice encoded filter reader pub struct GCSFilterReader { filter: GCSFilter, - m: u64 + m: u64, } impl GCSFilterReader { @@ -242,7 +261,11 @@ impl GCSFilterReader { } /// match any query pattern - pub fn match_any(&self, reader: &mut dyn io::Read, query: &mut dyn Iterator) -> Result { + pub fn match_any( + &self, + reader: &mut dyn io::Read, + query: &mut dyn Iterator, + ) -> Result { let mut decoder = reader; let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0)); let reader = &mut decoder; @@ -282,7 +305,11 @@ impl GCSFilterReader { } /// match all query pattern - pub fn match_all(&self, reader: &mut dyn io::Read, query: &mut dyn Iterator) -> Result { + pub fn match_all( + &self, + reader: &mut dyn io::Read, + query: &mut dyn Iterator, + ) -> Result { let mut decoder = reader; let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0)); let reader = &mut decoder; @@ -314,7 +341,7 @@ impl GCSFilterReader { } else { return Ok(false); } - }, + } Ordering::Greater => return Ok(false), } } @@ -333,17 +360,23 @@ pub struct GCSFilterWriter<'a> { filter: GCSFilter, writer: &'a mut dyn io::Write, elements: HashSet>, - m: u64 + m: u64, } impl<'a> GCSFilterWriter<'a> { /// Create a new GCS writer wrapping a generic writer, with specific seed to siphash - pub fn new(writer: &'a mut dyn io::Write, k0: u64, k1: u64, m: u64, p: u8) -> GCSFilterWriter<'a> { + pub fn new( + writer: &'a mut dyn io::Write, + k0: u64, + k1: u64, + m: u64, + p: u8, + ) -> GCSFilterWriter<'a> { GCSFilterWriter { filter: GCSFilter::new(k0, k1, p), writer, elements: HashSet::new(), - m + m, } } @@ -359,13 +392,18 @@ impl<'a> GCSFilterWriter<'a> { let nm = self.elements.len() as u64 * self.m; // map hashes to [0, n_elements * M) - let mut mapped: Vec<_> = self.elements.iter() - .map(|e| map_to_range(self.filter.hash(e.as_slice()), nm)).collect(); + let mut mapped: Vec<_> = self + .elements + .iter() + .map(|e| map_to_range(self.filter.hash(e.as_slice()), nm)) + .collect(); mapped.sort_unstable(); // write number of elements as varint let mut encoder = Vec::new(); - VarInt(mapped.len() as u64).consensus_encode(&mut encoder).expect("in-memory writers don't error"); + VarInt(mapped.len() as u64) + .consensus_encode(&mut encoder) + .expect("in-memory writers don't error"); let mut wrote = self.writer.write(encoder.as_slice())?; // write out deltas of sorted values into a Golonb-Rice coded bit stream @@ -384,7 +422,7 @@ impl<'a> GCSFilterWriter<'a> { struct GCSFilter { k0: u64, // sip hash key k1: u64, // sip hash key - p: u8 + p: u8, } impl GCSFilter { @@ -433,17 +471,16 @@ pub struct BitStreamReader<'a> { impl<'a> BitStreamReader<'a> { /// Create a new BitStreamReader that reads bitwise from a given reader pub fn new(reader: &'a mut dyn io::Read) -> BitStreamReader { - BitStreamReader { - buffer: [0u8], - reader, - offset: 8, - } + BitStreamReader { buffer: [0u8], reader, offset: 8 } } /// Read nbit bits pub fn read(&mut self, mut nbits: u8) -> Result { if nbits > 64 { - return Err(io::Error::new(io::ErrorKind::Other, "can not read more than 64 bits at once")); + return Err(io::Error::new( + io::ErrorKind::Other, + "can not read more than 64 bits at once", + )); } let mut data = 0u64; while nbits > 0 { @@ -471,17 +508,16 @@ pub struct BitStreamWriter<'a> { impl<'a> BitStreamWriter<'a> { /// Create a new BitStreamWriter that writes bitwise to a given writer pub fn new(writer: &'a mut dyn io::Write) -> BitStreamWriter { - BitStreamWriter { - buffer: [0u8], - writer, - offset: 0, - } + BitStreamWriter { buffer: [0u8], writer, offset: 0 } } /// Write nbits bits from data pub fn write(&mut self, data: u64, mut nbits: u8) -> Result { if nbits > 64 { - return Err(io::Error::new(io::ErrorKind::Other, "can not write more than 64 bits at once")); + return Err(io::Error::new( + io::ErrorKind::Other, + "can not write more than 64 bits at once", + )); } let mut wrote = 0; while nbits > 0 { @@ -511,63 +547,79 @@ impl<'a> BitStreamWriter<'a> { #[cfg(test)] mod test { - use io::Cursor; - use hash_types::BlockHash; use hashes::hex::FromHex; + use io::Cursor; use super::*; extern crate serde_json; - use self::serde_json::Value; + use std::collections::HashMap; use consensus::encode::deserialize; - use std::collections::HashMap; + + use self::serde_json::Value; #[test] fn test_blockfilters() { - // test vectors from: https://github.com/jimpo/bitcoin/blob/c7efb652f3543b001b4dd22186a354605b14f47e/src/test/data/blockfilters.json let data = include_str!("../../test_data/blockfilters.json"); let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); for t in testdata.iter().skip(1) { let block_hash = BlockHash::from_hex(&t.get(1).unwrap().as_str().unwrap()).unwrap(); - let block: Block = deserialize(&Vec::from_hex(&t.get(2).unwrap().as_str().unwrap()).unwrap()).unwrap(); + let block: Block = + deserialize(&Vec::from_hex(&t.get(2).unwrap().as_str().unwrap()).unwrap()).unwrap(); assert_eq!(block.block_hash(), block_hash); let scripts = t.get(3).unwrap().as_array().unwrap(); - let previous_filter_header = FilterHeader::from_hex(&t.get(4).unwrap().as_str().unwrap()).unwrap(); + let previous_filter_header = + FilterHeader::from_hex(&t.get(4).unwrap().as_str().unwrap()).unwrap(); let filter_content = Vec::from_hex(&t.get(5).unwrap().as_str().unwrap()).unwrap(); - let filter_header = FilterHeader::from_hex(&t.get(6).unwrap().as_str().unwrap()).unwrap(); + let filter_header = + FilterHeader::from_hex(&t.get(6).unwrap().as_str().unwrap()).unwrap(); let mut txmap = HashMap::new(); let mut si = scripts.iter(); for tx in block.txdata.iter().skip(1) { for input in tx.input.iter() { - txmap.insert(input.previous_output.clone(), Script::from(Vec::from_hex(si.next().unwrap().as_str().unwrap()).unwrap())); + txmap.insert( + input.previous_output.clone(), + Script::from(Vec::from_hex(si.next().unwrap().as_str().unwrap()).unwrap()), + ); } } - let filter = BlockFilter::new_script_filter(&block, - |o| if let Some(s) = txmap.get(o) { - Ok(s.clone()) - } else { - Err(Error::UtxoMissing(o.clone())) - }).unwrap(); + let filter = BlockFilter::new_script_filter(&block, |o| { + if let Some(s) = txmap.get(o) { + Ok(s.clone()) + } else { + Err(Error::UtxoMissing(o.clone())) + } + }) + .unwrap(); let test_filter = BlockFilter::new(filter_content.as_slice()); assert_eq!(test_filter.content, filter.content); let block_hash = &block.block_hash(); - assert!(filter.match_all(block_hash, &mut txmap.iter() - .filter_map(|(_, s)| if !s.is_empty() { Some(s.as_bytes()) } else { None })).unwrap()); + assert!(filter + .match_all( + block_hash, + &mut txmap.iter().filter_map(|(_, s)| if !s.is_empty() { + Some(s.as_bytes()) + } else { + None + }) + ) + .unwrap()); for (_, script) in &txmap { let query = vec![script]; - if !script.is_empty () { - assert!(filter.match_any(&block_hash, &mut query.iter() - .map(|s| s.as_bytes())).unwrap()); + if !script.is_empty() { + assert!(filter + .match_any(&block_hash, &mut query.iter().map(|s| s.as_bytes())) + .unwrap()); } } @@ -623,7 +675,9 @@ mod test { let reader = GCSFilterReader::new(0, 0, M, P); let mut input = Cursor::new(bytes.clone()); - assert!(!reader.match_any(&mut input, &mut query.iter().map(|v| v.as_slice())).unwrap()); + assert!(!reader + .match_any(&mut input, &mut query.iter().map(|v| v.as_slice())) + .unwrap()); } { let reader = GCSFilterReader::new(0, 0, M, P); @@ -642,7 +696,9 @@ mod test { } query.push(Vec::from_hex("abcdef").unwrap()); let mut input = Cursor::new(bytes.clone()); - assert!(!reader.match_all(&mut input, &mut query.iter().map(|v| v.as_slice())).unwrap()); + assert!(!reader + .match_all(&mut input, &mut query.iter().map(|v| v.as_slice())) + .unwrap()); } } @@ -661,7 +717,10 @@ mod test { writer.flush().unwrap(); } let bytes = out; - assert_eq!("01011010110000110000000001110000", format!("{:08b}{:08b}{:08b}{:08b}", bytes[0], bytes[1], bytes[2], bytes[3])); + assert_eq!( + "01011010110000110000000001110000", + format!("{:08b}{:08b}{:08b}{:08b}", bytes[0], bytes[1], bytes[2], bytes[3]) + ); { let mut input = Cursor::new(bytes); let mut reader = BitStreamReader::new(&mut input); diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 5c89170d05..054793d288 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -17,21 +17,23 @@ //! at . //! -use prelude::*; - -use io::Write; -use core::{fmt, str::FromStr, default::Default}; +use core::default::Default; +use core::fmt; use core::ops::Index; -#[cfg(feature = "std")] use std::error; -#[cfg(feature = "serde")] use serde; +use core::str::FromStr; +#[cfg(feature = "std")] +use std::error; use hash_types::XpubIdentifier; -use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine, hex}; -use secp256k1::{self, Secp256k1, XOnlyPublicKey}; - +use hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use io::Write; use network::constants::Network; +use prelude::*; +use secp256k1::{self, Secp256k1, XOnlyPublicKey}; +#[cfg(feature = "serde")] +use serde; +use util::key::{KeyPair, PrivateKey, PublicKey}; use util::{base58, endian, key}; -use util::key::{PublicKey, PrivateKey, KeyPair}; /// A chain code #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -60,7 +62,7 @@ pub struct ExtendedPrivKey { /// Private key pub private_key: secp256k1::SecretKey, /// Chain code - pub chain_code: ChainCode + pub chain_code: ChainCode, } serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key"); @@ -92,7 +94,7 @@ pub struct ExtendedPubKey { /// Public key pub public_key: secp256k1::PublicKey, /// Chain code - pub chain_code: ChainCode + pub chain_code: ChainCode, } serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key"); @@ -102,12 +104,12 @@ pub enum ChildNumber { /// Non-hardened key Normal { /// Key index, within [0, 2^31 - 1] - index: u32 + index: u32, }, /// Hardened key Hardened { /// Key index, within [0, 2^31 - 1] - index: u32 + index: u32, }, } @@ -148,16 +150,16 @@ impl ChildNumber { /// [`Hardened`]: #variant.Hardened pub fn is_hardened(&self) -> bool { match self { - ChildNumber::Hardened {..} => true, - ChildNumber::Normal {..} => false, + ChildNumber::Hardened { .. } => true, + ChildNumber::Normal { .. } => false, } } /// Returns the child number that is a single increment from this one. pub fn increment(self) -> Result { match self { - ChildNumber::Normal{ index: idx } => ChildNumber::from_normal_idx(idx+1), - ChildNumber::Hardened{ index: idx } => ChildNumber::from_hardened_idx(idx+1), + ChildNumber::Normal { index: idx } => ChildNumber::from_normal_idx(idx + 1), + ChildNumber::Hardened { index: idx } => ChildNumber::from_hardened_idx(idx + 1), } } } @@ -188,7 +190,7 @@ impl fmt::Display for ChildNumber { fmt::Display::fmt(&index, f)?; let alt = f.alternate(); f.write_str(if alt { "h" } else { "'" }) - }, + } ChildNumber::Normal { index } => fmt::Display::fmt(&index, f), } } @@ -200,7 +202,9 @@ impl FromStr for ChildNumber { fn from_str(inp: &str) -> Result { let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h'); Ok(if is_hardened { - ChildNumber::from_hardened_idx(inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?)? + ChildNumber::from_hardened_idx( + inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?, + )? } else { ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)? }) @@ -259,7 +263,10 @@ impl Default for DerivationPath { } } -impl IntoDerivationPath for T where T: Into { +impl IntoDerivationPath for T +where + T: Into, +{ fn into_derivation_path(self) -> Result { Ok(self.into()) } @@ -296,7 +303,10 @@ impl<'a> From<&'a [ChildNumber]> for DerivationPath { } impl ::core::iter::FromIterator for DerivationPath { - fn from_iter(iter: T) -> Self where T: IntoIterator { + fn from_iter(iter: T) -> Self + where + T: IntoIterator, + { DerivationPath(Vec::from_iter(iter)) } } @@ -342,10 +352,7 @@ pub struct DerivationPathIterator<'a> { impl<'a> DerivationPathIterator<'a> { /// Start a new [DerivationPathIterator] at the given child. pub fn start_from(path: &'a DerivationPath, start: ChildNumber) -> DerivationPathIterator<'a> { - DerivationPathIterator { - base: path, - next_child: Some(start), - } + DerivationPathIterator { base: path, next_child: Some(start) } } } @@ -403,12 +410,12 @@ impl DerivationPath { /// Get an [Iterator] over the unhardened children of this [DerivationPath]. pub fn normal_children(&self) -> DerivationPathIterator { - DerivationPathIterator::start_from(self, ChildNumber::Normal{ index: 0 }) + DerivationPathIterator::start_from(self, ChildNumber::Normal { index: 0 }) } /// Get an [Iterator] over the hardened children of this [DerivationPath]. pub fn hardened_children(&self) -> DerivationPathIterator { - DerivationPathIterator::start_from(self, ChildNumber::Hardened{ index: 0 }) + DerivationPathIterator::start_from(self, ChildNumber::Hardened { index: 0 }) } /// Concatenate `self` with `path` and return the resulting new path. @@ -475,21 +482,29 @@ pub enum Error { /// Base58 encoding error Base58(base58::Error), /// Hexadecimal decoding error - Hex(hex::Error) + Hex(hex::Error), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::CannotDeriveFromHardenedKey => f.write_str("cannot derive hardened key from public key"), + Error::CannotDeriveFromHardenedKey => { + f.write_str("cannot derive hardened key from public key") + } Error::Secp256k1(ref e) => fmt::Display::fmt(e, f), - Error::InvalidChildNumber(ref n) => write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n), + Error::InvalidChildNumber(ref n) => { + write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n) + } Error::InvalidChildNumberFormat => f.write_str("invalid child number format"), Error::InvalidDerivationPathFormat => f.write_str("invalid derivation path format"), - Error::UnknownVersion(ref bytes) => write!(f, "unknown version magic bytes: {:?}", bytes), - Error::WrongExtendedKeyLength(ref len) => write!(f, "encoded extended key data has wrong length {}", len), + Error::UnknownVersion(ref bytes) => { + write!(f, "unknown version magic bytes: {:?}", bytes) + } + Error::WrongExtendedKeyLength(ref len) => { + write!(f, "encoded extended key data has wrong length {}", len) + } Error::Base58(ref err) => write!(f, "base58 encoding error: {}", err), - Error::Hex(ref e) => write!(f, "Hexadecimal decoding error: {}", e) + Error::Hex(ref e) => write!(f, "Hexadecimal decoding error: {}", e), } } } @@ -512,13 +527,15 @@ impl From for Error { key::Error::Base58(e) => Error::Base58(e), key::Error::Secp256k1(e) => Error::Secp256k1(e), key::Error::InvalidKeyPrefix(_) => Error::Secp256k1(secp256k1::Error::InvalidPublicKey), - key::Error::Hex(e) => Error::Hex(e) + key::Error::Hex(e) => Error::Hex(e), } } } impl From for Error { - fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) } + fn from(e: secp256k1::Error) -> Error { + Error::Secp256k1(e) + } } impl From for Error { @@ -549,14 +566,15 @@ impl ExtendedPrivKey { PrivateKey { compressed: true, network: self.network, - inner: self.private_key + inner: self.private_key, } } /// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal /// secret key representation. pub fn to_keypair(&self, secp: &Secp256k1) -> KeyPair { - KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken") + KeyPair::from_seckey_slice(secp, &self.private_key[..]) + .expect("BIP32 internal private key representation is broken") } /// Attempts to derive an extended private key from a path. @@ -575,12 +593,18 @@ impl ExtendedPrivKey { } /// Private->Private child key derivation - pub fn ckd_priv(&self, secp: &Secp256k1, i: ChildNumber) -> Result { + pub fn ckd_priv( + &self, + secp: &Secp256k1, + i: ChildNumber, + ) -> Result { let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); match i { ChildNumber::Normal { .. } => { // Non-hardened key: compute public data and use that - hmac_engine.input(&secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..]); + hmac_engine.input( + &secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..], + ); } ChildNumber::Hardened { .. } => { // Hardened key: use only secret data to prevent public derivation @@ -600,14 +624,14 @@ impl ExtendedPrivKey { parent_fingerprint: self.fingerprint(secp), child_number: i, private_key: sk, - chain_code: ChainCode::from(&hmac_result[32..]) + chain_code: ChainCode::from(&hmac_result[32..]), }) } /// Decoding extended private key from binary data according to BIP 32 pub fn decode(data: &[u8]) -> Result { if data.len() != 78 { - return Err(Error::WrongExtendedKeyLength(data.len())) + return Err(Error::WrongExtendedKeyLength(data.len())); } let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] { @@ -633,10 +657,12 @@ impl ExtendedPrivKey { /// Extended private key binary encoding according to BIP 32 pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; - ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], - Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], - }[..]); + ret[0..4].copy_from_slice( + &match self.network { + Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], + Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], + }[..], + ); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); @@ -660,28 +686,31 @@ impl ExtendedPrivKey { impl ExtendedPubKey { /// Derives a public key from a private key #[deprecated(since = "0.28.0", note = "use ExtendedPubKey::from_priv")] - pub fn from_private(secp: &Secp256k1, sk: &ExtendedPrivKey) -> ExtendedPubKey { + pub fn from_private( + secp: &Secp256k1, + sk: &ExtendedPrivKey, + ) -> ExtendedPubKey { ExtendedPubKey::from_priv(secp, sk) } /// Derives a public key from a private key - pub fn from_priv(secp: &Secp256k1, sk: &ExtendedPrivKey) -> ExtendedPubKey { + pub fn from_priv( + secp: &Secp256k1, + sk: &ExtendedPrivKey, + ) -> ExtendedPubKey { ExtendedPubKey { network: sk.network, depth: sk.depth, parent_fingerprint: sk.parent_fingerprint, child_number: sk.child_number, public_key: secp256k1::PublicKey::from_secret_key(secp, &sk.private_key), - chain_code: sk.chain_code + chain_code: sk.chain_code, } } /// Constructs ECDSA compressed public key matching internal public key representation. pub fn to_pub(&self) -> PublicKey { - PublicKey { - compressed: true, - inner: self.public_key - } + PublicKey { compressed: true, inner: self.public_key } } /// Constructs BIP340 x-only public key for BIP-340 signatures and Taproot use matching @@ -706,13 +735,15 @@ impl ExtendedPubKey { } /// Compute the scalar tweak added to this key to get a child key - pub fn ckd_pub_tweak(&self, i: ChildNumber) -> Result<(secp256k1::SecretKey, ChainCode), Error> { + pub fn ckd_pub_tweak( + &self, + i: ChildNumber, + ) -> Result<(secp256k1::SecretKey, ChainCode), Error> { match i { - ChildNumber::Hardened { .. } => { - Err(Error::CannotDeriveFromHardenedKey) - } + ChildNumber::Hardened { .. } => Err(Error::CannotDeriveFromHardenedKey), ChildNumber::Normal { index: n } => { - let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); + let mut hmac_engine: HmacEngine = + HmacEngine::new(&self.chain_code[..]); hmac_engine.input(&self.public_key.serialize()[..]); hmac_engine.input(&endian::u32_to_array_be(n)); @@ -748,7 +779,7 @@ impl ExtendedPubKey { /// Decoding extended public key from binary data according to BIP 32 pub fn decode(data: &[u8]) -> Result { if data.len() != 78 { - return Err(Error::WrongExtendedKeyLength(data.len())) + return Err(Error::WrongExtendedKeyLength(data.len())); } Ok(ExtendedPubKey { @@ -772,10 +803,12 @@ impl ExtendedPubKey { /// Extended public key binary encoding according to BIP 32 pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; - ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], - Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], - }[..]); + ret[0..4].copy_from_slice( + &match self.network { + Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], + Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], + }[..], + ); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); @@ -839,15 +872,14 @@ impl FromStr for ExtendedPubKey { #[cfg(test)] mod tests { - use super::*; - use super::ChildNumber::{Hardened, Normal}; - use core::str::FromStr; - use secp256k1::{self, Secp256k1}; use hashes::hex::FromHex; - use network::constants::Network::{self, Bitcoin}; + use secp256k1::{self, Secp256k1}; + + use super::ChildNumber::{Hardened, Normal}; + use super::*; #[test] fn test_parse_derivation_path() { @@ -856,7 +888,10 @@ mod tests { assert_eq!(DerivationPath::from_str("4/m/5"), Err(Error::InvalidDerivationPathFormat)); assert_eq!(DerivationPath::from_str("m//3/0'"), Err(Error::InvalidChildNumberFormat)); assert_eq!(DerivationPath::from_str("m/0h/0x"), Err(Error::InvalidChildNumberFormat)); - assert_eq!(DerivationPath::from_str("m/2147483648"), Err(Error::InvalidChildNumber(2147483648))); + assert_eq!( + DerivationPath::from_str("m/2147483648"), + Err(Error::InvalidChildNumber(2147483648)) + ); assert_eq!(DerivationPath::master(), DerivationPath::from_str("m").unwrap()); assert_eq!(DerivationPath::master(), DerivationPath::default()); @@ -867,7 +902,11 @@ mod tests { ); assert_eq!( DerivationPath::from_str("m/0'/1"), - Ok(vec![ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()].into()) + Ok(vec![ + ChildNumber::from_hardened_idx(0).unwrap(), + ChildNumber::from_normal_idx(1).unwrap() + ] + .into()) ); assert_eq!( DerivationPath::from_str("m/0h/1/2'"), @@ -875,7 +914,8 @@ mod tests { ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap(), ChildNumber::from_hardened_idx(2).unwrap(), - ].into()) + ] + .into()) ); assert_eq!( DerivationPath::from_str("m/0'/1/2h/2"), @@ -884,7 +924,8 @@ mod tests { ChildNumber::from_normal_idx(1).unwrap(), ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(), - ].into()) + ] + .into()) ); assert_eq!( DerivationPath::from_str("m/0'/1/2'/2/1000000000"), @@ -894,7 +935,8 @@ mod tests { ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(), ChildNumber::from_normal_idx(1000000000).unwrap(), - ].into()) + ] + .into()) ); let s = "m/0'/50/3'/5/545456"; assert_eq!(DerivationPath::from_str(s), s.into_derivation_path()); @@ -907,7 +949,13 @@ mod tests { let numbers: Vec = path.clone().into(); let path2: DerivationPath = numbers.into(); assert_eq!(path, path2); - assert_eq!(&path[..2], &[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()]); + assert_eq!( + &path[..2], + &[ + ChildNumber::from_hardened_idx(0).unwrap(), + ChildNumber::from_normal_idx(1).unwrap() + ] + ); let indexed: DerivationPath = path[..2].into(); assert_eq!(indexed, DerivationPath::from_str("m/0h/1").unwrap()); assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path); @@ -919,8 +967,8 @@ mod tests { seed: &[u8], path: DerivationPath, expected_sk: &str, - expected_pk: &str) - { + expected_pk: &str, + ) { let mut sk = ExtendedPrivKey::new_master(network, seed).unwrap(); let mut pk = ExtendedPubKey::from_priv(secp, &sk); @@ -939,16 +987,13 @@ mod tests { for &num in path.0.iter() { sk = sk.ckd_priv(secp, num).unwrap(); match num { - Normal {..} => { + Normal { .. } => { let pk2 = pk.ckd_pub(secp, num).unwrap(); pk = ExtendedPubKey::from_priv(secp, &sk); assert_eq!(pk, pk2); } - Hardened {..} => { - assert_eq!( - pk.ckd_pub(secp, num), - Err(Error::CannotDeriveFromHardenedKey) - ); + Hardened { .. } => { + assert_eq!(pk.ckd_pub(secp, num), Err(Error::CannotDeriveFromHardenedKey)); pk = ExtendedPubKey::from_priv(secp, &sk); } } @@ -968,15 +1013,15 @@ mod tests { fn test_increment() { let idx = 9345497; // randomly generated, I promise let cn = ChildNumber::from_normal_idx(idx).unwrap(); - assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx+1).unwrap())); + assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx + 1).unwrap())); let cn = ChildNumber::from_hardened_idx(idx).unwrap(); - assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx+1).unwrap())); + assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx + 1).unwrap())); - let max = (1<<31)-1; + let max = (1 << 31) - 1; let cn = ChildNumber::from_normal_idx(max).unwrap(); - assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31))); + assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31))); let cn = ChildNumber::from_hardened_idx(max).unwrap(); - assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31))); + assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31))); let cn = ChildNumber::from_normal_idx(350).unwrap(); let path = DerivationPath::from_str("m/42'").unwrap(); @@ -1093,7 +1138,6 @@ mod tests { test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); - } #[test] @@ -1111,7 +1155,7 @@ mod tests { #[cfg(feature = "serde")] pub fn encode_fingerprint_chaincode() { use serde_json; - let fp = Fingerprint::from(&[1u8,2,3,42][..]); + let fp = Fingerprint::from(&[1u8, 2, 3, 42][..]); #[rustfmt::skip] let cc = ChainCode::from( &[1u8,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2][..] @@ -1170,7 +1214,6 @@ mod tests { ExtendedPrivKey::from_str(xpriv_str).unwrap(); } - #[test] #[should_panic(expected = "Secp256k1(InvalidSecretKey)")] fn schnorr_broken_privkey_ffs() { @@ -1179,4 +1222,3 @@ mod tests { ExtendedPrivKey::from_str(xpriv_str).unwrap(); } } - diff --git a/src/util/ecdsa.rs b/src/util/ecdsa.rs index 431b368af5..5ccdf32285 100644 --- a/src/util/ecdsa.rs +++ b/src/util/ecdsa.rs @@ -16,13 +16,13 @@ //! //! This module provides ECDSA signatures used Bitcoin that can be roundtrip (de)serialized. -use prelude::*; use core::str::FromStr; use core::{fmt, iter}; -use hashes::hex::{self, FromHex}; + use blockdata::transaction::NonStandardSighashType; -use secp256k1; -use EcdsaSighashType; +use hashes::hex::{self, FromHex}; +use prelude::*; +use {secp256k1, EcdsaSighashType}; /// An ECDSA signature with the corresponding hash type. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -37,28 +37,25 @@ pub struct EcdsaSig { impl EcdsaSig { /// Constructs ECDSA bitcoin signature for [`EcdsaSighashType::All`] pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig { - EcdsaSig { - sig, - hash_ty: EcdsaSighashType::All - } + EcdsaSig { sig, hash_ty: EcdsaSighashType::All } } /// Deserialize from slice following the standardness rules for [`EcdsaSighashType`] pub fn from_slice(sl: &[u8]) -> Result { - let (hash_ty, sig) = sl.split_last() - .ok_or(EcdsaSigError::EmptySignature)?; + let (hash_ty, sig) = sl.split_last().ok_or(EcdsaSigError::EmptySignature)?; let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32) .map_err(|_| EcdsaSigError::NonStandardSighashType(*hash_ty as u32))?; - let sig = secp256k1::ecdsa::Signature::from_der(sig) - .map_err(EcdsaSigError::Secp256k1)?; + let sig = secp256k1::ecdsa::Signature::from_der(sig).map_err(EcdsaSigError::Secp256k1)?; Ok(EcdsaSig { sig, hash_ty }) } /// Serialize EcdsaSig pub fn to_vec(&self) -> Vec { // TODO: add support to serialize to a writer to SerializedSig - self.sig.serialize_der() - .iter().map(|x| *x) + self.sig + .serialize_der() + .iter() + .map(|x| *x) .chain(iter::once(self.hash_ty as u8)) .collect() } @@ -76,11 +73,10 @@ impl FromStr for EcdsaSig { fn from_str(s: &str) -> Result { let bytes = Vec::from_hex(s)?; - let (sighash_byte, signature) = bytes.split_last() - .ok_or(EcdsaSigError::EmptySignature)?; + let (sighash_byte, signature) = bytes.split_last().ok_or(EcdsaSigError::EmptySignature)?; Ok(EcdsaSig { sig: secp256k1::ecdsa::Signature::from_der(signature)?, - hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)? + hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?, }) } } @@ -98,17 +94,15 @@ pub enum EcdsaSigError { Secp256k1(secp256k1::Error), } - impl fmt::Display for EcdsaSigError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - EcdsaSigError::NonStandardSighashType(hash_ty) => - write!(f, "Non standard signature hash type {}", hash_ty), - EcdsaSigError::Secp256k1(ref e) => - write!(f, "Invalid Ecdsa signature: {}", e), - EcdsaSigError::EmptySignature => - write!(f, "Empty ECDSA signature"), - EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e) + EcdsaSigError::NonStandardSighashType(hash_ty) => { + write!(f, "Non standard signature hash type {}", hash_ty) + } + EcdsaSigError::Secp256k1(ref e) => write!(f, "Invalid Ecdsa signature: {}", e), + EcdsaSigError::EmptySignature => write!(f, "Empty ECDSA signature"), + EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e), } } } diff --git a/src/util/endian.rs b/src/util/endian.rs index f09a123780..f7eeb10d5f 100644 --- a/src/util/endian.rs +++ b/src/util/endian.rs @@ -5,11 +5,11 @@ macro_rules! define_slice_to_be { assert_eq!(slice.len(), ::core::mem::size_of::<$type>()); let mut res = 0; for i in 0..::core::mem::size_of::<$type>() { - res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1)*8; + res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1) * 8; } res } - } + }; } macro_rules! define_slice_to_le { ($name: ident, $type: ty) => { @@ -18,11 +18,11 @@ macro_rules! define_slice_to_le { assert_eq!(slice.len(), ::core::mem::size_of::<$type>()); let mut res = 0; for i in 0..::core::mem::size_of::<$type>() { - res |= (slice[i] as $type) << i*8; + res |= (slice[i] as $type) << i * 8; } res } - } + }; } macro_rules! define_be_to_array { ($name: ident, $type: ty, $byte_len: expr) => { @@ -31,11 +31,11 @@ macro_rules! define_be_to_array { debug_assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 let mut res = [0; $byte_len]; for i in 0..$byte_len { - res[i] = ((val >> ($byte_len - i - 1)*8) & 0xff) as u8; + res[i] = ((val >> ($byte_len - i - 1) * 8) & 0xff) as u8; } res } - } + }; } macro_rules! define_le_to_array { ($name: ident, $type: ty, $byte_len: expr) => { @@ -44,11 +44,11 @@ macro_rules! define_le_to_array { debug_assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 let mut res = [0; $byte_len]; for i in 0..$byte_len { - res[i] = ((val >> i*8) & 0xff) as u8; + res[i] = ((val >> i * 8) & 0xff) as u8; } res } - } + }; } define_slice_to_be!(slice_to_u32_be, u32); @@ -92,11 +92,13 @@ macro_rules! define_chunk_slice_to_int { #[inline] pub fn $name(inp: &[u8], outp: &mut [$type]) { assert_eq!(inp.len(), outp.len() * ::core::mem::size_of::<$type>()); - for (outp_val, data_bytes) in outp.iter_mut().zip(inp.chunks(::core::mem::size_of::<$type>())) { + for (outp_val, data_bytes) in + outp.iter_mut().zip(inp.chunks(::core::mem::size_of::<$type>())) + { *outp_val = $converter(data_bytes); } } - } + }; } define_chunk_slice_to_int!(bytes_to_u64_slice_le, u64, slice_to_u64_le); @@ -107,20 +109,32 @@ mod tests { #[test] fn endianness_test() { assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef); - assert_eq!(slice_to_u64_be(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0xca, 0xfe]), 0xdeadbeef1badcafe); + assert_eq!( + slice_to_u64_be(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0xca, 0xfe]), + 0xdeadbeef1badcafe + ); assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]); assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead); assert_eq!(slice_to_u32_le(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef); - assert_eq!(slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]), 0x1badcafedeadbeef); + assert_eq!( + slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]), + 0x1badcafedeadbeef + ); assert_eq!(u16_to_array_le(0xdead), [0xad, 0xde]); assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]); - assert_eq!(u64_to_array_le(0x1badcafedeadbeef), [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]); + assert_eq!( + u64_to_array_le(0x1badcafedeadbeef), + [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b] + ); } #[test] fn endian_chunk_test() { - let inp = [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa, 0x01, 0x02]; + let inp = [ + 0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa, + 0x01, 0x02, + ]; let mut out = [0; 2]; bytes_to_u64_slice_le(&inp, &mut out); assert_eq!(out, [0x1badcafedeadbeef, 0x0201face1badcafe]); diff --git a/src/util/hash.rs b/src/util/hash.rs index 6a14d07b33..f85650294c 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -17,15 +17,13 @@ //! merkleization. //! -use core::iter; - -use prelude::*; - -use io; use core::cmp::min; +use core::iter; -use hashes::Hash; use consensus::encode::Encodable; +use hashes::Hash; +use io; +use prelude::*; /// Calculates the merkle root of a list of *hashes*, inline (in place) in `hashes`. /// @@ -38,7 +36,7 @@ use consensus::encode::Encodable; pub fn bitcoin_merkle_root_inline(hashes: &mut [T]) -> Option where T: Hash + Encodable, - ::Engine: io::Write, + ::Engine: io::Write, { match hashes.len() { 0 => None, @@ -57,7 +55,7 @@ pub fn bitcoin_merkle_root(mut hashes: I) -> Option where T: Hash + Encodable, ::Engine: io::Write, - I: Iterator, + I: Iterator, { let first = hashes.next()?; let second = match hashes.next() { @@ -91,15 +89,19 @@ where ::Engine: io::Write, { if hashes.len() == 1 { - return hashes[0] + return hashes[0]; } for idx in 0..((hashes.len() + 1) / 2) { let idx1 = 2 * idx; let idx2 = min(idx1 + 1, hashes.len() - 1); let mut encoder = T::engine(); - hashes[idx1].consensus_encode(&mut encoder).expect("in-memory writers don't error"); - hashes[idx2].consensus_encode(&mut encoder).expect("in-memory writers don't error"); + hashes[idx1] + .consensus_encode(&mut encoder) + .expect("in-memory writers don't error"); + hashes[idx2] + .consensus_encode(&mut encoder) + .expect("in-memory writers don't error"); hashes[idx] = T::from_engine(encoder); } let half_len = hashes.len() / 2 + hashes.len() % 2; @@ -109,10 +111,10 @@ where #[cfg(test)] mod tests { + use blockdata::block::Block; use consensus::encode::deserialize; use hashes::sha256d; - use blockdata::block::Block; use super::*; #[test] diff --git a/src/util/key.rs b/src/util/key.rs index d02411ad46..f01cf7f252 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -16,19 +16,20 @@ //! This module provides keys used in Bitcoin that can be roundtrip //! (de)serialized. -pub use secp256k1::{XOnlyPublicKey, KeyPair}; - -use prelude::*; - -use core::{ops, str::FromStr}; use core::fmt::{self, Write as _fmtWrite}; -use io; -#[cfg(feature = "std")] use std::error; +use core::ops; +use core::str::FromStr; +#[cfg(feature = "std")] +use std::error; -use secp256k1::{self, Secp256k1}; -use network::constants::Network; -use hashes::{Hash, hash160, hex, hex::FromHex}; use hash_types::{PubkeyHash, WPubkeyHash}; +use hashes::hex::FromHex; +use hashes::{hash160, hex, Hash}; +use io; +use network::constants::Network; +use prelude::*; +use secp256k1::{self, Secp256k1}; +pub use secp256k1::{KeyPair, XOnlyPublicKey}; use util::base58; /// A key-related error. @@ -41,7 +42,7 @@ pub enum Error { /// Invalid key prefix error InvalidKeyPrefix(u8), /// Hex decoding error - Hex(hex::Error) + Hex(hex::Error), } impl fmt::Display for Error { @@ -50,7 +51,7 @@ impl fmt::Display for Error { Error::Base58(ref e) => write!(f, "Key base58 error: {}", e), Error::Secp256k1(ref e) => write!(f, "Key secp256k1 error: {}", e), Error::InvalidKeyPrefix(ref e) => write!(f, "Key prefix invalid: {}", e), - Error::Hex(ref e) => write!(f, "Key hex decoding error: {}", e) + Error::Hex(ref e) => write!(f, "Key hex decoding error: {}", e), } } } @@ -63,7 +64,7 @@ impl ::std::error::Error for Error { Error::Base58(ref e) => Some(e), Error::Secp256k1(ref e) => Some(e), Error::InvalidKeyPrefix(_) => None, - Error::Hex(ref e) => Some(e) + Error::Hex(ref e) => Some(e), } } } @@ -89,7 +90,6 @@ impl From for Error { } } - /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PublicKey { @@ -102,19 +102,13 @@ pub struct PublicKey { impl PublicKey { /// Constructs compressed ECDSA public key from the provided generic Secp256k1 public key pub fn new(key: secp256k1::PublicKey) -> PublicKey { - PublicKey { - compressed: true, - inner: key, - } + PublicKey { compressed: true, inner: key } } /// Constructs uncompressed (legacy) ECDSA public key from the provided generic Secp256k1 /// public key pub fn new_uncompressed(key: secp256k1::PublicKey) -> PublicKey { - PublicKey { - compressed: false, - inner: key, - } + PublicKey { compressed: false, inner: key } } /// Returns bitcoin 160-bit hash of the public key @@ -130,7 +124,7 @@ impl PublicKey { pub fn wpubkey_hash(&self) -> Option { if self.compressed { Some(WPubkeyHash::from_inner( - hash160::Hash::hash(&self.inner.serialize()).into_inner() + hash160::Hash::hash(&self.inner.serialize()).into_inner(), )) } else { // We can't create witness pubkey hashes for an uncompressed @@ -168,7 +162,7 @@ impl PublicKey { Error::Base58(_) => "base58 error", Error::Secp256k1(_) => "secp256k1 error", Error::InvalidKeyPrefix(_) => "invalid key prefix", - Error::Hex(_) => "hex decoding error" + Error::Hex(_) => "hex decoding error", }; io::Error::new(io::ErrorKind::InvalidData, reason) }) @@ -186,13 +180,13 @@ impl PublicKey { let compressed = match data.len() { 33 => true, 65 => false, - len => { + len => { return Err(base58::Error::InvalidLength(len).into()); - }, + } }; if !compressed && data[0] != 0x04 { - return Err(Error::InvalidKeyPrefix(data[0])) + return Err(Error::InvalidKeyPrefix(data[0])); } Ok(PublicKey { @@ -202,7 +196,10 @@ impl PublicKey { } /// Computes the public key as supposed to be used with this secret - pub fn from_private_key(secp: &Secp256k1, sk: &PrivateKey) -> PublicKey { + pub fn from_private_key( + secp: &Secp256k1, + sk: &PrivateKey, + ) -> PublicKey { sk.public_key(secp) } } @@ -228,7 +225,7 @@ impl FromStr for PublicKey { match s.len() { 66 => PublicKey::from_slice(&<[u8; 33]>::from_hex(s)?), 130 => PublicKey::from_slice(&<[u8; 65]>::from_hex(s)?), - len => return Err(Error::Hex(hex::Error::InvalidLength(66, len))) + len => return Err(Error::Hex(hex::Error::InvalidLength(66, len))), } } } @@ -249,28 +246,20 @@ impl PrivateKey { /// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key /// and the specified network pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { - compressed: true, - network, - inner: key, - } + PrivateKey { compressed: true, network, inner: key } } /// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1 /// private key and the specified network pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { - compressed: false, - network, - inner: key, - } + PrivateKey { compressed: false, network, inner: key } } /// Creates a public key from this private key pub fn public_key(&self, secp: &Secp256k1) -> PublicKey { PublicKey { compressed: self.compressed, - inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner) + inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner), } } @@ -324,7 +313,7 @@ impl PrivateKey { let network = match data[0] { 128 => Network::Bitcoin, 239 => Network::Testnet, - x => { + x => { return Err(Error::Base58(base58::Error::InvalidAddressVersion(x))); } }; @@ -482,19 +471,21 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey { #[cfg(test)] mod tests { - use io; - use super::{PrivateKey, PublicKey}; - use secp256k1::Secp256k1; use std::str::FromStr; + use hashes::hex::ToHex; - use network::constants::Network::Testnet; - use network::constants::Network::Bitcoin; + use io; + use network::constants::Network::{Bitcoin, Testnet}; + use secp256k1::Secp256k1; use util::address::Address; + use super::{PrivateKey, PublicKey}; + #[test] fn test_key_derivation() { // testnet compressed - let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + let sk = + PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); assert_eq!(sk.network, Testnet); assert_eq!(sk.compressed, true); assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); @@ -510,7 +501,8 @@ mod tests { assert_eq!(&sk.to_wif(), &sk_str.to_wif()); // mainnet uncompressed - let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); + let sk = + PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); assert_eq!(sk.network, Bitcoin); assert_eq!(sk.compressed, false); assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); @@ -523,13 +515,25 @@ mod tests { let addr = Address::p2pkh(&pk, sk.network); assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); pk.compressed = true; - assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"); - assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap()); + assert_eq!( + &pk.to_string(), + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ); + assert_eq!( + pk, + PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ) + .unwrap() + ); } #[test] fn test_pubkey_hash() { - let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap(); + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap(); assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"); assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a"); @@ -537,7 +541,10 @@ mod tests { #[test] fn test_wpubkey_hash() { - let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap(); + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap(); assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"); assert_eq!(upk.wpubkey_hash(), None); @@ -546,10 +553,11 @@ mod tests { #[cfg(feature = "serde")] #[test] fn test_key_serde() { - use serde_test::{Configure, Token, assert_tokens}; + use serde_test::{assert_tokens, Configure, Token}; static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"; - static PK_STR: &'static str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; + static PK_STR: &'static str = + "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; static PK_STR_U: &'static str = "\ 04\ 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\ @@ -579,10 +587,7 @@ mod tests { let s = Secp256k1::new(); let sk = PrivateKey::from_str(&KEY_WIF).unwrap(); let pk = PublicKey::from_private_key(&s, &sk); - let pk_u = PublicKey { - inner: pk.inner, - compressed: false, - }; + let pk_u = PublicKey { inner: pk.inner, compressed: false }; assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]); assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index cc70f58186..69a27d1dbd 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -52,18 +52,14 @@ //! assert_eq!(1, index[0]); //! ``` -use prelude::*; - -use io; - -use hashes::Hash; -use hash_types::{Txid, TxMerkleNode}; - -use blockdata::transaction::Transaction; use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; +use blockdata::transaction::Transaction; use consensus::encode::{self, Decodable, Encodable}; +use hash_types::{TxMerkleNode, Txid}; +use hashes::Hash; +use prelude::*; use util::merkleblock::MerkleBlockError::*; -use {Block, BlockHeader}; +use {io, Block, BlockHeader}; /// An error when verifying the merkle block #[derive(Clone, PartialEq, Eq, Debug)] @@ -362,11 +358,7 @@ impl Decodable for PartialMerkleTree { for (p, bit) in bits.iter_mut().enumerate() { *bit = (bytes[p / 8] & (1 << (p % 8) as u8)) != 0; } - Ok(PartialMerkleTree { - num_transactions, - hashes, - bits, - }) + Ok(PartialMerkleTree { num_transactions, hashes, bits }) } } @@ -422,7 +414,7 @@ impl MerkleBlock { /// ``` pub fn from_block_with_predicate(block: &Block, match_txids: F) -> Self where - F: Fn(&Txid) -> bool + F: Fn(&Txid) -> bool, { let block_txids: Vec<_> = block.txdata.iter().map(Transaction::txid).collect(); Self::from_header_txids_with_predicate(&block.header, &block_txids, match_txids) @@ -446,18 +438,12 @@ impl MerkleBlock { match_txids: F, ) -> Self where - F: Fn(&Txid) -> bool + F: Fn(&Txid) -> bool, { - let matches: Vec = block_txids - .iter() - .map(match_txids) - .collect(); + let matches: Vec = block_txids.iter().map(match_txids).collect(); let pmt = PartialMerkleTree::from_txids(block_txids, &matches); - MerkleBlock { - header: *header, - txn: pmt, - } + MerkleBlock { header: *header, txn: pmt } } /// Create a MerkleBlock from the block's header and txids, that should contain proofs for match_txids. @@ -492,8 +478,7 @@ impl MerkleBlock { impl Encodable for MerkleBlock { fn consensus_encode(&self, mut s: S) -> Result { - let len = self.header.consensus_encode(&mut s)? - + self.txn.consensus_encode(s)?; + let len = self.header.consensus_encode(&mut s)? + self.txn.consensus_encode(s)?; Ok(len) } } @@ -511,12 +496,11 @@ impl Decodable for MerkleBlock { mod tests { use core::cmp::min; - use hashes::Hash; + use consensus::encode::{deserialize, serialize}; + use hash_types::{TxMerkleNode, Txid}; use hashes::hex::{FromHex, ToHex}; - use hash_types::{Txid, TxMerkleNode}; + use hashes::Hash; use secp256k1::rand::prelude::*; - - use consensus::encode::{deserialize, serialize}; use util::hash::bitcoin_merkle_root; use util::merkleblock::{MerkleBlock, PartialMerkleTree}; use Block; @@ -534,7 +518,8 @@ mod tests { // Calculate the merkle root and height let hashes = txids.iter().map(|t| t.as_hash()); - let merkle_root_1: TxMerkleNode = bitcoin_merkle_root(hashes).expect("hashes is not empty").into(); + let merkle_root_1: TxMerkleNode = + bitcoin_merkle_root(hashes).expect("hashes is not empty").into(); let mut height = 1; let mut ntx = num_tx; while ntx > 1 { @@ -591,9 +576,8 @@ mod tests { let mut pmt3: PartialMerkleTree = deserialize(&serialized).unwrap(); pmt3.damage(&mut rng); let mut match_txid3 = vec![]; - let merkle_root_3 = pmt3 - .extract_matches(&mut match_txid3, &mut indexes) - .unwrap(); + let merkle_root_3 = + pmt3.extract_matches(&mut match_txid3, &mut indexes).unwrap(); assert_ne!(merkle_root_3, merkle_root_1); } } @@ -608,9 +592,8 @@ mod tests { .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap()) .collect(); - let matches = vec![ - false, false, false, false, false, false, false, false, false, true, true, false, - ]; + let matches = + vec![false, false, false, false, false, false, false, false, false, true, true, false]; let tree = PartialMerkleTree::from_txids(&txids, &matches); // Should fail due to duplicate txs found @@ -666,10 +649,7 @@ mod tests { let mut index: Vec = vec![]; assert_eq!( - merkle_block - .txn - .extract_matches(&mut matches, &mut index) - .unwrap(), + merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(), block.header.merkle_root ); assert_eq!(matches.len(), 2); @@ -699,10 +679,7 @@ mod tests { let mut index: Vec = vec![]; assert_eq!( - merkle_block - .txn - .extract_matches(&mut matches, &mut index) - .unwrap(), + merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(), block.header.merkle_root ); assert_eq!(matches.len(), 0); diff --git a/src/util/misc.rs b/src/util/misc.rs index ad1215578d..a6aa56e14a 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -18,12 +18,10 @@ //! recovery when library is used with the `secp-recovery` feature. //! -use prelude::*; - -use hashes::{sha256d, Hash, HashEngine}; - use blockdata::opcodes; use consensus::{encode, Encodable}; +use hashes::{sha256d, Hash, HashEngine}; +use prelude::*; #[cfg(feature = "secp-recovery")] #[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))] @@ -34,16 +32,17 @@ pub const BITCOIN_SIGNED_MSG_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n"; #[cfg(feature = "secp-recovery")] mod message_signing { - #[cfg(feature = "base64")] use prelude::*; use core::fmt; - #[cfg(feature = "std")] use std::error; + #[cfg(feature = "std")] + use std::error; use hashes::sha256d; + #[cfg(feature = "base64")] + use prelude::*; use secp256k1; - use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; - - use util::key::PublicKey; + use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use util::address::{Address, AddressType}; + use util::key::PublicKey; /// An error used for dealing with Bitcoin Signed Messages. #[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))] @@ -63,9 +62,13 @@ mod message_signing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { MessageSignatureError::InvalidLength => write!(f, "length not 65 bytes"), - MessageSignatureError::InvalidEncoding(ref e) => write!(f, "invalid encoding: {}", e), + MessageSignatureError::InvalidEncoding(ref e) => { + write!(f, "invalid encoding: {}", e) + } MessageSignatureError::InvalidBase64 => write!(f, "invalid base64"), - MessageSignatureError::UnsupportedAddressType(ref address_type) => write!(f, "unsupported address type: {}", address_type), + MessageSignatureError::UnsupportedAddressType(ref address_type) => { + write!(f, "unsupported address type: {}", address_type) + } } } } @@ -105,10 +108,7 @@ mod message_signing { impl MessageSignature { /// Create a new [MessageSignature]. pub fn new(signature: RecoverableSignature, compressed: bool) -> MessageSignature { - MessageSignature { - signature, - compressed, - } + MessageSignature { signature, compressed } } /// Serialize to bytes. @@ -131,7 +131,9 @@ mod message_signing { } // We just check this here so we can safely subtract further. if bytes[0] < 27 { - return Err(MessageSignatureError::InvalidEncoding(secp256k1::Error::InvalidRecoveryId)); + return Err(MessageSignatureError::InvalidEncoding( + secp256k1::Error::InvalidRecoveryId, + )); }; let recid = RecoveryId::from_i32(((bytes[0] - 27) & 0x03) as i32)?; Ok(MessageSignature { @@ -146,15 +148,11 @@ mod message_signing { pub fn recover_pubkey( &self, secp_ctx: &secp256k1::Secp256k1, - msg_hash: sha256d::Hash + msg_hash: sha256d::Hash, ) -> Result { - let msg = secp256k1::Message::from_slice(&msg_hash[..]) - .expect("cannot fail"); + let msg = secp256k1::Message::from_slice(&msg_hash[..]).expect("cannot fail"); let pubkey = secp_ctx.recover_ecdsa(&msg, &self.signature)?; - Ok(PublicKey { - inner: pubkey, - compressed: self.compressed, - }) + Ok(PublicKey { inner: pubkey, compressed: self.compressed }) } /// Verify that the signature signs the message and was signed by the given address. @@ -164,14 +162,16 @@ mod message_signing { &self, secp_ctx: &secp256k1::Secp256k1, address: &Address, - msg_hash: sha256d::Hash + msg_hash: sha256d::Hash, ) -> Result { match address.address_type() { Some(AddressType::P2pkh) => { let pubkey = self.recover_pubkey(secp_ctx, msg_hash)?; Ok(*address == Address::p2pkh(&pubkey, address.network)) } - Some(address_type) => Err(MessageSignatureError::UnsupportedAddressType(address_type)), + Some(address_type) => { + Err(MessageSignatureError::UnsupportedAddressType(address_type)) + } None => Ok(false), } } @@ -198,8 +198,11 @@ mod message_signing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bytes = self.serialize(); // This avoids the allocation of a String. - write!(f, "{}", ::base64::display::Base64Display::with_config( - &bytes[..], ::base64::STANDARD)) + write!( + f, + "{}", + ::base64::display::Base64Display::with_config(&bytes[..], ::base64::STANDARD) + ) } } @@ -241,12 +244,13 @@ pub fn script_find_and_remove(haystack: &mut Vec, needle: &[u8]) -> usize { break; } } else { - i += match opcodes::All::from((*haystack)[i]).classify(opcodes::ClassifyContext::Legacy) { + i += match opcodes::All::from((*haystack)[i]).classify(opcodes::ClassifyContext::Legacy) + { opcodes::Class::PushBytes(n) => n as usize + 1, opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => 2, opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => 3, opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => 5, - _ => 1 + _ => 1, }; } } @@ -266,18 +270,21 @@ pub fn signed_msg_hash(msg: &str) -> sha256d::Hash { #[cfg(test)] mod tests { - use super::*; use hashes::hex::ToHex; - use super::script_find_and_remove; - use super::signed_msg_hash; + + use super::{script_find_and_remove, signed_msg_hash, *}; #[test] fn test_script_find_and_remove() { - let mut v = vec![101u8, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109]; + let mut v = + vec![101u8, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109]; assert_eq!(script_find_and_remove(&mut v, &[]), 0); assert_eq!(script_find_and_remove(&mut v, &[105, 105, 105]), 0); - assert_eq!(v, vec![101, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109]); + assert_eq!( + v, + vec![101, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109] + ); assert_eq!(script_find_and_remove(&mut v, &[105, 106, 107]), 1); assert_eq!(v, vec![101, 102, 103, 104, 102, 103, 104, 102, 103, 104, 108, 109]); @@ -305,36 +312,48 @@ mod tests { #[test] fn test_script_codesep_remove() { - let mut s = vec![33u8, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 81]; + let mut s = vec![ + 33u8, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, + 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 33, + 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, + 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 81, + ]; assert_eq!(script_find_and_remove(&mut s, &[171]), 2); - assert_eq!(s, vec![33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 81]); + assert_eq!( + s, + vec![ + 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, + 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 33, + 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, + 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 81 + ] + ); } #[test] fn test_signed_msg_hash() { let hash = signed_msg_hash("test"); - assert_eq!(hash.to_hex(), "a6f87fe6d58a032c320ff8d1541656f0282c2c7bfcc69d61af4c8e8ed528e49c"); + assert_eq!( + hash.to_hex(), + "a6f87fe6d58a032c320ff8d1541656f0282c2c7bfcc69d61af4c8e8ed528e49c" + ); } #[test] #[cfg(all(feature = "secp-recovery", feature = "base64"))] fn test_message_signature() { use core::str::FromStr; - use secp256k1; - use ::AddressType; + + use {secp256k1, AddressType}; let secp = secp256k1::Secp256k1::new(); let message = "rust-bitcoin MessageSignature test"; let msg_hash = super::signed_msg_hash(&message); let msg = secp256k1::Message::from_slice(&msg_hash).expect("message"); - let privkey = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); let secp_sig = secp.sign_ecdsa_recoverable(&msg, &privkey); - let signature = super::MessageSignature { - signature: secp_sig, - compressed: true, - }; + let signature = super::MessageSignature { signature: secp_sig, compressed: true }; assert_eq!(signature.to_base64(), signature.to_string()); let signature2 = super::MessageSignature::from_str(&signature.to_string()).unwrap(); @@ -370,11 +389,12 @@ mod tests { // Signed with pk "UuOGDsfLPr4HIMKQX0ipjJeRaj1geCq3yPUF2COP5ME=" let signature_base64 = "IAM2qX24tYx/bdBTIgVLhD8QEAjrPlJpmjB4nZHdRYGIBa4DmVulAcwjPnWe6Q5iEwXH6F0pUCJP/ZeHPWS1h1o="; let pubkey_base64 = "A1FTfMEntPpAty3qkEo0q2Dc1FEycI10a3jmwEFy+Qr6"; - let signature = super::MessageSignature::from_base64(signature_base64).expect("message signature"); + let signature = + super::MessageSignature::from_base64(signature_base64).expect("message signature"); - let pubkey = PublicKey::from_slice( - &::base64::decode(&pubkey_base64).expect("base64 string") - ).expect("pubkey slice"); + let pubkey = + PublicKey::from_slice(&::base64::decode(&pubkey_base64).expect("base64 string")) + .expect("pubkey slice"); let p2pkh = ::Address::p2pkh(&pubkey, ::Network::Bitcoin); assert_eq!(signature.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(false)); diff --git a/src/util/mod.rs b/src/util/mod.rs index bace2e45bc..132f603436 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -17,32 +17,32 @@ //! Functions needed by all parts of the Bitcoin library. //! -pub mod key; -pub mod ecdsa; -pub mod schnorr; pub mod address; pub mod amount; pub mod base58; -pub mod bip32; pub mod bip143; +pub mod bip158; +pub mod bip32; +pub mod ecdsa; pub mod hash; +pub mod key; pub mod merkleblock; pub mod misc; pub mod psbt; +pub mod schnorr; +pub mod sighash; pub mod taproot; pub mod uint; -pub mod bip158; -pub mod sighash; pub(crate) mod endian; -use prelude::*; -use io; use core::fmt; -#[cfg(feature = "std")] use std::error; +#[cfg(feature = "std")] +use std::error; -use network; use consensus::encode; +use prelude::*; +use {io, network}; /// A trait which allows numbers to act as fixed-size bit arrays pub trait BitArray { @@ -92,11 +92,11 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { match *self { Error::Encode(ref e) => Some(e), Error::Network(ref e) => Some(e), - Error::BlockBadProofOfWork | Error::BlockBadTarget => None + Error::BlockBadProofOfWork | Error::BlockBadTarget => None, } } } @@ -123,7 +123,7 @@ pub(crate) fn read_to_end(mut d: D) -> Result, io::Error> { match d.read(&mut buf) { Ok(0) => break, Ok(n) => result.extend_from_slice(&buf[0..n]), - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => return Err(e), }; } diff --git a/src/util/psbt/error.rs b/src/util/psbt/error.rs index c281106de9..c83a80562f 100644 --- a/src/util/psbt/error.rs +++ b/src/util/psbt/error.rs @@ -12,16 +12,14 @@ // If not, see . // -use prelude::*; - use core::fmt; use blockdata::transaction::Transaction; use consensus::encode; -use util::psbt::raw; - use hashes; +use prelude::*; use util::bip32::ExtendedPubKey; +use util::psbt::raw; /// Enum for marking psbt hash error. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -85,24 +83,39 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), - Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), + Error::InvalidProprietaryKey => { + write!(f, "non-proprietary key type found when proprietary key was expected") + } Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), - Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), + Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!( + f, + "different unsigned transaction: expected {}, actual {}", + e.txid(), + a.txid() + ), + Error::NonStandardSighashType(ref sht) => { + write!(f, "non-standard sighash type: {}", sht) + } Error::InvalidMagic => f.write_str("invalid magic"), Error::InvalidSeparator => f.write_str("invalid separator"), - Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), - Error::UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"), + Error::UnsignedTxHasScriptSigs => { + f.write_str("the unsigned transaction has script sigs") + } + Error::UnsignedTxHasScriptWitnesses => { + f.write_str("the unsigned transaction has script witnesses") + } Error::MustHaveUnsignedTx => { f.write_str("partially signed transactions must have an unsigned transaction") } Error::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), Error::HashParseError(e) => write!(f, "Hash Parse Error: {}", e), - Error::InvalidPreimageHashPair{ref preimage, ref hash, ref hash_type} => { + Error::InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => { // directly using debug forms of psbthash enums - write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash ) + write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash) + } + Error::CombineInconsistentKeySources(ref s) => { + write!(f, "combine conflict: {}", s) } - Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) } Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"), } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 78c7f3597a..ef6798fdfa 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -14,7 +14,11 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { $crate::consensus::deserialize::<$crate::util::psbt::PartiallySignedTransaction>(&<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) }; + ($s:expr) => { + $crate::consensus::deserialize::<$crate::util::psbt::PartiallySignedTransaction>( + &<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap(), + ) + }; } macro_rules! combine { @@ -76,7 +80,9 @@ macro_rules! impl_psbtmap_consensus_decoding { loop { match $crate::consensus::Decodable::consensus_decode(&mut d) { Ok(pair) => rv.insert_pair(pair)?, - Err($crate::consensus::encode::Error::Psbt($crate::util::psbt::Error::NoMorePairs)) => return Ok(rv), + Err($crate::consensus::encode::Error::Psbt( + $crate::util::psbt::Error::NoMorePairs, + )) => return Ok(rv), Err(e) => return Err(e), } } @@ -122,7 +128,6 @@ macro_rules! impl_psbt_insert_pair { }; } - #[cfg_attr(rustfmt, rustfmt_skip)] macro_rules! impl_psbt_get_pair { ($rv:ident.push($slf:ident.$unkeyed_name:ident, $unkeyed_typeval:ident)) => { @@ -161,9 +166,8 @@ macro_rules! impl_psbt_hash_deserialize { ($hash_type:ty) => { impl $crate::util::psbt::serialize::Deserialize for $hash_type { fn deserialize(bytes: &[u8]) -> Result { - <$hash_type>::from_slice(&bytes[..]).map_err(|e| { - $crate::util::psbt::Error::from(e).into() - }) + <$hash_type>::from_slice(&bytes[..]) + .map_err(|e| $crate::util::psbt::Error::from(e).into()) } } }; diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index b6f7d51af3..9c1f2361e4 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -12,18 +12,15 @@ // If not, see . // -use prelude::*; - -use io::{self, Cursor, Read}; - use blockdata::transaction::Transaction; -use consensus::{encode, Encodable, Decodable}; use consensus::encode::MAX_VEC_SIZE; -use util::psbt::map::Map; -use util::psbt::{raw, PartiallySignedTransaction}; -use util::psbt::Error; +use consensus::{encode, Decodable, Encodable}; +use io::{self, Cursor, Read}; +use prelude::*; +use util::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint}; use util::endian::u32_to_array_le; -use util::bip32::{ExtendedPubKey, Fingerprint, DerivationPath, ChildNumber}; +use util::psbt::map::Map; +use util::psbt::{raw, Error, PartiallySignedTransaction}; /// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 const PSBT_GLOBAL_UNSIGNED_TX: u8 = 0x00; @@ -39,10 +36,7 @@ impl Map for PartiallySignedTransaction { let mut rv: Vec = Default::default(); rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_UNSIGNED_TX, - key: vec![], - }, + key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key: vec![] }, value: { // Manually serialized to ensure 0-input txs are serialized // without witnesses. @@ -66,33 +60,24 @@ impl Map for PartiallySignedTransaction { ret.extend(fingerprint.as_bytes()); derivation.into_iter().for_each(|n| ret.extend(&u32_to_array_le((*n).into()))); ret - } + }, }); } // Serializing version only for non-default value; otherwise test vectors fail if self.version > 0 { rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_VERSION, - key: vec![], - }, - value: u32_to_array_le(self.version).to_vec() + key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key: vec![] }, + value: u32_to_array_le(self.version).to_vec(), }); } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } Ok(rv) @@ -105,7 +90,8 @@ impl PartiallySignedTransaction { let mut tx: Option = None; let mut version: Option = None; let mut unknowns: BTreeMap> = Default::default(); - let mut xpub_map: BTreeMap = Default::default(); + let mut xpub_map: BTreeMap = + Default::default(); let mut proprietary: BTreeMap> = Default::default(); loop { @@ -131,13 +117,13 @@ impl PartiallySignedTransaction { }); if decoder.position() != vlen as u64 { - return Err(encode::Error::ParseFailed("data not consumed entirely when explicitly deserializing")) + return Err(encode::Error::ParseFailed("data not consumed entirely when explicitly deserializing")); } } else { - return Err(Error::DuplicateKey(pair.key).into()) + return Err(Error::DuplicateKey(pair.key).into()); } } else { - return Err(Error::InvalidKey(pair.key).into()) + return Err(Error::InvalidKey(pair.key).into()); } } PSBT_GLOBAL_XPUB => { @@ -148,7 +134,9 @@ impl PartiallySignedTransaction { ))?; if pair.value.is_empty() || pair.value.len() % 4 != 0 { - return Err(encode::Error::ParseFailed("Incorrect length of global xpub derivation data")) + return Err(encode::Error::ParseFailed( + "Incorrect length of global xpub derivation data", + )); } let child_count = pair.value.len() / 4 - 1; @@ -161,11 +149,18 @@ impl PartiallySignedTransaction { } let derivation = DerivationPath::from(path); // Keys, according to BIP-174, must be unique - if xpub_map.insert(xpub, (Fingerprint::from(&fingerprint[..]), derivation)).is_some() { - return Err(encode::Error::ParseFailed("Repeated global xpub key")) + if xpub_map + .insert(xpub, (Fingerprint::from(&fingerprint[..]), derivation)) + .is_some() + { + return Err(encode::Error::ParseFailed( + "Repeated global xpub key", + )); } } else { - return Err(encode::Error::ParseFailed("Xpub global key must contain serialized Xpub data")) + return Err(encode::Error::ParseFailed( + "Xpub global key must contain serialized Xpub data", + )); } } PSBT_GLOBAL_VERSION => { @@ -176,33 +171,43 @@ impl PartiallySignedTransaction { let vlen: usize = pair.value.len(); let mut decoder = Cursor::new(pair.value); if vlen != 4 { - return Err(encode::Error::ParseFailed("Wrong global version value length (must be 4 bytes)")) + return Err(encode::Error::ParseFailed( + "Wrong global version value length (must be 4 bytes)", + )); } version = Some(Decodable::consensus_decode(&mut decoder)?); // We only understand version 0 PSBTs. According to BIP-174 we // should throw an error if we see anything other than version 0. if version != Some(0) { - return Err(encode::Error::ParseFailed("PSBT versions greater than 0 are not supported")) + return Err(encode::Error::ParseFailed( + "PSBT versions greater than 0 are not supported", + )); } } else { - return Err(Error::DuplicateKey(pair.key).into()) + return Err(Error::DuplicateKey(pair.key).into()); } } else { - return Err(Error::InvalidKey(pair.key).into()) + return Err(Error::InvalidKey(pair.key).into()); } } - PSBT_GLOBAL_PROPRIETARY => match proprietary.entry(raw::ProprietaryKey::from_key(pair.key.clone())?) { + PSBT_GLOBAL_PROPRIETARY => match proprietary + .entry(raw::ProprietaryKey::from_key(pair.key.clone())?) + { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(pair.key).into()), - } + } + btree_map::Entry::Occupied(_) => { + return Err(Error::DuplicateKey(pair.key).into()) + } + }, _ => match unknowns.entry(pair.key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), - } + } + btree_map::Entry::Occupied(k) => { + return Err(Error::DuplicateKey(k.key().clone()).into()) + } + }, } } Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => break, @@ -218,7 +223,7 @@ impl PartiallySignedTransaction { proprietary, unknown: unknowns, inputs: vec![], - outputs: vec![] + outputs: vec![], }) } else { Err(Error::MustHaveUnsignedTx.into()) diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 1aca4bfd82..05c0f2210a 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -12,29 +12,24 @@ // If not, see . // -use prelude::*; -use io; use core::fmt; use core::str::FromStr; -use secp256k1; use blockdata::script::Script; +use blockdata::transaction::{NonStandardSighashType, SighashTypeParseError, Transaction, TxOut}; use blockdata::witness::Witness; -use blockdata::transaction::{Transaction, TxOut, NonStandardSighashType, SighashTypeParseError}; use consensus::encode; use hashes::{self, hash160, ripemd160, sha256, sha256d}; +use prelude::*; use secp256k1::XOnlyPublicKey; use util::bip32::KeySource; -use util::psbt; +use util::key::PublicKey; use util::psbt::map::Map; -use util::psbt::raw; use util::psbt::serialize::Deserialize; -use util::psbt::{Error, error}; -use util::key::PublicKey; - -use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; -use util::sighash; -use {EcdsaSighashType, SchnorrSighashType, EcdsaSig, SchnorrSig}; +use util::psbt::{error, raw, Error}; +use util::taproot::{ControlBlock, LeafVersion, TapBranchHash, TapLeafHash}; +use util::{psbt, sighash}; +use {io, secp256k1, EcdsaSig, EcdsaSighashType, SchnorrSig, SchnorrSighashType}; /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00; @@ -146,7 +141,6 @@ pub struct Input { pub unknown: BTreeMap>, } - /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash /// type can be either [`EcdsaSighashType`] or [`SchnorrSighashType`] but it is not possible to know /// directly which signature hash type the user is dealing with. Therefore, the user is responsible @@ -154,7 +148,7 @@ pub struct Input { #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct PsbtSighashType { - pub (in ::util::psbt) inner: u32, + pub(in util::psbt) inner: u32, } impl fmt::Display for PsbtSighashType { @@ -166,7 +160,7 @@ impl fmt::Display for PsbtSighashType { } } -#[allow(deprecated)] // TODO: Swap `trim_left_matches` for `trim_start_matches` once MSRV >= 1.30. +#[allow(deprecated)] // TODO: Swap `trim_left_matches` for `trim_start_matches` once MSRV >= 1.30. impl FromStr for PsbtSighashType { type Err = SighashTypeParseError; @@ -178,7 +172,9 @@ impl FromStr for PsbtSighashType { // inputs. We also do not support SIGHASH_RESERVED in verbatim form // ("0xFF" string should be used instead). match SchnorrSighashType::from_str(s) { - Ok(SchnorrSighashType::Reserved) => return Err(SighashTypeParseError{ unrecognized: s.to_owned() }), + Ok(SchnorrSighashType::Reserved) => { + return Err(SighashTypeParseError { unrecognized: s.to_owned() }) + } Ok(ty) => return Ok(ty.into()), Err(_) => {} } @@ -188,7 +184,7 @@ impl FromStr for PsbtSighashType { return Ok(PsbtSighashType { inner }); } - Err(SighashTypeParseError{ unrecognized: s.to_owned() }) + Err(SighashTypeParseError { unrecognized: s.to_owned() }) } } impl From for PsbtSighashType { @@ -228,7 +224,6 @@ impl PsbtSighashType { PsbtSighashType { inner: n } } - /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag. /// /// No guarantees are made as to the standardness or validity of the returned value. @@ -263,10 +258,7 @@ impl Input { } pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_IN_NON_WITNESS_UTXO => { @@ -315,16 +307,36 @@ impl Input { } } PSBT_IN_RIPEMD160 => { - psbt_insert_hash_pair(&mut self.ripemd160_preimages, raw_key, raw_value, error::PsbtHash::Ripemd)?; + psbt_insert_hash_pair( + &mut self.ripemd160_preimages, + raw_key, + raw_value, + error::PsbtHash::Ripemd, + )?; } PSBT_IN_SHA256 => { - psbt_insert_hash_pair(&mut self.sha256_preimages, raw_key, raw_value, error::PsbtHash::Sha256)?; + psbt_insert_hash_pair( + &mut self.sha256_preimages, + raw_key, + raw_value, + error::PsbtHash::Sha256, + )?; } PSBT_IN_HASH160 => { - psbt_insert_hash_pair(&mut self.hash160_preimages, raw_key, raw_value, error::PsbtHash::Hash160)?; + psbt_insert_hash_pair( + &mut self.hash160_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash160, + )?; } PSBT_IN_HASH256 => { - psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?; + psbt_insert_hash_pair( + &mut self.hash256_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash256, + )?; } PSBT_IN_TAP_KEY_SIG => { impl_psbt_insert_pair! { @@ -361,15 +373,19 @@ impl Input { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, - btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), + } + btree_map::Entry::Occupied(_) => { + return Err(Error::DuplicateKey(raw_key).into()) + } } } _ => match self.unknown.entry(raw_key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); } - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), + btree_map::Entry::Occupied(k) => { + return Err(Error::DuplicateKey(k.key().clone()).into()) + } }, } @@ -487,17 +503,11 @@ impl Map for Input { rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT) } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } Ok(rv) @@ -580,9 +590,7 @@ mod test { #[test] fn psbt_sighash_type_schnorr_notstd() { - for (schnorr, schnorr_str) in &[ - (SchnorrSighashType::Reserved, "0xff"), - ] { + for (schnorr, schnorr_str) in &[(SchnorrSighashType::Reserved, "0xff")] { let sighash = PsbtSighashType::from(*schnorr); let s = format!("{}", sighash); assert_eq!(&s, schnorr_str); diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index 3b25bd21f4..11c21c855a 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -12,11 +12,9 @@ // If not, see . // -use prelude::*; - -use io; - use consensus::encode; +use io; +use prelude::*; use util::psbt::raw; mod global; @@ -24,7 +22,7 @@ mod input; mod output; pub use self::input::{Input, PsbtSighashType}; -pub use self::output::{Output, TapTree, IncompleteTapTree}; +pub use self::output::{IncompleteTapTree, Output, TapTree}; /// A trait that describes a PSBT key-value map. pub(super) trait Map { diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 855524d5de..8b612f62b7 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -12,23 +12,14 @@ // If not, see . // -use prelude::*; -use core; - -use io; - use blockdata::script::Script; use consensus::encode; +use prelude::*; use secp256k1::XOnlyPublicKey; use util::bip32::KeySource; -use secp256k1; use util::psbt::map::Map; -use util::psbt::raw; -use util::psbt::Error; - -use util::taproot::{ScriptLeaf, TapLeafHash}; - -use util::taproot::{NodeInfo, TaprootBuilder}; +use util::psbt::{raw, Error}; +use util::taproot::{NodeInfo, ScriptLeaf, TapLeafHash, TaprootBuilder}; /// Type: Redeem Script PSBT_OUT_REDEEM_SCRIPT = 0x00 const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00; @@ -66,16 +57,10 @@ pub struct Output { #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))] pub tap_key_origins: BTreeMap, KeySource)>, /// Proprietary key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))] pub unknown: BTreeMap>, } @@ -93,8 +78,9 @@ impl IncompleteTapTree { /// Converts error into the original incomplete [`TaprootBuilder`] instance. pub fn into_builder(self) -> TaprootBuilder { match self { - IncompleteTapTree::NotFinalized(builder) | - IncompleteTapTree::HiddenParts(builder) => builder + IncompleteTapTree::NotFinalized(builder) | IncompleteTapTree::HiddenParts(builder) => { + builder + } } } } @@ -102,8 +88,12 @@ impl IncompleteTapTree { impl core::fmt::Display for IncompleteTapTree { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str(match self { - IncompleteTapTree::NotFinalized(_) => "an attempt to construct a tap tree from a builder containing incomplete branches.", - IncompleteTapTree::HiddenParts(_) => "an attempt to construct a tap tree from a builder containing hidden parts.", + IncompleteTapTree::NotFinalized(_) => { + "an attempt to construct a tap tree from a builder containing incomplete branches." + } + IncompleteTapTree::HiddenParts(_) => { + "an attempt to construct a tap tree from a builder containing hidden parts." + } }) } } @@ -132,7 +122,9 @@ impl TapTree { // have only 1 element in branch and that is not None. // We make sure that we only allow is_complete builders via the from_inner // constructor - self.0.branch()[0].as_ref().expect("from_inner only parses is_complete builders") + self.0.branch()[0] + .as_ref() + .expect("from_inner only parses is_complete builders") } /// Converts a [`TaprootBuilder`] into a tree if it is complete binary tree. @@ -159,11 +151,7 @@ impl TapTree { /// tree [`ScriptLeaf`]s. pub fn script_leaves(&self) -> TapTreeIter { match (self.0.branch().len(), self.0.branch().last()) { - (1, Some(Some(root))) => { - TapTreeIter { - leaf_iter: root.leaves.iter() - } - } + (1, Some(Some(root))) => TapTreeIter { leaf_iter: root.leaves.iter() }, // This should be unreachable as we Taptree is already finalized _ => unreachable!("non-finalized tree builder inside TapTree"), } @@ -187,10 +175,7 @@ impl<'tree> Iterator for TapTreeIter<'tree> { impl Output { pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_OUT_REDEEM_SCRIPT => { @@ -213,8 +198,10 @@ impl Output { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, - btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), + } + btree_map::Entry::Occupied(_) => { + return Err(Error::DuplicateKey(raw_key).into()) + } } } PSBT_OUT_TAP_INTERNAL_KEY => { @@ -236,8 +223,10 @@ impl Output { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); } - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), - } + btree_map::Entry::Occupied(k) => { + return Err(Error::DuplicateKey(k.key().clone()).into()) + } + }, } Ok(()) @@ -286,17 +275,11 @@ impl Map for Output { } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } Ok(rv) diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 4cf84ff698..b1eeb0c43a 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -23,12 +23,10 @@ use core::cmp; use blockdata::script::Script; use blockdata::transaction::Transaction; -use consensus::{encode, Encodable, Decodable}; use consensus::encode::MAX_VEC_SIZE; - -use prelude::*; - +use consensus::{encode, Decodable, Encodable}; use io; +use prelude::*; mod error; pub use self::error::Error; @@ -41,11 +39,11 @@ mod macros; pub mod serialize; mod map; -pub use self::map::{Input, Output, TapTree, PsbtSighashType, IncompleteTapTree}; -use self::map::Map; - use util::bip32::{ExtendedPubKey, KeySource}; +use self::map::Map; +pub use self::map::{IncompleteTapTree, Input, Output, PsbtSighashType, TapTree}; + /// A Partially Signed Transaction. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -142,7 +140,7 @@ impl PartiallySignedTransaction { match self.xpub.entry(xpub) { btree_map::Entry::Vacant(entry) => { entry.insert((fingerprint1, derivation1)); - }, + } btree_map::Entry::Occupied(mut entry) => { // Here in case of the conflict we select the version with algorithm: // 1) if everything is equal we do nothing @@ -155,15 +153,17 @@ impl PartiallySignedTransaction { let (fingerprint2, derivation2) = entry.get().clone(); - if (derivation1 == derivation2 && fingerprint1 == fingerprint2) || - (derivation1.len() < derivation2.len() && derivation1[..] == derivation2[derivation2.len() - derivation1.len()..]) + if (derivation1 == derivation2 && fingerprint1 == fingerprint2) + || (derivation1.len() < derivation2.len() + && derivation1[..] + == derivation2[derivation2.len() - derivation1.len()..]) { - continue - } - else if derivation2[..] == derivation1[derivation1.len() - derivation2.len()..] + continue; + } else if derivation2[..] + == derivation1[derivation1.len() - derivation2.len()..] { entry.insert((fingerprint1, derivation1)); - continue + continue; } return Err(Error::CombineInconsistentKeySources(xpub)); } @@ -187,11 +187,13 @@ impl PartiallySignedTransaction { #[cfg(feature = "base64")] mod display_from_str { - use super::PartiallySignedTransaction; - use core::fmt::{Display, Formatter, self}; + use core::fmt::{self, Display, Formatter}; use core::str::FromStr; - use consensus::encode::{Error, self}; - use ::base64::display::Base64Display; + + use base64::display::Base64Display; + use consensus::encode::{self, Error}; + + use super::PartiallySignedTransaction; /// Error happening during PSBT decoding from Base64 string #[derive(Debug)] @@ -200,7 +202,7 @@ mod display_from_str { /// Error in internal PSBT data structure PsbtEncoding(Error), /// Error in PSBT Base64 encoding - Base64Encoding(::base64::DecodeError) + Base64Encoding(::base64::DecodeError), } impl Display for PsbtParseError { @@ -219,7 +221,11 @@ mod display_from_str { #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] impl Display for PartiallySignedTransaction { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", Base64Display::with_config(&encode::serialize(self), ::base64::STANDARD)) + write!( + f, + "{}", + Base64Display::with_config(&encode::serialize(self), ::base64::STANDARD) + ) } } @@ -306,24 +312,22 @@ impl Decodable for PartiallySignedTransaction { #[cfg(test)] mod tests { - use super::*; - - use hashes::hex::FromHex; - use hashes::{sha256, hash160, Hash, ripemd160}; - use hash_types::Txid; - - use secp256k1::{Secp256k1, self}; + use std::collections::BTreeMap; use blockdata::script::Script; - use blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint}; - use network::constants::Network::Bitcoin; + use blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; + use blockdata::witness::Witness; use consensus::encode::{deserialize, serialize, serialize_hex}; + use hash_types::Txid; + use hashes::hex::FromHex; + use hashes::{hash160, ripemd160, sha256, Hash}; + use network::constants::Network::Bitcoin; + use secp256k1::{self, Secp256k1}; use util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, Fingerprint, KeySource}; - use util::psbt::map::{Output, Input}; + use util::psbt::map::{Input, Output}; use util::psbt::raw; - use std::collections::BTreeMap; - use blockdata::witness::Witness; + use super::*; #[test] fn trivial_psbt() { @@ -346,14 +350,13 @@ mod tests { } #[test] - fn psbt_uncompressed_key() { - - let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); + fn psbt_uncompressed_key() { + let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); - assert!(psbt.inputs[0].partial_sigs.len() == 1); - let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; - assert!(!pk.compressed); - } + assert!(psbt.inputs[0].partial_sigs.len() == 1); + let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; + assert!(!pk.compressed); + } #[test] fn serialize_then_deserialize_output() { @@ -405,7 +408,8 @@ mod tests { previous_output: OutPoint { txid: Txid::from_hex( "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), + ) + .unwrap(), vout: 0, }, script_sig: Script::new(), @@ -443,10 +447,7 @@ mod tests { #[test] fn serialize_then_deserialize_psbtkvpair() { let expected = raw::Pair { - key: raw::Key { - type_value: 0u8, - key: vec![42u8, 69u8], - }, + key: raw::Key { type_value: 0u8, key: vec![42u8, 69u8] }, value: vec![69u8, 42u8, 4u8], }; @@ -476,29 +477,37 @@ mod tests { lock_time: 0, input: vec![TxIn { previous_output: OutPoint { - txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(), + txid: Txid::from_hex( + "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", + ) + .unwrap(), vout: 1, }, script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), sequence: 4294967295, - witness: Witness::from_vec(vec![Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]), + witness: Witness::from_vec(vec![Vec::from_hex( + "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105", + ) + .unwrap()]), + }], + output: vec![TxOut { + value: 190303501938, + script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), }], - output: vec![ - TxOut { - value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), - }, - ], }; - let unknown: BTreeMap> = vec![( - raw::Key { type_value: 1, key: vec![0, 1] }, - vec![3, 4 ,5], - )].into_iter().collect(); + let unknown: BTreeMap> = + vec![(raw::Key { type_value: 1, key: vec![0, 1] }, vec![3, 4, 5])] + .into_iter() + .collect(); let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap()); let keypaths: BTreeMap = vec![( - "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883" + .parse() + .unwrap(), key_source.clone(), - )].into_iter().collect(); + )] + .into_iter() + .collect(); let proprietary: BTreeMap> = vec![( raw::ProprietaryKey { @@ -507,7 +516,9 @@ mod tests { key: "test_key".as_bytes().to_vec(), }, vec![5, 6, 7], - )].into_iter().collect(); + )] + .into_iter() + .collect(); let psbt = PartiallySignedTransaction { version: 0, @@ -562,20 +573,18 @@ mod tests { } mod bip_vectors { + use std::collections::BTreeMap; #[cfg(feature = "base64")] use std::str::FromStr; - use hashes::hex::FromHex; - use hash_types::Txid; - use blockdata::script::Script; - use blockdata::transaction::{EcdsaSighashType, Transaction, TxIn, TxOut, OutPoint}; - use consensus::encode::serialize_hex; - use util::psbt::map::{Map, Input, Output}; - use util::psbt::raw; - use util::psbt::{PartiallySignedTransaction, Error}; - use std::collections::BTreeMap; + use blockdata::transaction::{EcdsaSighashType, OutPoint, Transaction, TxIn, TxOut}; use blockdata::witness::Witness; + use consensus::encode::serialize_hex; + use hash_types::Txid; + use hashes::hex::FromHex; + use util::psbt::map::{Input, Map, Output}; + use util::psbt::{raw, Error, PartiallySignedTransaction}; #[test] #[should_panic(expected = "InvalidMagic")] @@ -746,11 +755,15 @@ mod tests { assert_eq!(serialize_hex(&unserialized), base16str); assert_eq!(unserialized, hex_psbt!(base16str).unwrap()); - #[cfg(feature = "base64")] { + #[cfg(feature = "base64")] + { let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA"; assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), unserialized); assert_eq!(base64str, unserialized.to_string()); - assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), hex_psbt!(base16str).unwrap()); + assert_eq!( + PartiallySignedTransaction::from_str(base64str).unwrap(), + hex_psbt!(base16str).unwrap() + ); } } @@ -790,9 +803,8 @@ mod tests { assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.txid()); assert!(psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize] - .script_pubkey - .is_p2pkh() - ); + .script_pubkey + .is_p2pkh()); assert_eq!( (&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(), EcdsaSighashType::All @@ -855,7 +867,8 @@ mod tests { let tx = &psbt.unsigned_tx; assert_eq!( tx.txid(), - Txid::from_hex("75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115").unwrap(), + Txid::from_hex("75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115") + .unwrap(), ); let mut unknown: BTreeMap> = BTreeMap::new(); @@ -872,8 +885,7 @@ mod tests { } mod bip_371_vectors { - use super::*; - use super::serialize; + use super::{serialize, *}; #[test] fn invalid_vectors() { @@ -888,7 +900,10 @@ mod tests { let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07570000220702fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da7560000800100008000000080010000000000000000").unwrap_err(); assert_eq!(err.to_string(), "parse failed: Invalid xonly public key"); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6924214022cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094089756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); - assert_eq!(err.to_string(), "PSBT error: Hash Parse Error: bad slice length 33 (expected 32)"); + assert_eq!( + err.to_string(), + "PSBT error: Hash Parse Error: bad slice length 33 (expected 32)" + ); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err(); assert_eq!(err.to_string(), "parse failed: Invalid Schnorr signature length"); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); @@ -1068,11 +1083,14 @@ mod tests { #[test] fn serialize_and_deserialize_proprietary() { let mut psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); - psbt.proprietary.insert(raw::ProprietaryKey { - prefix: b"test".to_vec(), - subtype: 0u8, - key: b"test".to_vec(), - }, b"test".to_vec()); + psbt.proprietary.insert( + raw::ProprietaryKey { + prefix: b"test".to_vec(), + subtype: 0u8, + key: b"test".to_vec(), + }, + b"test".to_vec(), + ); assert!(!psbt.proprietary.is_empty()); let rtt: PartiallySignedTransaction = hex_psbt!(&serialize_hex(&psbt)).unwrap(); assert!(!rtt.proprietary.is_empty()); diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 7e028570aa..594a472133 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -18,12 +18,14 @@ //! . //! -use prelude::*; use core::fmt; -use io; -use consensus::encode::{self, ReadExt, WriteExt, Decodable, Encodable, VarInt, serialize, deserialize, MAX_VEC_SIZE}; +use consensus::encode::{ + self, deserialize, serialize, Decodable, Encodable, ReadExt, VarInt, WriteExt, MAX_VEC_SIZE, +}; use hashes::hex; +use io; +use prelude::*; use util::psbt::Error; use util::read_to_end; @@ -56,7 +58,10 @@ pub type ProprietaryType = u8; /// structure according to BIP 174. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct ProprietaryKey where Subtype: Copy + From + Into { +pub struct ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Proprietary type prefix used for grouping together keys under some /// application and avoid namespace collision #[cfg_attr(feature = "serde", serde(with = "::serde_utils::hex_bytes"))] @@ -89,7 +94,7 @@ impl Decodable for Key { return Err(encode::Error::OversizedVectorAllocation { requested: key_byte_size as usize, max: MAX_VEC_SIZE, - }) + }); } let type_value: u8 = Decodable::consensus_decode(&mut d)?; @@ -134,7 +139,10 @@ impl Decodable for Pair { } } -impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Encodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_encode(&self, mut e: W) -> Result { let mut len = self.prefix.consensus_encode(&mut e)? + 1; e.emit_u8(self.subtype.into())?; @@ -144,7 +152,10 @@ impl Encodable for ProprietaryKey where Subtype: Copy + From Decodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Decodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_decode(mut d: D) -> Result { let prefix = Vec::::consensus_decode(&mut d)?; let subtype = Subtype::from(d.read_u8()?); @@ -154,12 +165,15 @@ impl Decodable for ProprietaryKey where Subtype: Copy + From ProprietaryKey where Subtype: Copy + From + Into { +impl ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Constructs [ProprietaryKey] from [Key]; returns /// [Error::InvalidProprietaryKey] if `key` do not starts with 0xFC byte pub fn from_key(key: Key) -> Result { if key.type_value != 0xFC { - return Err(Error::InvalidProprietaryKey) + return Err(Error::InvalidProprietaryKey); } Ok(deserialize(&key.key)?) @@ -167,9 +181,6 @@ impl ProprietaryKey where Subtype: Copy + From + Into /// Constructs full [Key] corresponding to this proprietary key type pub fn to_key(&self) -> Key { - Key { - type_value: 0xFC, - key: serialize(self) - } + Key { type_value: 0xFC, key: serialize(self) } } } diff --git a/src/util/psbt/serialize.rs b/src/util/psbt/serialize.rs index 3c946ec773..8083c9507f 100644 --- a/src/util/psbt/serialize.rs +++ b/src/util/psbt/serialize.rs @@ -18,26 +18,21 @@ //! bytes from/as PSBT key-value pairs. //! -use prelude::*; - -use io; - use blockdata::script::Script; -use blockdata::witness::Witness; use blockdata::transaction::{Transaction, TxOut}; -use consensus::encode::{self, serialize, Decodable, Encodable, deserialize_partial}; +use blockdata::witness::Witness; +use consensus::encode::{self, deserialize_partial, serialize, Decodable, Encodable}; +use hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use prelude::*; use secp256k1::{self, XOnlyPublicKey}; use util::bip32::{ChildNumber, Fingerprint, KeySource}; -use hashes::{hash160, ripemd160, sha256, sha256d, Hash}; use util::ecdsa::{EcdsaSig, EcdsaSigError}; -use util::psbt; -use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion}; -use schnorr; use util::key::PublicKey; +use util::psbt; +use util::taproot::{ControlBlock, LeafVersion, TapBranchHash, TapLeafHash, TaprootBuilder}; +use {io, schnorr}; -use super::map::{TapTree, PsbtSighashType}; - -use util::taproot::TaprootBuilder; +use super::map::{PsbtSighashType, TapTree}; /// A trait for serializing a value as raw data for insertion into PSBT /// key-value pairs. pub trait Serialize { @@ -86,8 +81,7 @@ impl Serialize for PublicKey { impl Deserialize for PublicKey { fn deserialize(bytes: &[u8]) -> Result { - PublicKey::from_slice(bytes) - .map_err(|_| encode::Error::ParseFailed("invalid public key")) + PublicKey::from_slice(bytes).map_err(|_| encode::Error::ParseFailed("invalid public key")) } } @@ -125,21 +119,18 @@ impl Deserialize for EcdsaSig { // also has a field sighash_u32 (See BIP141). For example, when signing with non-standard // 0x05, the sighash message would have the last field as 0x05u32 while, the verification // would use check the signature assuming sighash_u32 as `0x01`. - EcdsaSig::from_slice(&bytes) - .map_err(|e| match e { - EcdsaSigError::EmptySignature => { - encode::Error::ParseFailed("Empty partial signature data") - } - EcdsaSigError::NonStandardSighashType(flag) => { - encode::Error::from(psbt::Error::NonStandardSighashType(flag)) - } - EcdsaSigError::Secp256k1(..) => { - encode::Error::ParseFailed("Invalid Ecdsa signature") - } - EcdsaSigError::HexEncoding(..) => { - unreachable!("Decoding from slice, not hex") - } - }) + EcdsaSig::from_slice(&bytes).map_err(|e| match e { + EcdsaSigError::EmptySignature => { + encode::Error::ParseFailed("Empty partial signature data") + } + EcdsaSigError::NonStandardSighashType(flag) => { + encode::Error::from(psbt::Error::NonStandardSighashType(flag)) + } + EcdsaSigError::Secp256k1(..) => encode::Error::ParseFailed("Invalid Ecdsa signature"), + EcdsaSigError::HexEncoding(..) => { + unreachable!("Decoding from slice, not hex") + } + }) } } @@ -160,7 +151,7 @@ impl Serialize for KeySource { impl Deserialize for KeySource { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 4 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let fprint: Fingerprint = Fingerprint::from(&bytes[0..4]); @@ -218,7 +209,7 @@ impl Deserialize for XOnlyPublicKey { } } -impl Serialize for schnorr::SchnorrSig { +impl Serialize for schnorr::SchnorrSig { fn serialize(&self) -> Vec { self.to_vec() } @@ -226,18 +217,17 @@ impl Serialize for schnorr::SchnorrSig { impl Deserialize for schnorr::SchnorrSig { fn deserialize(bytes: &[u8]) -> Result { - schnorr::SchnorrSig::from_slice(&bytes) - .map_err(|e| match e { - schnorr::SchnorrSigError::InvalidSighashType(flag) => { - encode::Error::from(psbt::Error::NonStandardSighashType(flag as u32)) - } - schnorr::SchnorrSigError::InvalidSchnorrSigSize(_) => { - encode::Error::ParseFailed("Invalid Schnorr signature length") - } - schnorr::SchnorrSigError::Secp256k1(..) => { - encode::Error::ParseFailed("Invalid Schnorr signature") - } - }) + schnorr::SchnorrSig::from_slice(&bytes).map_err(|e| match e { + schnorr::SchnorrSigError::InvalidSighashType(flag) => { + encode::Error::from(psbt::Error::NonStandardSighashType(flag as u32)) + } + schnorr::SchnorrSigError::InvalidSchnorrSigSize(_) => { + encode::Error::ParseFailed("Invalid Schnorr signature length") + } + schnorr::SchnorrSigError::Secp256k1(..) => { + encode::Error::ParseFailed("Invalid Schnorr signature") + } + }) } } @@ -254,7 +244,7 @@ impl Serialize for (XOnlyPublicKey, TapLeafHash) { impl Deserialize for (XOnlyPublicKey, TapLeafHash) { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 32 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; @@ -270,8 +260,7 @@ impl Serialize for ControlBlock { impl Deserialize for ControlBlock { fn deserialize(bytes: &[u8]) -> Result { - Self::from_slice(bytes) - .map_err(|_| encode::Error::ParseFailed("Invalid control block")) + Self::from_slice(bytes).map_err(|_| encode::Error::ParseFailed("Invalid control block")) } } @@ -288,7 +277,7 @@ impl Serialize for (Script, LeafVersion) { impl Deserialize for (Script, LeafVersion) { fn deserialize(bytes: &[u8]) -> Result { if bytes.is_empty() { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } // The last byte is LeafVersion. let script = Script::deserialize(&bytes[..bytes.len() - 1])?; @@ -298,10 +287,9 @@ impl Deserialize for (Script, LeafVersion) { } } - impl Serialize for (Vec, KeySource) { fn serialize(&self) -> Vec { - let mut buf = Vec::with_capacity( 32 * self.0.len() + key_source_len(&self.1)); + let mut buf = Vec::with_capacity(32 * self.0.len() + key_source_len(&self.1)); self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation"); // TODO: Add support for writing into a writer for key-source buf.extend(self.1.serialize()); @@ -333,7 +321,7 @@ impl Serialize for TapTree { } buf } - // This should be unreachable as we Taptree is already finalized + // This should be unreachable as we Taptree is already finalized _ => unreachable!(), } } @@ -344,7 +332,8 @@ impl Deserialize for TapTree { let mut builder = TaprootBuilder::new(); let mut bytes_iter = bytes.iter(); while let Some(depth) = bytes_iter.next() { - let version = bytes_iter.next().ok_or(encode::Error::ParseFailed("Invalid Taproot Builder"))?; + let version = + bytes_iter.next().ok_or(encode::Error::ParseFailed("Invalid Taproot Builder"))?; let (script, consumed) = deserialize_partial::