From d156c65778aa38a9bcdaf7c7d77e59bae55187f9 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 26 Dec 2019 12:39:03 +0800 Subject: [PATCH 0001/1740] Fix serde struct macros deserialization impls The Deserialize impls generated by serde_struct_impl and serde_struct_human_string_impl need to be able to handle serialization formats which serialize structs as sequences (such as bincode). This commit adds visit_seq methods to the Visitor types defined by these macros, in addition to the existing visit_map methods. The implementation is taken directly from the serde docs: https://serde.rs/deserialize-struct.html --- src/internal_macros.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 362a2290..6307e330 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -282,6 +282,28 @@ macro_rules! serde_struct_impl { formatter.write_str("a struct") } + fn visit_seq(self, mut seq: V) -> Result + where + V: $crate::serde::de::SeqAccess<'de>, + { + use $crate::serde::de::Error; + + let length = 0; + $( + let $fe = seq.next_element()?.ok_or_else(|| { + Error::invalid_length(length, &self) + })?; + #[allow(unused_variables)] + let length = length + 1; + )* + + let ret = $name { + $($fe: $fe),* + }; + + Ok(ret) + } + fn visit_map(self, mut map: A) -> Result where A: $crate::serde::de::MapAccess<'de>, @@ -498,6 +520,28 @@ macro_rules! serde_struct_human_string_impl { formatter.write_str("a struct") } + fn visit_seq(self, mut seq: V) -> Result + where + V: $crate::serde::de::SeqAccess<'de>, + { + use $crate::serde::de::Error; + + let length = 0; + $( + let $fe = seq.next_element()?.ok_or_else(|| { + Error::invalid_length(length, &self) + })?; + #[allow(unused_variables)] + let length = length + 1; + )* + + let ret = $name { + $($fe: $fe),* + }; + + Ok(ret) + } + fn visit_map(self, mut map: A) -> Result where A: $crate::serde::de::MapAccess<'de>, From 2326dd6a82757214741dc66b262f8206fbd620dd Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 9 Jan 2020 11:11:49 +0000 Subject: [PATCH 0002/1740] Update secp256k1's rand feature to rand-std --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0409be7a..a05275d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ path = "src/lib.rs" [features] fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"] unstable = [] -rand = ["secp256k1/rand"] +rand = ["secp256k1/rand-std"] use-serde = ["hex", "serde", "bitcoin_hashes/serde", "secp256k1/serde"] [dependencies] @@ -34,4 +34,4 @@ hex = "=0.3.2" serde_derive = "<1.0.99" serde_json = "1" serde_test = "1" -secp256k1 = { version = "0.17.1", features = ["rand"] } +secp256k1 = { version = "0.17.1", features = ["rand-std"] } From 8e52b8ce4d8bcb7d2900a08101ea5e62c88b268a Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 10 Jan 2020 11:34:16 +0000 Subject: [PATCH 0003/1740] Remove the BitcoinHash trait Replaced by a `block_hash` method on both `Block` and `BlockHeader`. --- src/blockdata/block.rs | 29 ++++++++++++++--------------- src/blockdata/constants.rs | 5 ++--- src/lib.rs | 1 - src/util/bip158.rs | 7 +++---- src/util/hash.rs | 6 ------ src/util/merkleblock.rs | 8 ++++---- 6 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index f67e8586..2fff8f03 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -22,7 +22,7 @@ use util; use util::Error::{BlockBadTarget, BlockBadProofOfWork}; -use util::hash::{BitcoinHash, bitcoin_merkle_root}; +use util::hash::bitcoin_merkle_root; use hashes::{Hash, HashEngine}; use hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; use util::uint::Uint256; @@ -61,6 +61,11 @@ pub struct Block { } impl Block { + /// Return the block hash. + pub fn block_hash(&self) -> BlockHash { + self.header.block_hash() + } + /// check if merkle root of header matches merkle root of the transaction list pub fn check_merkle_root (&self) -> bool { self.header.merkle_root == self.merkle_root() @@ -122,6 +127,13 @@ impl Block { } impl BlockHeader { + /// Return the block hash. + pub fn block_hash(&self) -> BlockHash { + let mut engine = BlockHash::engine(); + self.consensus_encode(&mut engine).expect("engines don't error"); + BlockHash::from_engine(engine) + } + /// Computes the target [0, T] that a blockhash must land in to be valid pub fn target(&self) -> Uint256 { // This is a floating-point "compact" encoding originally used by @@ -174,7 +186,7 @@ impl BlockHeader { if target != required_target { return Err(BlockBadTarget); } - let data: [u8; 32] = self.bitcoin_hash().into_inner(); + let data: [u8; 32] = self.block_hash().into_inner(); let mut ret = [0u64; 4]; util::endian::bytes_to_u64_slice_le(&data, &mut ret); let hash = &Uint256(ret); @@ -193,19 +205,6 @@ impl BlockHeader { } } -impl BitcoinHash for BlockHeader { - fn bitcoin_hash(&self) -> BlockHash { - use consensus::encode::serialize; - BlockHash::hash(&serialize(self)) - } -} - -impl BitcoinHash for Block { - fn bitcoin_hash(&self) -> BlockHash { - self.header.bitcoin_hash() - } -} - impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce); impl_consensus_encoding!(Block, header, txdata); serde_struct_impl!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce); diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 23622918..a5056c8f 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -151,7 +151,6 @@ mod test { use consensus::encode::serialize; use blockdata::constants::{genesis_block, bitcoin_genesis_tx}; use blockdata::constants::{MAX_SEQUENCE, COIN_VALUE}; - use util::hash::BitcoinHash; #[test] fn bitcoin_genesis_first_transaction() { @@ -186,7 +185,7 @@ mod test { assert_eq!(gen.header.time, 1231006505); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 2083236893); - assert_eq!(format!("{:x}", gen.header.bitcoin_hash()), + assert_eq!(format!("{:x}", gen.header.block_hash()), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f".to_string()); } @@ -200,7 +199,7 @@ mod test { assert_eq!(gen.header.time, 1296688602); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 414098458); - assert_eq!(format!("{:x}", gen.header.bitcoin_hash()), + assert_eq!(format!("{:x}", gen.header.block_hash()), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string()); } } diff --git a/src/lib.rs b/src/lib.rs index 6ba26f92..f122b931 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,7 +97,6 @@ pub use util::address::Address; pub use util::address::AddressType; pub use util::amount::Amount; pub use util::amount::SignedAmount; -pub use util::hash::BitcoinHash; pub use util::key::PrivateKey; pub use util::key::PublicKey; pub use util::merkleblock::MerkleBlock; diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 1d71d01d..b7154bfe 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -59,7 +59,6 @@ use blockdata::transaction::OutPoint; use consensus::{Decodable, Encodable}; use consensus::encode::VarInt; use util::endian; -use util::hash::BitcoinHash; /// Golomb encoding parameter as in BIP-158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 const P: u8 = 19; @@ -155,7 +154,7 @@ pub struct BlockFilterWriter<'a> { impl<'a> BlockFilterWriter<'a> { /// Create a block filter writer pub fn new(writer: &'a mut io::Write, block: &'a Block) -> BlockFilterWriter<'a> { - let block_hash_as_int = block.bitcoin_hash().into_inner(); + let block_hash_as_int = block.block_hash().into_inner(); let k0 = endian::slice_to_u64_le(&block_hash_as_int[0..8]); let k1 = endian::slice_to_u64_le(&block_hash_as_int[8..16]); let writer = GCSFilterWriter::new(writer, k0, k1, M, P); @@ -559,7 +558,7 @@ mod test { 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(hex::decode(&t.get(2).unwrap().as_str().unwrap().as_bytes()).unwrap().as_slice()).unwrap(); - assert_eq!(block.bitcoin_hash(), block_hash); + assert_eq!(block.block_hash(), block_hash); let scripts = t.get(3).unwrap().as_array().unwrap(); let previous_filter_id = FilterHash::from_hex(&t.get(4).unwrap().as_str().unwrap()).unwrap(); let filter_content = hex::decode(&t.get(5).unwrap().as_str().unwrap().as_bytes()).unwrap(); @@ -584,7 +583,7 @@ mod test { assert_eq!(test_filter.content, filter.content); - let block_hash = &block.header.bitcoin_hash(); + 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()); diff --git a/src/util/hash.rs b/src/util/hash.rs index 0de4731f..ba7b6d20 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -75,9 +75,3 @@ pub fn bitcoin_merkle_root(mut iter: I) -> T } bitcoin_merkle_root_inline(&mut alloc) } - -/// Objects which are referred to by hash -pub trait BitcoinHash { - /// Produces a Sha256dHash which can be used to refer to the object - fn bitcoin_hash(&self) -> T; -} diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 3dca69d8..b1365751 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -502,7 +502,7 @@ mod tests { use secp256k1::rand::prelude::*; use consensus::encode::{deserialize, serialize}; - use util::hash::{bitcoin_merkle_root, BitcoinHash}; + use util::hash::bitcoin_merkle_root; use util::merkleblock::{MerkleBlock, PartialMerkleTree}; use {hex, Block}; @@ -616,7 +616,7 @@ mod tests { af156d6fc30b55fad4112df2b95531e68114e9ad10011e72f7b7cfdb025700"; let mb: MerkleBlock = deserialize(&hex::decode(mb_hex).unwrap()).unwrap(); - assert_eq!(get_block_13b8a().bitcoin_hash(), mb.header.bitcoin_hash()); + assert_eq!(get_block_13b8a().block_hash(), mb.header.block_hash()); assert_eq!( mb.header.merkle_root, mb.txn.extract_matches(&mut vec![], &mut vec![]).unwrap() @@ -645,7 +645,7 @@ mod tests { let merkle_block = MerkleBlock::from_block(&block, &txids); - assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash()); + assert_eq!(merkle_block.header.block_hash(), block.block_hash()); let mut matches: Vec = vec![]; let mut index: Vec = vec![]; @@ -678,7 +678,7 @@ mod tests { let merkle_block = MerkleBlock::from_block(&block, &txids); - assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash()); + assert_eq!(merkle_block.header.block_hash(), block.block_hash()); let mut matches: Vec = vec![]; let mut index: Vec = vec![]; From 09c0e7fbdef770de450e6409a43699429d9cd71e Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 14 Jan 2020 11:07:58 -0500 Subject: [PATCH 0004/1740] Add WITNESS_SCALE_FACTOR constant --- src/blockdata/constants.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 23622918..b41d8c92 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -44,6 +44,8 @@ pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600; pub const MAX_BLOCK_WEIGHT: u32 = 4_000_000; /// The minimum transaction weight for a valid serialized transaction pub const MIN_TRANSACTION_WEIGHT: u32 = 4 * 60; +/// The factor that non-witness serialization data is multiplied by during weight calculation +pub const WITNESS_SCALE_FACTOR: usize = 4; /// In Bitcoind this is insanely described as ~((u256)0 >> 32) From 3624ee82c8b294a6bc42094120a8046ca249eed9 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 14 Jan 2020 11:11:43 -0500 Subject: [PATCH 0005/1740] Use witness scaling constant in get_weight --- src/blockdata/transaction.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 7beac7f5..eed1349c 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -30,6 +30,7 @@ use hashes::{self, Hash, sha256d}; use hashes::hex::FromHex; use util::endian; +use blockdata::constants::WITNESS_SCALE_FACTOR; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; use consensus::{encode, serialize, Decodable, Encodable}; @@ -391,7 +392,7 @@ impl Transaction { let mut input_weight = 0; let mut inputs_with_witnesses = 0; for input in &self.input { - input_weight += 4*(32 + 4 + 4 + // outpoint (32+4) + nSequence + input_weight += WITNESS_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() { @@ -418,9 +419,9 @@ impl Transaction { // lock_time 4; if inputs_with_witnesses == 0 { - non_input_size * 4 + input_weight + non_input_size * WITNESS_SCALE_FACTOR + input_weight } else { - non_input_size * 4 + input_weight + self.input.len() - inputs_with_witnesses + 2 + non_input_size * WITNESS_SCALE_FACTOR + input_weight + self.input.len() - inputs_with_witnesses + 2 } } From 2916685ca65944248e284fea4c28315ab847ce9c Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 14 Jan 2020 11:12:21 -0500 Subject: [PATCH 0006/1740] small Transaction test cleanup --- src/blockdata/transaction.rs | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index eed1349c..c2708579 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -624,6 +624,7 @@ mod tests { use super::{OutPoint, ParseOutPointError, Transaction, TxIn}; use std::str::FromStr; + use blockdata::constants::WITNESS_SCALE_FACTOR; use blockdata::script::Script; use consensus::encode::serialize; use consensus::encode::deserialize; @@ -689,15 +690,15 @@ mod tests { let genesis = constants::genesis_block(Network::Bitcoin); assert! (genesis.txdata[0].is_coin_base()); - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert!(!tx.is_coin_base()); } #[test] fn test_nonsegwit_transaction() { - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let tx: Result = deserialize(&hex_tx); + let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx: Result = deserialize(&tx_bytes); assert!(tx.is_ok()); let realtx = tx.unwrap(); // All these tests aren't really needed because if they fail, the hash check at the end @@ -716,19 +717,19 @@ mod tests { "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); assert_eq!(format!("{:x}", realtx.wtxid()), "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); - assert_eq!(realtx.get_weight(), 193*4); + assert_eq!(realtx.get_weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR); } #[test] fn test_segwit_transaction() { - let hex_tx = Vec::::from_hex( + let tx_bytes = Vec::::from_hex( "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\ 0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\ 55d3bcb8627d085e94553e62f057dcc00000000" ).unwrap(); - let tx: Result = deserialize(&hex_tx); + let tx: Result = deserialize(&tx_bytes); assert!(tx.is_ok()); let realtx = tx.unwrap(); // All these tests aren't really needed because if they fail, the hash check at the end @@ -752,22 +753,22 @@ mod tests { #[test] fn tx_no_input_deserialization() { - let hex_tx = Vec::::from_hex( + let tx_bytes = Vec::::from_hex( "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000" ).unwrap(); - let tx: Transaction = deserialize(&hex_tx).expect("deserialize tx"); + let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx"); assert_eq!(tx.input.len(), 0); assert_eq!(tx.output.len(), 1); let reser = serialize(&tx); - assert_eq!(hex_tx, reser); + assert_eq!(tx_bytes, reser); } #[test] fn test_ntxid() { - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let mut tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let mut tx: Transaction = deserialize(&tx_bytes).unwrap(); let old_ntxid = tx.ntxid(); assert_eq!(format!("{:x}", old_ntxid), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"); @@ -782,7 +783,7 @@ mod tests { #[test] fn test_txid() { // segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction - let hex_tx = Vec::::from_hex( + let tx_bytes = Vec::::from_hex( "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\ 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\ @@ -812,14 +813,14 @@ mod tests { 5a2b5e0e09a535e61690647021023222ceec58b94bd25925dd9743dae6b928737491bd940fc5dd7c6f5d5f\ 2adc1e53ae00000000" ).unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert_eq!(format!("{:x}", tx.wtxid()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); assert_eq!(tx.get_weight(), 2718); // non-segwit tx from my mempool - let hex_tx = Vec::::from_hex( + let tx_bytes = Vec::::from_hex( "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\ 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\ 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\ @@ -827,7 +828,7 @@ mod tests { bcfd08473d2b76b02a48f8c69088ac0000000000000000296a273236303039343836393731373233313237\ 3633313032313332353630353838373931323132373000000000" ).unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert_eq!(format!("{:x}", tx.wtxid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); @@ -836,8 +837,8 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_txn_encode_decode() { - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); serde_round_trip!(tx); } @@ -857,13 +858,13 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_segwit_tx_decode() { - let hex_tx = Vec::::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let tx_bytes = Vec::::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert_eq!(tx.get_weight(), 780); serde_round_trip!(tx); let consensus_encoded = serialize(&tx); - assert_eq!(consensus_encoded, hex_tx); + assert_eq!(consensus_encoded, tx_bytes); } From c19b7365665ea6536534fe3b2c06b7d347909907 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 8 Jan 2020 19:02:30 +0200 Subject: [PATCH 0007/1740] Remove the hex dependency --- Cargo.toml | 3 +-- src/blockdata/block.rs | 18 ++++++++-------- src/blockdata/constants.rs | 8 +++---- src/blockdata/script.rs | 17 ++++++++------- src/blockdata/transaction.rs | 36 ++++++++++++++++---------------- src/internal_macros.rs | 4 ++-- src/lib.rs | 1 - src/network/message.rs | 10 ++++----- src/network/message_blockdata.rs | 10 ++++----- src/network/message_network.rs | 4 ++-- src/network/stream_reader.rs | 10 ++++----- src/util/address.rs | 11 +++++----- src/util/base58.rs | 7 ++++--- src/util/bip143.rs | 10 ++++----- src/util/bip32.rs | 8 +++---- src/util/contracthash.rs | 4 ++-- src/util/merkleblock.rs | 6 +++--- src/util/psbt/macros.rs | 2 +- src/util/psbt/mod.rs | 18 +++++++--------- 19 files changed, 90 insertions(+), 97 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a05275d9..0eb1140d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ path = "src/lib.rs" fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"] unstable = [] rand = ["secp256k1/rand-std"] -use-serde = ["hex", "serde", "bitcoin_hashes/serde", "secp256k1/serde"] +use-serde = ["serde", "bitcoin_hashes/serde", "secp256k1/serde"] [dependencies] bech32 = "0.7.2" @@ -27,7 +27,6 @@ secp256k1 = "0.17.1" bitcoinconsensus = { version = "0.19.0-1", optional = true } serde = { version = "1", optional = true } -hex = { version = "=0.3.2", optional = true } [dev-dependencies] hex = "=0.3.2" diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 2fff8f03..059ab9ae 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -212,18 +212,18 @@ serde_struct_impl!(Block, header, txdata); #[cfg(test)] mod tests { - use hex::decode as hex_decode; + use hashes::hex::FromHex; use blockdata::block::{Block, BlockHeader}; use consensus::encode::{deserialize, serialize}; #[test] fn block_test() { - let some_block = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap(); - let cutoff_block = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap(); + let some_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap(); + let cutoff_block = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap(); - let prevhash = hex_decode("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); - let merkle = hex_decode("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); + let prevhash = Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); + let merkle = Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); let decode: Result = deserialize(&some_block); let bad_decode: Result = deserialize(&cutoff_block); @@ -249,12 +249,12 @@ mod tests { // Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b #[test] fn segwit_block_test() { - let segwit_block = hex_decode("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e5503bd5750d4061a4ed90a700f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000").unwrap(); + let segwit_block = Vec::from_hex("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e5503bd5750d4061a4ed90a700f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000").unwrap(); let decode: Result = deserialize(&segwit_block); - let prevhash = hex_decode("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000").unwrap(); - let merkle = hex_decode("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e").unwrap(); + let prevhash = Vec::from_hex("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000").unwrap(); + let merkle = Vec::from_hex("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e").unwrap(); assert!(decode.is_ok()); let real_decode = decode.unwrap(); @@ -274,7 +274,7 @@ mod tests { #[test] fn compact_roundrtip_test() { - let some_header = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); + let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header"); diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index b7e3d8c3..8cbb5bd4 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -84,7 +84,7 @@ fn bitcoin_genesis_tx() -> Transaction { // Outputs let out_script = script::Builder::new() - .push_slice(&Vec::::from_hex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()) + .push_slice(&Vec::from_hex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()) .push_opcode(opcodes::all::OP_CHECKSIG) .into_script(); ret.output.push(TxOut { @@ -147,7 +147,7 @@ pub fn genesis_block(network: Network) -> Block { #[cfg(test)] mod test { use std::default::Default; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use network::constants::Network; use consensus::encode::serialize; @@ -163,12 +163,12 @@ mod test { assert_eq!(gen.input[0].previous_output.txid, Default::default()); assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF); assert_eq!(serialize(&gen.input[0].script_sig), - hex_decode("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73").unwrap()); + Vec::from_hex("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73").unwrap()); assert_eq!(gen.input[0].sequence, MAX_SEQUENCE); assert_eq!(gen.output.len(), 1); assert_eq!(serialize(&gen.output[0].script_pubkey), - hex_decode("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac").unwrap()); + Vec::from_hex("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac").unwrap()); assert_eq!(gen.output[0].value, 50 * COIN_VALUE); assert_eq!(gen.lock_time, 0); diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 508a91da..d71b936c 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -693,6 +693,7 @@ impl<'de> serde::Deserialize<'de> for Script { D: serde::Deserializer<'de>, { use std::fmt::Formatter; + use hashes::hex::FromHex; struct Visitor; impl<'de> serde::de::Visitor<'de> for Visitor { @@ -706,7 +707,7 @@ impl<'de> serde::Deserialize<'de> for Script { where E: serde::de::Error, { - let v: Vec = ::hex::decode(v).map_err(E::custom)?; + let v = Vec::from_hex(v).map_err(E::custom)?; Ok(Script::from(v)) } @@ -761,7 +762,7 @@ impl Decodable for Script { #[cfg(test)] mod test { use std::str::FromStr; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use super::*; use super::build_scriptint; @@ -796,10 +797,10 @@ mod test { // keys let keystr = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; let key = PublicKey::from_str(&keystr[2..]).unwrap(); - script = script.push_key(&key); comp.extend(hex_decode(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(hex_decode(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[..]); @@ -811,7 +812,7 @@ mod test { // 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(&hex_decode("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap()) + .push_slice(&Vec::from_hex("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap()) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_CHECKSIG) .into_script(); @@ -892,7 +893,7 @@ mod test { #[test] fn script_serialize() { - let hex_script = hex_decode("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52").unwrap(); + let hex_script = Vec::from_hex("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52").unwrap(); let script: Result = deserialize(&hex_script); assert!(script.is_ok()); assert_eq!(serialize(&script.unwrap()), hex_script); @@ -1082,8 +1083,8 @@ mod test { #[cfg(feature="bitcoinconsensus")] fn test_bitcoinconsensus () { // a random segwit transaction from the blockchain using native segwit - let spent = Builder::from(hex_decode("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d").unwrap()).into_script(); - let spending = hex_decode("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap(); + let spent = Builder::from(Vec::from_hex("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d").unwrap()).into_script(); + let spending = Vec::from_hex("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap(); spent.verify(0, 18393430, spending.as_slice()).unwrap(); } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index c2708579..286cc2cb 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -669,7 +669,7 @@ mod tests { #[test] fn test_txin() { - let txin: Result = deserialize(&Vec::::from_hex("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff").unwrap()); + let txin: Result = deserialize(&Vec::from_hex("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff").unwrap()); assert!(txin.is_ok()); } @@ -690,14 +690,14 @@ mod tests { let genesis = constants::genesis_block(Network::Bitcoin); assert! (genesis.txdata[0].is_coin_base()); - let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert!(!tx.is_coin_base()); } #[test] fn test_nonsegwit_transaction() { - let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Result = deserialize(&tx_bytes); assert!(tx.is_ok()); let realtx = tx.unwrap(); @@ -722,7 +722,7 @@ mod tests { #[test] fn test_segwit_transaction() { - let tx_bytes = Vec::::from_hex( + let tx_bytes = Vec::from_hex( "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\ @@ -753,7 +753,7 @@ mod tests { #[test] fn tx_no_input_deserialization() { - let tx_bytes = Vec::::from_hex( + let tx_bytes = Vec::from_hex( "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000" ).unwrap(); let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx"); @@ -767,7 +767,7 @@ mod tests { #[test] fn test_ntxid() { - let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let mut tx: Transaction = deserialize(&tx_bytes).unwrap(); let old_ntxid = tx.ntxid(); @@ -783,7 +783,7 @@ mod tests { #[test] fn test_txid() { // segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction - let tx_bytes = Vec::::from_hex( + let tx_bytes = Vec::from_hex( "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\ 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\ @@ -820,7 +820,7 @@ mod tests { assert_eq!(tx.get_weight(), 2718); // non-segwit tx from my mempool - let tx_bytes = Vec::::from_hex( + let tx_bytes = Vec::from_hex( "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\ 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\ 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\ @@ -837,15 +837,15 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_txn_encode_decode() { - let tx_bytes = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); serde_round_trip!(tx); } 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(); + 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(); raw_expected.reverse(); let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap(); @@ -858,7 +858,7 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_segwit_tx_decode() { - let tx_bytes = Vec::::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let tx_bytes = Vec::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert_eq!(tx.get_weight(), 780); serde_round_trip!(tx); @@ -1167,17 +1167,17 @@ mod tests { #[test] #[cfg(feature="bitcoinconsensus")] fn test_transaction_verify () { - use hex::decode as hex_decode; + use hashes::hex::FromHex; use std::collections::HashMap; use blockdata::script; // a random recent segwit transaction from blockchain using both old and segwit inputs - let mut spending: Transaction = deserialize(hex_decode("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700") + let mut spending: Transaction = deserialize(Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700") .unwrap().as_slice()).unwrap(); - let spent1: Transaction = deserialize(hex_decode("020000000001040aacd2c49f5f3c0968cfa8caf9d5761436d95385252e3abb4de8f5dcf8a582f20000000017160014bcadb2baea98af0d9a902e53a7e9adff43b191e9feffffff96cd3c93cac3db114aafe753122bd7d1afa5aa4155ae04b3256344ecca69d72001000000171600141d9984579ceb5c67ebfbfb47124f056662fe7adbfeffffffc878dd74d3a44072eae6178bb94b9253177db1a5aaa6d068eb0e4db7631762e20000000017160014df2a48cdc53dae1aba7aa71cb1f9de089d75aac3feffffffe49f99275bc8363f5f593f4eec371c51f62c34ff11cc6d8d778787d340d6896c0100000017160014229b3b297a0587e03375ab4174ef56eeb0968735feffffff03360d0f00000000001976a9149f44b06f6ee92ddbc4686f71afe528c09727a5c788ac24281b00000000001976a9140277b4f68ff20307a2a9f9b4487a38b501eb955888ac227c0000000000001976a9148020cd422f55eef8747a9d418f5441030f7c9c7788ac0247304402204aa3bd9682f9a8e101505f6358aacd1749ecf53a62b8370b97d59243b3d6984f02200384ad449870b0e6e89c92505880411285ecd41cf11e7439b973f13bad97e53901210205b392ffcb83124b1c7ce6dd594688198ef600d34500a7f3552d67947bbe392802473044022033dfd8d190a4ae36b9f60999b217c775b96eb10dee3a1ff50fb6a75325719106022005872e4e36d194e49ced2ebcf8bb9d843d842e7b7e0eb042f4028396088d292f012103c9d7cbf369410b090480de2aa15c6c73d91b9ffa7d88b90724614b70be41e98e0247304402207d952de9e59e4684efed069797e3e2d993e9f98ec8a9ccd599de43005fe3f713022076d190cc93d9513fc061b1ba565afac574e02027c9efbfa1d7b71ab8dbb21e0501210313ad44bc030cc6cb111798c2bf3d2139418d751c1e79ec4e837ce360cc03b97a024730440220029e75edb5e9413eb98d684d62a077b17fa5b7cc19349c1e8cc6c4733b7b7452022048d4b9cae594f03741029ff841e35996ef233701c1ea9aa55c301362ea2e2f68012103590657108a72feb8dc1dec022cf6a230bb23dc7aaa52f4032384853b9f8388baf9d20700") + let spent1: Transaction = deserialize(Vec::from_hex("020000000001040aacd2c49f5f3c0968cfa8caf9d5761436d95385252e3abb4de8f5dcf8a582f20000000017160014bcadb2baea98af0d9a902e53a7e9adff43b191e9feffffff96cd3c93cac3db114aafe753122bd7d1afa5aa4155ae04b3256344ecca69d72001000000171600141d9984579ceb5c67ebfbfb47124f056662fe7adbfeffffffc878dd74d3a44072eae6178bb94b9253177db1a5aaa6d068eb0e4db7631762e20000000017160014df2a48cdc53dae1aba7aa71cb1f9de089d75aac3feffffffe49f99275bc8363f5f593f4eec371c51f62c34ff11cc6d8d778787d340d6896c0100000017160014229b3b297a0587e03375ab4174ef56eeb0968735feffffff03360d0f00000000001976a9149f44b06f6ee92ddbc4686f71afe528c09727a5c788ac24281b00000000001976a9140277b4f68ff20307a2a9f9b4487a38b501eb955888ac227c0000000000001976a9148020cd422f55eef8747a9d418f5441030f7c9c7788ac0247304402204aa3bd9682f9a8e101505f6358aacd1749ecf53a62b8370b97d59243b3d6984f02200384ad449870b0e6e89c92505880411285ecd41cf11e7439b973f13bad97e53901210205b392ffcb83124b1c7ce6dd594688198ef600d34500a7f3552d67947bbe392802473044022033dfd8d190a4ae36b9f60999b217c775b96eb10dee3a1ff50fb6a75325719106022005872e4e36d194e49ced2ebcf8bb9d843d842e7b7e0eb042f4028396088d292f012103c9d7cbf369410b090480de2aa15c6c73d91b9ffa7d88b90724614b70be41e98e0247304402207d952de9e59e4684efed069797e3e2d993e9f98ec8a9ccd599de43005fe3f713022076d190cc93d9513fc061b1ba565afac574e02027c9efbfa1d7b71ab8dbb21e0501210313ad44bc030cc6cb111798c2bf3d2139418d751c1e79ec4e837ce360cc03b97a024730440220029e75edb5e9413eb98d684d62a077b17fa5b7cc19349c1e8cc6c4733b7b7452022048d4b9cae594f03741029ff841e35996ef233701c1ea9aa55c301362ea2e2f68012103590657108a72feb8dc1dec022cf6a230bb23dc7aaa52f4032384853b9f8388baf9d20700") .unwrap().as_slice()).unwrap(); - let spent2: Transaction = deserialize(hex_decode("0200000000010166c3d39490dc827a2594c7b17b7d37445e1f4b372179649cd2ce4475e3641bbb0100000017160014e69aa750e9bff1aca1e32e57328b641b611fc817fdffffff01e87c5d010000000017a914f3890da1b99e44cd3d52f7bcea6a1351658ea7be87024830450221009eb97597953dc288de30060ba02d4e91b2bde1af2ecf679c7f5ab5989549aa8002202a98f8c3bd1a5a31c0d72950dd6e2e3870c6c5819a6c3db740e91ebbbc5ef4800121023f3d3b8e74b807e32217dea2c75c8d0bd46b8665b3a2d9b3cb310959de52a09bc9d20700") + let spent2: Transaction = deserialize(Vec::from_hex("0200000000010166c3d39490dc827a2594c7b17b7d37445e1f4b372179649cd2ce4475e3641bbb0100000017160014e69aa750e9bff1aca1e32e57328b641b611fc817fdffffff01e87c5d010000000017a914f3890da1b99e44cd3d52f7bcea6a1351658ea7be87024830450221009eb97597953dc288de30060ba02d4e91b2bde1af2ecf679c7f5ab5989549aa8002202a98f8c3bd1a5a31c0d72950dd6e2e3870c6c5819a6c3db740e91ebbbc5ef4800121023f3d3b8e74b807e32217dea2c75c8d0bd46b8665b3a2d9b3cb310959de52a09bc9d20700") .unwrap().as_slice()).unwrap(); - let spent3: Transaction = deserialize(hex_decode("01000000027a1120a30cef95422638e8dab9dedf720ec614b1b21e451a4957a5969afb869d000000006a47304402200ecc318a829a6cad4aa9db152adbf09b0cd2de36f47b53f5dade3bc7ef086ca702205722cda7404edd6012eedd79b2d6f24c0a0c657df1a442d0a2166614fb164a4701210372f4b97b34e9c408741cd1fc97bcc7ffdda6941213ccfde1cb4075c0f17aab06ffffffffc23b43e5a18e5a66087c0d5e64d58e8e21fcf83ce3f5e4f7ecb902b0e80a7fb6010000006b483045022100f10076a0ea4b4cf8816ed27a1065883efca230933bf2ff81d5db6258691ff75202206b001ef87624e76244377f57f0c84bc5127d0dd3f6e0ef28b276f176badb223a01210309a3a61776afd39de4ed29b622cd399d99ecd942909c36a8696cfd22fc5b5a1affffffff0200127a000000000017a914f895e1dd9b29cb228e9b06a15204e3b57feaf7cc8769311d09000000001976a9144d00da12aaa51849d2583ae64525d4a06cd70fde88ac00000000") + let spent3: Transaction = deserialize(Vec::from_hex("01000000027a1120a30cef95422638e8dab9dedf720ec614b1b21e451a4957a5969afb869d000000006a47304402200ecc318a829a6cad4aa9db152adbf09b0cd2de36f47b53f5dade3bc7ef086ca702205722cda7404edd6012eedd79b2d6f24c0a0c657df1a442d0a2166614fb164a4701210372f4b97b34e9c408741cd1fc97bcc7ffdda6941213ccfde1cb4075c0f17aab06ffffffffc23b43e5a18e5a66087c0d5e64d58e8e21fcf83ce3f5e4f7ecb902b0e80a7fb6010000006b483045022100f10076a0ea4b4cf8816ed27a1065883efca230933bf2ff81d5db6258691ff75202206b001ef87624e76244377f57f0c84bc5127d0dd3f6e0ef28b276f176badb223a01210309a3a61776afd39de4ed29b622cd399d99ecd942909c36a8696cfd22fc5b5a1affffffff0200127a000000000017a914f895e1dd9b29cb228e9b06a15204e3b57feaf7cc8769311d09000000001976a9144d00da12aaa51849d2583ae64525d4a06cd70fde88ac00000000") .unwrap().as_slice()).unwrap(); let mut spent = HashMap::new(); diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 362a2290..66cdcaf2 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -224,10 +224,10 @@ macro_rules! display_from_debug { } #[cfg(test)] -macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from(::hex::decode($s).unwrap()))); +macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from( as ::hashes::hex::FromHex>::from_hex($s).unwrap()))); #[cfg(test)] -macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(&::hex::decode($s).unwrap()).unwrap())); +macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(& as ::hashes::hex::FromHex>::from_hex($s).unwrap()).unwrap())); macro_rules! serde_struct_impl { ($name:ident, $($fe:ident),*) => ( diff --git a/src/lib.rs b/src/lib.rs index f122b931..edf3425d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,6 @@ pub extern crate secp256k1; pub extern crate bech32; -#[cfg(any(test, feature = "serde"))] extern crate hex; #[cfg(feature = "serde")] extern crate serde; #[cfg(all(test, feature = "serde"))] #[macro_use] extern crate serde_derive; // for 1.22.0 compat #[cfg(all(test, feature = "serde"))] extern crate serde_json; diff --git a/src/network/message.rs b/src/network/message.rs index 82c74060..5710023c 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -336,7 +336,7 @@ mod test { use super::{RawNetworkMessage, NetworkMessage, CommandString}; use network::constants::ServiceFlags; use consensus::encode::{Encodable, deserialize, deserialize_partial, serialize}; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use hashes::sha256d::Hash; use hashes::Hash as HashTrait; use network::address::Address; @@ -353,10 +353,10 @@ mod test { #[test] fn full_round_ser_der_raw_network_message_test() { // TODO: Impl Rand traits here to easily generate random values. - let version_msg: VersionMessage = deserialize(&hex_decode("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap()).unwrap(); - let tx: Transaction = deserialize(&hex_decode("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap(); - let block: Block = deserialize(&hex_decode("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e5503bd5750d4061a4ed90a700f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000").unwrap()).unwrap(); - let header: BlockHeader = deserialize(&hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap(); + let version_msg: VersionMessage = deserialize(&Vec::from_hex("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap()).unwrap(); + let tx: Transaction = deserialize(&Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap(); + let block: Block = deserialize(&Vec::from_hex("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e5503bd5750d4061a4ed90a700f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000").unwrap()).unwrap(); + let header: BlockHeader = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap(); let msgs = vec![ NetworkMessage::Version(version_msg), diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index a758c3c4..3326fb52 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -136,15 +136,15 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); mod tests { use super::{GetHeadersMessage, GetBlocksMessage}; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use consensus::encode::{deserialize, serialize}; use std::default::Default; #[test] fn getblocks_message_test() { - let from_sat = hex_decode("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = hex_decode("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); @@ -159,8 +159,8 @@ mod tests { #[test] fn getheaders_message_test() { - let from_sat = hex_decode("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = hex_decode("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); diff --git a/src/network/message_network.rs b/src/network/message_network.rs index de158e54..c3d90940 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -147,7 +147,7 @@ impl_consensus_encoding!(Reject, message, ccode, reason, hash); mod tests { use super::VersionMessage; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use network::constants::ServiceFlags; use consensus::encode::{deserialize, serialize}; @@ -155,7 +155,7 @@ mod tests { #[test] fn version_message_test() { // This message is from my satoshi node, morning of May 27 2014 - let from_sat = hex_decode("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap(); + let from_sat = Vec::from_hex("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); diff --git a/src/network/stream_reader.rs b/src/network/stream_reader.rs index 78923a76..501bf607 100644 --- a/src/network/stream_reader.rs +++ b/src/network/stream_reader.rs @@ -315,13 +315,13 @@ mod test { fn read_block_from_file_test() { use std::io; use consensus::serialize; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use Block; - let normal_data = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap(); - let cutoff_data = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap(); - let prevhash = hex_decode("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); - let merkle = hex_decode("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); + 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 stream = io::BufReader::new(&normal_data[..]); let mut reader = StreamReader::new(stream, None); diff --git a/src/util/address.rs b/src/util/address.rs index 7ad2d32b..7715736f 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -506,8 +506,7 @@ mod tests { use std::str::FromStr; use std::string::ToString; - use hashes::Hash; - use hex::{decode as hex_decode, encode as hex_encode}; + use hashes::hex::{FromHex, ToHex}; use blockdata::script::Script; use network::constants::Network::{Bitcoin, Testnet}; @@ -515,11 +514,11 @@ mod tests { use super::*; - macro_rules! hex (($hex:expr) => (hex_decode($hex).unwrap())); + macro_rules! hex (($hex:expr) => (Vec::from_hex($hex).unwrap())); macro_rules! hex_key (($hex:expr) => (PublicKey::from_slice(&hex!($hex)).unwrap())); macro_rules! hex_script (($hex:expr) => (Script::from(hex!($hex)))); - macro_rules! hex_pubkeyhash (($hex:expr) => (PubkeyHash::from_slice(&hex!($hex)).unwrap())); - macro_rules! hex_scripthash (($hex:expr) => (ScriptHash::from_slice(&hex!($hex)).unwrap())); + macro_rules! hex_pubkeyhash (($hex:expr) => (PubkeyHash::from_hex(&$hex).unwrap())); + macro_rules! hex_scripthash (($hex:expr) => (ScriptHash::from_hex($hex).unwrap())); fn roundtrips(addr: &Address) { assert_eq!( @@ -664,7 +663,7 @@ mod tests { ]; for vector in &valid_vectors { let addr: Address = vector.0.parse().unwrap(); - assert_eq!(&hex_encode(addr.script_pubkey().as_bytes()), vector.1); + assert_eq!(&addr.script_pubkey().as_bytes().to_hex(), vector.1); roundtrips(&addr); } diff --git a/src/util/base58.rs b/src/util/base58.rs index 2a268eac..c4746cdd 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -249,10 +249,11 @@ pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt:: format_iter(fmt, iter) } + #[cfg(test)] mod tests { use super::*; - use hex::decode as hex_decode; + use hashes::hex::FromHex; #[test] fn test_base58_encode() { @@ -275,7 +276,7 @@ mod tests { assert_eq!(&res, exp); // Addresses - let addr = hex_decode("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap(); + let addr = Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap(); assert_eq!(&check_encode_slice(&addr[..]), "1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH"); } @@ -293,7 +294,7 @@ mod tests { // Addresses assert_eq!(from_check("1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH").ok(), - Some(hex_decode("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap())) + Some(Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap())) } #[test] diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 742a53f2..bae4ebd1 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -109,12 +109,11 @@ mod tests { use util::address::Address; use util::key::PublicKey; use hashes::hex::FromHex; - use hex; use super::*; fn p2pkh_hex(pk: &str) -> Script { - let pk = hex::decode(pk).unwrap(); + let pk = Vec::from_hex(pk).unwrap(); let pk = PublicKey::from_slice(pk.as_slice()).unwrap(); let witness_script = Address::p2pkh(&pk, Network::Bitcoin).script_pubkey(); witness_script @@ -123,7 +122,7 @@ mod tests { #[test] fn bip143_p2wpkh() { let tx = deserialize::( - &Vec::::from_hex( + &Vec::from_hex( "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f000000\ 0000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a01000000\ 00ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093\ @@ -161,7 +160,7 @@ mod tests { #[test] fn bip143_p2wpkh_nested_in_p2sh() { let tx = deserialize::( - &Vec::::from_hex( + &Vec::from_hex( "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000\ 0000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac00\ 08af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000", @@ -170,7 +169,6 @@ mod tests { let witness_script = p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873"); let value = 1_000_000_000; - let comp = SighashComponents::new(&tx); assert_eq!( comp, @@ -198,7 +196,7 @@ mod tests { #[test] fn bip143_p2wsh_nested_in_p2sh() { let tx = deserialize::( - &Vec::::from_hex( + &Vec::from_hex( "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\ ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\ 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000").unwrap()[..], diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 6228dd24..470e59e1 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -688,7 +688,7 @@ mod tests { use std::string::ToString; use secp256k1::{self, Secp256k1}; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use network::constants::Network::{self, Bitcoin}; @@ -856,7 +856,7 @@ mod tests { #[test] fn test_vector_1() { let secp = Secp256k1::new(); - let seed = hex_decode("000102030405060708090a0b0c0d0e0f").unwrap(); + let seed = Vec::from_hex("000102030405060708090a0b0c0d0e0f").unwrap(); // m test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), @@ -892,7 +892,7 @@ mod tests { #[test] fn test_vector_2() { let secp = Secp256k1::new(); - let seed = hex_decode("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542").unwrap(); + let seed = Vec::from_hex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542").unwrap(); // m test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), @@ -928,7 +928,7 @@ mod tests { #[test] fn test_vector_3() { let secp = Secp256k1::new(); - let seed = hex_decode("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be").unwrap(); + let seed = Vec::from_hex("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be").unwrap(); // m test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 62691915..539944dd 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -284,7 +284,7 @@ pub fn untemplate(script: &script::Script) -> Result<(Template, Vec), #[cfg(test)] mod tests { use secp256k1::Secp256k1; - use hex::decode as hex_decode; + use hashes::hex::FromHex; use secp256k1::rand::thread_rng; use std::str::FromStr; @@ -294,7 +294,7 @@ mod tests { use super::*; use PublicKey; - macro_rules! hex (($hex:expr) => (hex_decode($hex).unwrap())); + macro_rules! hex (($hex:expr) => (Vec::from_hex($hex).unwrap())); macro_rules! hex_key (($hex:expr) => (PublicKey::from_slice(&hex!($hex)).unwrap())); macro_rules! alpha_template(() => (Template::from(&hex!("55fefefefefefefe57AE")[..]))); macro_rules! alpha_keys(() => ( diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index b1365751..2c097d9b 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -504,7 +504,7 @@ mod tests { use consensus::encode::{deserialize, serialize}; use util::hash::bitcoin_merkle_root; use util::merkleblock::{MerkleBlock, PartialMerkleTree}; - use {hex, Block}; + use Block; #[test] fn pmt_tests() { @@ -615,7 +615,7 @@ mod tests { ebe1ae264bc0e2289189ff0316cdc10511da71da757e553cada9f3b5b1434f3923673adb57d83caac392c38\ af156d6fc30b55fad4112df2b95531e68114e9ad10011e72f7b7cfdb025700"; - let mb: MerkleBlock = deserialize(&hex::decode(mb_hex).unwrap()).unwrap(); + let mb: MerkleBlock = deserialize(&Vec::from_hex(mb_hex).unwrap()).unwrap(); assert_eq!(get_block_13b8a().block_hash(), mb.header.block_hash()); assert_eq!( mb.header.merkle_root, @@ -781,6 +781,6 @@ mod tests { 058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb60\ 42034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37\ c32f5c388ac00000000"; - deserialize(&hex::decode(block_hex).unwrap()).unwrap() + deserialize(&Vec::from_hex(block_hex).unwrap()).unwrap() } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 020f1ff6..7844b7ca 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -14,7 +14,7 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { ::consensus::deserialize(&::hex::decode($s).unwrap()) }; + ($s:expr) => { ::consensus::deserialize(& as ::hashes::hex::FromHex>::from_hex($s).unwrap()) }; } macro_rules! merge { diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 48a8e240..d281f1ce 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -167,8 +167,6 @@ mod tests { use std::collections::BTreeMap; - use hex::decode as hex_decode; - use secp256k1::Secp256k1; use blockdata::script::Script; @@ -206,7 +204,7 @@ mod tests { #[test] fn serialize_then_deserialize_output() { let secp = &Secp256k1::new(); - let seed = hex_decode("000102030405060708090a0b0c0d0e0f").unwrap(); + let seed = Vec::from_hex("000102030405060708090a0b0c0d0e0f").unwrap(); let mut hd_keypaths: BTreeMap = Default::default(); @@ -312,8 +310,6 @@ mod tests { mod bip_vectors { use std::collections::BTreeMap; - use hex::decode as hex_decode; - use hashes::hex::FromHex; use hash_types::Txid; @@ -399,8 +395,8 @@ mod tests { script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), sequence: 4294967295, witness: vec![ - hex_decode("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(), - hex_decode("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(), + Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(), + Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(), ], }, TxIn { @@ -413,8 +409,8 @@ mod tests { script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), sequence: 4294967295, witness: vec![ - hex_decode("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(), - hex_decode("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(), + Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(), + Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(), ], }], output: vec![ @@ -556,9 +552,9 @@ mod tests { let mut unknown: BTreeMap> = BTreeMap::new(); let key: raw::Key = raw::Key { type_value: 0x0fu8, - key: hex_decode("010203040506070809").unwrap(), + key: Vec::from_hex("010203040506070809").unwrap(), }; - let value: Vec = hex_decode("0102030405060708090a0b0c0d0e0f").unwrap(); + let value: Vec = Vec::from_hex("0102030405060708090a0b0c0d0e0f").unwrap(); unknown.insert(key, value); From f3e762b555372625c3052276a778dd6148f57fb9 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 21 Jan 2020 13:11:48 +0100 Subject: [PATCH 0008/1740] Improving `construct_uint` macro --- src/util/uint.rs | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/util/uint.rs b/src/util/uint.rs index 2e26f979..9456df0a 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -18,11 +18,6 @@ //! The functions here are designed to be fast. //! -use std::fmt; - -use consensus::encode; -use util::BitArray; - macro_rules! construct_uint { ($name:ident, $n_words:expr) => ( /// Little-endian large integer type @@ -116,7 +111,7 @@ macro_rules! construct_uint { #[inline] fn sub(self, other: $name) -> $name { - self + !other + BitArray::one() + self + !other + $crate::util::BitArray::one() } } @@ -124,6 +119,7 @@ macro_rules! construct_uint { type Output = $name; fn mul(self, other: $name) -> $name { + use $crate::util::BitArray; let mut me = $name::zero(); // TODO: be more efficient about this for i in 0..(2 * $n_words) { @@ -170,7 +166,7 @@ macro_rules! construct_uint { } } - impl BitArray for $name { + impl $crate::util::BitArray for $name { #[inline] fn bit(&self, index: usize) -> bool { let &$name(ref arr) = self; @@ -214,7 +210,7 @@ macro_rules! construct_uint { impl ::std::default::Default for $name { fn default() -> $name { - BitArray::zero() + $crate::util::BitArray::zero() } } @@ -319,8 +315,8 @@ macro_rules! construct_uint { } } - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + impl ::std::fmt::Debug for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { let &$name(ref data) = self; write!(f, "0x")?; for ch in data.iter().rev() { @@ -330,18 +326,18 @@ macro_rules! construct_uint { } } - impl fmt::Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ::fmt(self, f) + impl ::std::fmt::Display for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + <::std::fmt::Debug>::fmt(self, f) } } - impl ::consensus::Encodable for $name { + impl $crate::consensus::Encodable for $name { #[inline] fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let &$name(ref data) = self; let mut len = 0; for word in data.iter() { @@ -351,11 +347,11 @@ macro_rules! construct_uint { } } - impl ::consensus::Decodable for $name { + impl $crate::consensus::Decodable for $name { fn consensus_decode( mut d: D, - ) -> Result<$name, encode::Error> { - use consensus::Decodable; + ) -> Result<$name, $crate::consensus::encode::Error> { + use $crate::consensus::Decodable; let mut ret: [u64; $n_words] = [0; $n_words]; for i in 0..$n_words { ret[i] = Decodable::consensus_decode(&mut d)?; From 908aff50bcf48c3ae8d11ffcb7057d030691b1c2 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 13 Jan 2020 11:16:48 -0500 Subject: [PATCH 0009/1740] Add bip143 sighash support for other flags --- src/blockdata/transaction.rs | 2 +- src/util/bip143.rs | 140 ++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 7beac7f5..f11c4f8c 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -586,7 +586,7 @@ pub enum SigHashType { impl SigHashType { /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean - fn split_anyonecanpay_flag(&self) -> (SigHashType, bool) { + pub(crate) fn split_anyonecanpay_flag(&self) -> (SigHashType, bool) { match *self { SigHashType::All => (SigHashType::All, false), SigHashType::None => (SigHashType::None, false), diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 742a53f2..23a3fd97 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -19,10 +19,10 @@ //! signatures, which are placed in the scriptSig. //! -use hashes::Hash; +use hashes::{Hash, sha256d}; use hash_types::SigHash; use blockdata::script::Script; -use blockdata::transaction::{Transaction, TxIn}; +use blockdata::transaction::{Transaction, TxIn, SigHashType}; use consensus::encode::Encodable; /// Parts of a sighash which are common across inputs or signatures, and which are @@ -99,6 +99,120 @@ impl SighashComponents { } } +/// A replacement for SigHashComponents which supports all sighash modes +pub struct SigHashCache<'a> { + /// Access to transaction required for various introspection + tx: &'a Transaction, + /// Hash of all the previous outputs, computed as required + hash_prevouts: Option, + /// Hash of all the input sequence nos, computed as required + hash_sequence: Option, + /// Hash of all the outputs in this transaction, computed as required + hash_outputs: Option, +} + +impl<'a> SigHashCache<'a> { + /// Compute the sighash components from an unsigned transaction and auxiliary + /// in a lazy manner when required. + /// For the generated sighashes to be valid, no fields in the transaction may change except for + /// script_sig and witnesses. + pub fn new(tx: &Transaction) -> SigHashCache { + SigHashCache { + tx: tx, + hash_prevouts: None, + hash_sequence: None, + hash_outputs: None, + } + } + + /// Calculate hash for prevouts + pub fn hash_prevouts(&mut self) -> sha256d::Hash { + let hash_prevout = &mut self.hash_prevouts; + let input = &self.tx.input; + *hash_prevout.get_or_insert_with(|| { + let mut enc = sha256d::Hash::engine(); + for txin in input { + txin.previous_output.consensus_encode(&mut enc).unwrap(); + } + sha256d::Hash::from_engine(enc) + }) + } + + /// Calculate hash for input sequence values + pub fn hash_sequence(&mut self) -> sha256d::Hash { + let hash_sequence = &mut self.hash_sequence; + let input = &self.tx.input; + *hash_sequence.get_or_insert_with(|| { + let mut enc = sha256d::Hash::engine(); + for txin in input { + txin.sequence.consensus_encode(&mut enc).unwrap(); + } + sha256d::Hash::from_engine(enc) + }) + } + + /// Calculate hash for outputs + pub fn hash_outputs(&mut self) -> sha256d::Hash { + let hash_output = &mut self.hash_outputs; + let output = &self.tx.output; + *hash_output.get_or_insert_with(|| { + let mut enc = sha256d::Hash::engine(); + for txout in output { + txout.consensus_encode(&mut enc).unwrap(); + } + sha256d::Hash::from_engine(enc) + }) + } + + /// Compute the BIP143 sighash for any flag type. See SighashComponents::sighash_all simpler + /// API for the most common case + pub fn signature_hash(&mut self, input_index: usize, script_code: &Script, value: u64, sighash_type: SigHashType) -> SigHash { + + let zero_hash = sha256d::Hash::default(); + + let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag(); + + let mut enc = SigHash::engine(); + self.tx.version.consensus_encode(&mut enc).unwrap(); + + if !anyone_can_pay { + self.hash_prevouts().consensus_encode(&mut enc).unwrap(); + } else { + zero_hash.consensus_encode(&mut enc).unwrap(); + } + + if !anyone_can_pay && sighash != SigHashType::Single && sighash != SigHashType::None { + self.hash_sequence().consensus_encode(&mut enc).unwrap(); + } else { + zero_hash.consensus_encode(&mut enc).unwrap(); + } + + let txin = &self.tx.input[input_index]; + + txin + .previous_output + .consensus_encode(&mut enc) + .unwrap(); + script_code.consensus_encode(&mut enc).unwrap(); + value.consensus_encode(&mut enc).unwrap(); + txin.sequence.consensus_encode(&mut enc).unwrap(); + + if sighash != SigHashType::Single && sighash != SigHashType::None { + self.hash_outputs().consensus_encode(&mut enc).unwrap(); + } else if sighash == SigHashType::Single && input_index < self.tx.output.len() { + let mut single_enc = SigHash::engine(); + self.tx.output[input_index].consensus_encode(&mut single_enc).unwrap(); + SigHash::from_engine(single_enc).consensus_encode(&mut enc).unwrap(); + } else { + zero_hash.consensus_encode(&mut enc).unwrap(); + } + + self.tx.lock_time.consensus_encode(&mut enc).unwrap(); + sighash_type.as_u32().consensus_encode(&mut enc).unwrap(); + SigHash::from_engine(enc) + } +} + #[cfg(test)] mod tests { use hash_types::SigHash; @@ -120,6 +234,17 @@ mod tests { witness_script } + 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(); + let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap(); + let mut cache = SigHashCache::new(&tx); + let sighash_type = SigHashType::from_u32(hash_type); + let actual_result = cache.signature_hash(input_index, &script, value, sighash_type); + assert_eq!(actual_result, expected_result); + } + #[test] fn bip143_p2wpkh() { let tx = deserialize::( @@ -237,4 +362,15 @@ mod tests { hex_hash!(SigHash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c") ); } + #[test] + fn bip143_sighash_flags() { + // All examples generated via Bitcoin Core RPC using signrawtransactionwithwallet + // with additional debug printing + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x01, "0a1bc2758dbb5b3a56646f8cafbf63f410cc62b77a482f8b87552683300a7711"); + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x02, "3e275ac8b084f79f756dcd535bffb615cc94a685eefa244d9031eaf22e4cec12"); + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x03, "191a08165ffacc3ea55753b225f323c35fd00d9cc0268081a4a501921fc6ec14"); + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x81, "4b6b612530f94470bbbdef18f57f2990d56b239f41b8728b9a49dc8121de4559"); + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x82, "a7e916d3acd4bb97a21e6793828279aeab02162adf8099ea4f309af81f3d5adb"); + run_test_sighash_bip143("0200000001cf309ee0839b8aaa3fbc84f8bd32e9c6357e99b49bf6a3af90308c68e762f1d70100000000feffffff0288528c61000000001600146e8d9e07c543a309dcdeba8b50a14a991a658c5be0aebb0000000000160014698d8419804a5d5994704d47947889ff7620c004db000000", "76a91462744660c6b5133ddeaacbc57d2dc2d7b14d0b0688ac", 0, 1648888940, 0x83, "d9276e2a48648ddb53a4aaa58314fc2b8067c13013e1913ffb67e0988ce82c78"); + } } From d1c5c7b08d68c39218ffb9095896ec152f8097c1 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Wed, 15 Jan 2020 11:46:30 -0500 Subject: [PATCH 0010/1740] Deprecate SigHashComponents --- src/util/bip143.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 23a3fd97..51b9adfc 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -28,6 +28,7 @@ use consensus::encode::Encodable; /// Parts of a sighash which are common across inputs or signatures, and which are /// sufficient (in conjunction with a private key) to sign the transaction #[derive(Clone, PartialEq, Eq, Debug)] +#[deprecated(since="0.24.0", note="please use `SigHashCache` instead")] pub struct SighashComponents { tx_version: u32, tx_locktime: u32, @@ -39,6 +40,7 @@ pub struct SighashComponents { pub hash_outputs: SigHash, } +#[allow(deprecated)] impl SighashComponents { /// Compute the sighash components from an unsigned transaction and auxiliary /// information about its inputs. @@ -214,6 +216,7 @@ impl<'a> SigHashCache<'a> { } #[cfg(test)] +#[allow(deprecated)] mod tests { use hash_types::SigHash; use blockdata::script::Script; From 9c0f4b1a6037bb7f29cf2b9f5d0afb9c458849d4 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Wed, 22 Jan 2020 11:28:11 +0100 Subject: [PATCH 0011/1740] Fixing namespaces in `impl_hashencode` --- src/hash_types.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/hash_types.rs b/src/hash_types.rs index 514c5309..3eefe39a 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -16,23 +16,22 @@ //! to avoid mixing data of the same hash format (like SHA256d) but of different meaning //! (transaction id, block hash etc). -use std::io; - use consensus::encode::{Encodable, Decodable, Error}; -use hashes::{sha256, sha256d, hash160, Hash}; -use hashes::hex::{ToHex, FromHex}; +use hashes::{Hash, sha256, sha256d, ripemd160, hash160}; +use hashes::hex::{FromHex, ToHex}; macro_rules! impl_hashencode { ($hashtype:ident) => { - impl Encodable for $hashtype { - fn consensus_encode(&self, s: S) -> Result { + impl $crate::consensus::Encodable for $hashtype { + fn consensus_encode(&self, s: S) -> Result { self.0.consensus_encode(s) } } - impl Decodable for $hashtype { - fn consensus_decode(d: D) -> Result { - Ok(Self::from_inner(<<$hashtype as Hash>::Inner>::consensus_decode(d)?)) + impl $crate::consensus::Decodable for $hashtype { + fn consensus_decode(d: D) -> Result { + use $crate::hashes::Hash; + Ok(Self::from_inner(<<$hashtype as $crate::hashes::Hash>::Inner>::consensus_decode(d)?)) } } } From 410e45f378f5e90d58d072c86f968844747c295d Mon Sep 17 00:00:00 2001 From: Will Binns Date: Thu, 23 Jan 2020 10:45:18 +0100 Subject: [PATCH 0012/1740] readme: Add links to CHANGELOG.md and LICENSE --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d0b4d8eb..b7791921 100644 --- a/README.md +++ b/README.md @@ -101,10 +101,10 @@ support only a single blockchain. # Release Notes -See CHANGELOG.md +See [CHANGELOG.md](CHANGELOG.md). # Licensing -The code in this project is licensed under the Creative Commons CC0 1.0 -Universal license. +The code in this project is licensed under the [Creative Commons CC0 1.0 +Universal license](LICENSE). From 399950bf71dcec3bfb9a8ecfc9cfdea572576bab Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Thu, 23 Jan 2020 11:45:59 +0200 Subject: [PATCH 0013/1740] Restrict serde-json dev dependency to less than 1.0.45 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a05275d9..8aa68a9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,6 @@ hex = { version = "=0.3.2", optional = true } [dev-dependencies] hex = "=0.3.2" serde_derive = "<1.0.99" -serde_json = "1" +serde_json = "<1.0.45" serde_test = "1" secp256k1 = { version = "0.17.1", features = ["rand-std"] } From eb7369b1dbe8f6a9a94fdaec728effa1fb00c0b4 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 20 Jan 2020 20:06:07 +0200 Subject: [PATCH 0014/1740] Simlify consensus_encode vectors --- src/consensus/encode.rs | 48 +++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 402a4b51..09f942f7 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -150,7 +150,8 @@ impl From for Error { /// Encode an object into a vector pub fn serialize(data: &T) -> Vec { let mut encoder = Cursor::new(vec![]); - data.consensus_encode(&mut encoder).unwrap(); + let len = data.consensus_encode(&mut encoder).unwrap(); + assert_eq!(len, encoder.get_ref().len()); encoder.into_inner() } @@ -278,7 +279,7 @@ impl WriteExt for W { } #[inline] fn emit_bool(&mut self, v: bool) -> Result<(), Error> { - self.write_all(&[if v {1} else {0}]).map_err(Error::Io) + self.write_all(&[v as u8]).map_err(Error::Io) } #[inline] fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error> { @@ -350,7 +351,6 @@ macro_rules! impl_int_encodable{ ReadExt::$meth_dec(&mut d).map($ty::from_le) } } - impl Encodable for $ty { #[inline] fn consensus_encode( @@ -454,7 +454,7 @@ impl Decodable for VarInt { impl Encodable for bool { #[inline] fn consensus_encode(&self, mut s: S) -> Result { - s.emit_u8(if *self {1} else {0})?; + s.emit_bool(*self)?; Ok(1) } } @@ -462,7 +462,7 @@ impl Encodable for bool { impl Decodable for bool { #[inline] fn consensus_decode(mut d: D) -> Result { - ReadExt::read_u8(&mut d).map(|n| n != 0) + ReadExt::read_bool(&mut d) } } @@ -575,7 +575,6 @@ macro_rules! impl_vec { Ok(len) } } - impl Decodable for Vec<$type> { #[inline] fn consensus_decode(mut d: D) -> Result { @@ -606,12 +605,17 @@ impl_vec!(Vec); impl_vec!((u32, Address)); impl_vec!(u64); +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, mut s: S) -> Result { - let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?; - s.emit_slice(&self)?; - Ok(vi_len + self.len()) + fn consensus_encode(&self, s: S) -> Result { + consensus_encode_with_size(self, s) } } @@ -622,8 +626,7 @@ impl Decodable for Vec { if len > MAX_VEC_SIZE { return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) } - let mut ret = Vec::with_capacity(len); - ret.resize(len, 0); + let mut ret = vec![0u8; len]; d.read_slice(&mut ret)?; Ok(ret) } @@ -631,25 +634,15 @@ impl Decodable for Vec { impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?; - s.emit_slice(&self)?; - Ok(vi_len + self.len()) + fn consensus_encode(&self, s: S) -> Result { + consensus_encode_with_size(self, s) } } impl Decodable for Box<[u8]> { #[inline] - fn consensus_decode(mut d: D) -> Result { - let len = VarInt::consensus_decode(&mut d)?.0; - let len = len as usize; - if len > MAX_VEC_SIZE { - return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) - } - let mut ret = Vec::with_capacity(len); - ret.resize(len, 0); - d.read_slice(&mut ret)?; - Ok(ret.into_boxed_slice()) + fn consensus_decode(d: D) -> Result { + >::consensus_decode(d).map(From::from) } } @@ -682,8 +675,7 @@ impl Decodable for CheckedData { }); } let checksum = <[u8; 4]>::consensus_decode(&mut d)?; - let mut ret = Vec::with_capacity(len as usize); - ret.resize(len as usize, 0); + let mut ret = vec![0u8; len as usize]; d.read_slice(&mut ret)?; let expected_checksum = sha2_checksum(&ret); if expected_checksum != checksum { From 5d276caf956c4050c72403ebde575fc9ea6ef699 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 20 Jan 2020 20:07:45 +0200 Subject: [PATCH 0015/1740] Mutation testing: encode: Added tests to "fix" mutation misses --- src/consensus/encode.rs | 150 ++++++++++++++++++++++++++++++++-------- 1 file changed, 123 insertions(+), 27 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 09f942f7..9bd8fb45 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -736,9 +736,15 @@ impl Decodable for sha256d::Hash { // Tests #[cfg(test)] mod tests { - use super::{CheckedData, VarInt}; - - use super::{deserialize, serialize, Error}; + use std::{io, mem, fmt}; + use std::mem::discriminant; + 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 network::message_blockdata::Inventory; + use network::Address; #[test] fn serialize_int_test() { @@ -797,34 +803,59 @@ mod tests { 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!(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)); + + // Test that length calc is working correctly + test_varint_len(VarInt(0), 1); + test_varint_len(VarInt(0xFC), 1); + test_varint_len(VarInt(0xFD), 3); + 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(u64::max_value()), 9); + } + + fn test_varint_len(varint: VarInt, expected: usize) { + let mut encoder = io::Cursor::new(vec![]); + assert_eq!(varint.consensus_encode(&mut encoder).unwrap(), expected); + assert_eq!(varint.len(), expected); + } + + 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) } #[test] fn deserialize_nonminimal_vec() { - match deserialize::>(&[0xfd, 0x00, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } - match deserialize::>(&[0xfd, 0xfc, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } - match deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } - match deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } - match deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } - match deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]) { - Err(Error::NonMinimalVarInt) => {}, - x => panic!(x) - } + // 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)); + let mut vec_256 = vec![0; 259]; vec_256[0] = 0xfd; @@ -904,6 +935,32 @@ mod tests { 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()); + + 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(); + assert_eq!(discriminant(&err), discriminant(&rand_io_err)); + + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::>(); + test_len_is_max_vec::<(u32, Address)>(); + test_len_is_max_vec::(); + } + + 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(); + assert_eq!(discriminant(&err), discriminant(&rand_io_err)); } #[test] @@ -920,5 +977,44 @@ mod tests { 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]))); } + + #[test] + fn serialization_round_trips() { + macro_rules! round_trip { + ($($val_type:ty),*) => { + $( + let r: $val_type = thread_rng().gen(); + assert_eq!(deserialize::<$val_type>(&serialize(&r)).unwrap(), r); + )* + }; + } + macro_rules! round_trip_bytes { + ($(($val_type:ty, $data:expr)),*) => { + $( + thread_rng().fill(&mut $data[..]); + assert_eq!(deserialize::<$val_type>(&serialize(&$data)).unwrap()[..], $data[..]); + )* + }; + } + + 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, + (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]}; + + data.clear(); + data64.clear(); + let len = thread_rng().gen_range(1, 256); + data.resize(len, 0u8); + 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)}; + + + } + } } From 1d01262d5c6b069ea087dc1e5323d3999b12a5e2 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 20 Jan 2020 20:08:07 +0200 Subject: [PATCH 0016/1740] Mutation testing: base58: Added tests to "fix" mutation misses --- src/util/base58.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/util/base58.rs b/src/util/base58.rs index c4746cdd..394b38fa 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -294,7 +294,9 @@ mod tests { // Addresses assert_eq!(from_check("1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH").ok(), - Some(Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap())) + Some(Vec::from_hex("00f8917303bfa8ef24f292e8fa1419b20460ba064d").unwrap())); + // Non Base58 char. + assert_eq!(from("¢").unwrap_err(), Error::BadByte(194)); } #[test] @@ -303,6 +305,12 @@ mod tests { let v: Vec = from_check(s).unwrap(); assert_eq!(check_encode_slice(&v[..]), s); assert_eq!(from_check(&check_encode_slice(&v[..])).ok(), Some(v)); + + // 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))); + } } From abc70781e75a3d1bc667f115efbb769b008d3bef Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Tue, 21 Jan 2020 13:36:53 +0200 Subject: [PATCH 0017/1740] Fix a logic problem in base58 (isn't a real bug) --- src/util/base58.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/base58.rs b/src/util/base58.rs index 394b38fa..68a0a2b7 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -131,7 +131,7 @@ pub fn from(data: &str) -> Result, Error> { // Build in base 256 for d58 in data.bytes() { // Compute "X = X * 58 + next_digit" in base 256 - if d58 as usize > BASE58_DIGITS.len() { + if d58 as usize >= BASE58_DIGITS.len() { return Err(Error::BadByte(d58)); } let mut carry = match BASE58_DIGITS[d58 as usize] { From ab6e20c87ea1244b278af0deba0f8835fbac8ef6 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Tue, 21 Jan 2020 19:42:44 +0200 Subject: [PATCH 0018/1740] Fix an overflow bug in SignedAmount to_string/fmt --- src/util/amount.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/util/amount.rs b/src/util/amount.rs index 7d3c0f76..1a9d2572 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -668,7 +668,11 @@ impl SignedAmount { /// /// Does not include the denomination. pub fn fmt_value_in(&self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result { - fmt_satoshi_in(self.as_sat().abs() as u64, self.is_negative(), f, denom) + 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 + }); + fmt_satoshi_in(sats, self.is_negative(), f, denom) } /// Get a string number of this [SignedAmount] in the given denomination. @@ -717,6 +721,13 @@ 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 { + self.0.checked_abs().map(SignedAmount) + } + /// Checked addition. /// Returns [None] if overflow occurred. pub fn checked_add(self, rhs: SignedAmount) -> Option { From 07b30c7fac98376b61dc9d4578ff27d97359cb6d Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Tue, 21 Jan 2020 19:43:10 +0200 Subject: [PATCH 0019/1740] Mutation testing: amount: Added tests to fix mutation misses --- src/util/amount.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/util/amount.rs b/src/util/amount.rs index 1a9d2572..1bbb6ec6 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -1158,6 +1158,7 @@ mod tests { fn parsing() { use super::ParseAmountError as E; let btc = Denomination::Bitcoin; + let sat = Denomination::Satoshi; let p = Amount::from_str_in; let sp = SignedAmount::from_str_in; @@ -1174,11 +1175,26 @@ mod tests { assert_eq!(p("1", btc), Ok(Amount::from_sat(1_000_000_00))); assert_eq!(sp("-.5", btc), Ok(SignedAmount::from_sat(-500_000_00))); assert_eq!(p("1.1", btc), Ok(Amount::from_sat(1_100_000_00))); + assert_eq!(p("100", sat), Ok(Amount::from_sat(100))); + assert_eq!(p("55", sat), Ok(Amount::from_sat(55))); + assert_eq!(p("5500000000000000000", sat), Ok(Amount::from_sat(5_500_000_000_000_000_000))); + // Should this even pass? + assert_eq!(p("5500000000000000000.", sat), Ok(Amount::from_sat(5_500_000_000_000_000_000))); assert_eq!( p("12345678901.12345678", btc), Ok(Amount::from_sat(12_345_678_901__123_456_78)) ); + + // 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!(p("12.000", Denomination::MilliSatoshi), Err(E::TooPrecise)); + // exactly 50 chars. + assert_eq!(p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin), Err(E::TooBig)); + // more than 50 chars. + assert_eq!(p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin), Err(E::InputTooLarge)); } #[test] @@ -1203,6 +1219,27 @@ mod tests { ); } + #[test] + fn test_unsigned_signed_conversion() { + use super::ParseAmountError as E; + let sa = SignedAmount::from_sat; + 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(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(i64::max_value() as u64 + 1).to_signed(), Err(E::TooBig)); + + assert_eq!(sa(-1).to_unsigned(), Err(E::Negative)); + assert_eq!(sa(i64::max_value()).to_unsigned(), Ok(ua(i64::max_value() as u64))); + + 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()))); + } + #[test] fn from_str() { use super::ParseAmountError as E; @@ -1242,9 +1279,38 @@ mod tests { } #[test] - fn to_string_with_denomination_from_str_roundtrip() { + fn to_from_string_in() { use super::Denomination as D; + let ua_str = Amount::from_str_in; + let ua_sat = Amount::from_sat; + let sa_str = SignedAmount::from_str_in; + let sa_sat = SignedAmount::from_sat; + assert_eq!("0.50", Amount::from_sat(50).to_string_in(D::Bit)); + assert_eq!("-0.50", SignedAmount::from_sat(-50).to_string_in(D::Bit)); + assert_eq!("0.00253583", Amount::from_sat(253583).to_string_in(D::Bitcoin)); + assert_eq!("-5", SignedAmount::from_sat(-5).to_string_in(D::Satoshi)); + assert_eq!("0.10000000", Amount::from_sat(100_000_00).to_string_in(D::Bitcoin)); + assert_eq!("-100.00", SignedAmount::from_sat(-10_000).to_string_in(D::Bit)); + + 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!(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)); + // 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)); + + } + + #[test] + fn to_string_with_denomination_from_str_roundtrip() { + use super::Denomination as D; let amt = Amount::from_sat(42); let denom = Amount::to_string_with_denomination; assert_eq!(Amount::from_str(&denom(&amt, D::Bitcoin)), Ok(amt)); @@ -1253,6 +1319,9 @@ mod tests { assert_eq!(Amount::from_str(&denom(&amt, D::Bit)), Ok(amt)); assert_eq!(Amount::from_str(&denom(&amt, D::Satoshi)), Ok(amt)); assert_eq!(Amount::from_str(&denom(&amt, D::MilliSatoshi)), Ok(amt)); + + assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat)); + assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat)); } #[cfg(feature = "serde")] From 826b2e0e2aa89be4172b961cabc945f0b4c5e3b5 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 28 Feb 2020 11:51:44 +0000 Subject: [PATCH 0020/1740] Export the util::amount::Denomination type --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index edf3425d..4cb27089 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,6 +95,7 @@ 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::key::PrivateKey; pub use util::key::PublicKey; From 9d212da0baa69114da870ffc6349d3eb9a88552e Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 17 Feb 2020 15:12:13 +0100 Subject: [PATCH 0021/1740] Added a simple handshake example. --- examples/handshake.rs | 102 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 examples/handshake.rs diff --git a/examples/handshake.rs b/examples/handshake.rs new file mode 100644 index 00000000..be40f7d9 --- /dev/null +++ b/examples/handshake.rs @@ -0,0 +1,102 @@ +use rand::Rng; +use std::io::Write; +use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; +use std::time::{SystemTime, UNIX_EPOCH}; + +use bitcoin::consensus::encode; +use bitcoin::network::address; +use bitcoin::network::constants; +use bitcoin::network::message; +use bitcoin::network::message_network; +use bitcoin::network::stream_reader::StreamReader; + +fn main() { + // This example establishes a connection to a Bitcoin node, sends the intial + // "version" message, waits for the reply, and finally closes the connection. + + let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(130, 149, 80, 221)), 8333); + + let version_message = build_version_message(address.clone()); + + let first_message = message::RawNetworkMessage { + magic: constants::Network::Bitcoin.magic(), + payload: version_message, + }; + + if let Ok(mut stream) = TcpStream::connect(address) { + // Send the message + let _ = stream.write(encode::serialize(&first_message).as_slice()); + println!("Sent version message"); + + // Wait for reply and close stream + + loop { + let reply = StreamReader::new(&mut stream, None).read_next(); + let unwrapped: message::RawNetworkMessage = reply.unwrap(); + match unwrapped.payload { + message::NetworkMessage::Version(_) => { + println!("Received version message: {:?}", unwrapped.payload); + + let second_message = message::RawNetworkMessage { + magic: constants::Network::Bitcoin.magic(), + payload: message::NetworkMessage::Verack, + }; + + let _ = stream.write(encode::serialize(&second_message).as_slice()); + println!("Sent verack message"); + } + message::NetworkMessage::Verack => { + println!("Received verack message: {:?}", unwrapped.payload); + break; + } + _ => { + println!("Received unknown message: {:?}", unwrapped.payload); + break; + } + } + } + let _ = stream.shutdown(Shutdown::Both); + } else { + eprintln!("Failed to open connection"); + } +} + +fn build_version_message(address: SocketAddr) -> message::NetworkMessage { + // Building version message, see https://en.bitcoin.it/wiki/Protocol_documentation#version + let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); + + // "bitfield of features to be enabled for this connection" + let services = constants::ServiceFlags::NONE; + + // "standard UNIX timestamp in seconds" + 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); + + // "The network address of the node emitting this message" + let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE); + + // "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self." + let nonce: u64 = rand::thread_rng().gen(); + + // "User Agent (0x00 if string is 0 bytes long)" + let user_agent = String::from("rust-example"); + + // "The last block received by the emitting node" + let start_height: i32 = 0; + + // Construct the message + message::NetworkMessage::Version(message_network::VersionMessage::new( + services, + timestamp as i64, + addr_recv, + addr_from, + nonce, + user_agent, + start_height, + )) +} From c4f0056856976a1f640b2b0ca49e4155f5acd157 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 17 Feb 2020 16:07:10 +0100 Subject: [PATCH 0022/1740] No clone needed. --- examples/handshake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index be40f7d9..fa67ca25 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -16,7 +16,7 @@ fn main() { let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(130, 149, 80, 221)), 8333); - let version_message = build_version_message(address.clone()); + let version_message = build_version_message(address); let first_message = message::RawNetworkMessage { magic: constants::Network::Bitcoin.magic(), From 2852083ff301842b77cf7aca5ade8ffc21b90827 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 17 Feb 2020 16:17:13 +0100 Subject: [PATCH 0023/1740] Using write_all(). --- examples/handshake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index fa67ca25..a8a1678a 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -25,7 +25,7 @@ fn main() { if let Ok(mut stream) = TcpStream::connect(address) { // Send the message - let _ = stream.write(encode::serialize(&first_message).as_slice()); + let _ = stream.write_all(encode::serialize(&first_message).as_slice()); println!("Sent version message"); // Wait for reply and close stream @@ -42,7 +42,7 @@ fn main() { payload: message::NetworkMessage::Verack, }; - let _ = stream.write(encode::serialize(&second_message).as_slice()); + let _ = stream.write_all(encode::serialize(&second_message).as_slice()); println!("Sent verack message"); } message::NetworkMessage::Verack => { From 62f5f8e3f9098b44e0ba9ec1eccdd007bc67b089 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 19 Feb 2020 08:46:26 +0100 Subject: [PATCH 0024/1740] Removed explicit dependency on rand. --- examples/handshake.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index a8a1678a..2536800d 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -1,4 +1,6 @@ -use rand::Rng; +extern crate bitcoin; + +use bitcoin::secp256k1::rand::Rng; use std::io::Write; use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -81,7 +83,7 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage { let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE); // "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self." - let nonce: u64 = rand::thread_rng().gen(); + let nonce: u64 = secp256k1::rand::thread_rng().gen(); // "User Agent (0x00 if string is 0 bytes long)" let user_agent = String::from("rust-example"); From b5f5abe0b433328fbff118b0d42b195bedef160e Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 19 Feb 2020 08:52:39 +0100 Subject: [PATCH 0025/1740] Removed pre-configured IP, now takes IP as argument. --- examples/handshake.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index 2536800d..1d97717e 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -1,22 +1,28 @@ extern crate bitcoin; -use bitcoin::secp256k1::rand::Rng; -use std::io::Write; use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; use std::time::{SystemTime, UNIX_EPOCH}; +use std::{env, process, io::Write}; +use bitcoin::secp256k1::rand::Rng; use bitcoin::consensus::encode; -use bitcoin::network::address; -use bitcoin::network::constants; -use bitcoin::network::message; -use bitcoin::network::message_network; -use bitcoin::network::stream_reader::StreamReader; +use bitcoin::network::{address, constants, message, message_network, stream_reader::StreamReader}; fn main() { // This example establishes a connection to a Bitcoin node, sends the intial // "version" message, waits for the reply, and finally closes the connection. + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("not enough arguments"); + process::exit(1); + } + + let str_address = &args[1]; - let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(130, 149, 80, 221)), 8333); + let address: SocketAddr = str_address.parse().unwrap_or_else(|error| { + eprintln!("Error parsing address: {:?}", error); + process::exit(1); + }); let version_message = build_version_message(address); From 40431f3d4f2f60a08d7593ee338e0689b5711072 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 19 Feb 2020 09:11:26 +0100 Subject: [PATCH 0026/1740] Formatted. --- examples/handshake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index 1d97717e..933c758b 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -2,11 +2,11 @@ extern crate bitcoin; use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; use std::time::{SystemTime, UNIX_EPOCH}; -use std::{env, process, io::Write}; +use std::{env, io::Write, process}; -use bitcoin::secp256k1::rand::Rng; use bitcoin::consensus::encode; use bitcoin::network::{address, constants, message, message_network, stream_reader::StreamReader}; +use bitcoin::secp256k1::rand::Rng; fn main() { // This example establishes a connection to a Bitcoin node, sends the intial From aa46618da7afddf7d5b23f56f81081f9c15a8616 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Fri, 28 Feb 2020 16:28:25 +0100 Subject: [PATCH 0027/1740] Intialize stream reader only once. --- examples/handshake.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index 933c758b..e04470a8 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -36,14 +36,15 @@ fn main() { let _ = stream.write_all(encode::serialize(&first_message).as_slice()); println!("Sent version message"); - // Wait for reply and close stream - + // Setup StreamReader + let read_stream = stream.try_clone().unwrap(); + let mut stream_reader = StreamReader::new(read_stream, None); loop { - let reply = StreamReader::new(&mut stream, None).read_next(); - let unwrapped: message::RawNetworkMessage = reply.unwrap(); - match unwrapped.payload { + // Loop an retrieve new messages + let reply: message::RawNetworkMessage = stream_reader.read_next().unwrap(); + match reply.payload { message::NetworkMessage::Version(_) => { - println!("Received version message: {:?}", unwrapped.payload); + println!("Received version message: {:?}", reply.payload); let second_message = message::RawNetworkMessage { magic: constants::Network::Bitcoin.magic(), @@ -54,11 +55,11 @@ fn main() { println!("Sent verack message"); } message::NetworkMessage::Verack => { - println!("Received verack message: {:?}", unwrapped.payload); + println!("Received verack message: {:?}", reply.payload); break; } _ => { - println!("Received unknown message: {:?}", unwrapped.payload); + println!("Received unknown message: {:?}", reply.payload); break; } } From 827d98d821bae184bf236053fd10b8da0f11d379 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 3 Mar 2020 12:18:37 +0100 Subject: [PATCH 0028/1740] Fixed for rust 1.22.0. --- examples/handshake.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/handshake.rs b/examples/handshake.rs index e04470a8..036d4223 100644 --- a/examples/handshake.rs +++ b/examples/handshake.rs @@ -2,10 +2,13 @@ extern crate bitcoin; use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; use std::time::{SystemTime, UNIX_EPOCH}; -use std::{env, io::Write, process}; +use std::{env, process}; +use std::io::Write; use bitcoin::consensus::encode; -use bitcoin::network::{address, constants, message, message_network, stream_reader::StreamReader}; +use bitcoin::network::{address, constants, message, message_network}; +use bitcoin::network::stream_reader::StreamReader; +use bitcoin::secp256k1; use bitcoin::secp256k1::rand::Rng; fn main() { From 6186ee6269491a21428e9ef4229ac1d3f95c9fae Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Sat, 7 Mar 2020 19:51:36 +0000 Subject: [PATCH 0029/1740] Change Amount Debug impl to BTC with 8 decimals --- src/util/amount.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/amount.rs b/src/util/amount.rs index 1bbb6ec6..025078fc 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -463,7 +463,7 @@ impl Ord for Amount { impl fmt::Debug for Amount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Amount({} satoshi)", self.as_sat()) + write!(f, "Amount({:.8} BTC)", self.as_btc()) } } @@ -807,7 +807,7 @@ impl Ord for SignedAmount { impl fmt::Debug for SignedAmount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "SignedAmount({} satoshi)", self.as_sat()) + write!(f, "SignedAmount({:.8} BTC)", self.as_btc()) } } From 65efc5cd370a3d40705a96e5cdeb101e17e2f443 Mon Sep 17 00:00:00 2001 From: Nadav Ivgi Date: Sat, 21 Mar 2020 15:58:10 +0200 Subject: [PATCH 0030/1740] Allow to construct MerkleBlock using the header and txids Co-Authored-By: Elichai Turkel --- src/util/merkleblock.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 2c097d9b..2b682547 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -440,18 +440,31 @@ impl MerkleBlock { /// # } /// ``` pub fn from_block(block: &Block, match_txids: &HashSet) -> Self { - let header = block.header; + let block_txids: Vec<_> = block.txdata.iter().map(Transaction::txid).collect(); + Self::from_header_txids(&block.header, &block_txids, match_txids) + } + + /// Create a MerkleBlock from the block's header and txids, that should contain proofs for match_txids. + /// + /// The `header` is the block header, `block_txids` is the full list of txids included in the block and + /// `match_txids` is a set containing the transaction ids that should be included in the partial merkle tree. + /// ``` - let mut matches: Vec = Vec::with_capacity(block.txdata.len()); - let mut hashes: Vec = Vec::with_capacity(block.txdata.len()); + pub fn from_header_txids( + header: &BlockHeader, + block_txids: &[Txid], + match_txids: &HashSet, + ) -> Self { + let matches: Vec = block_txids + .into_iter() + .map(|txid| match_txids.contains(txid)) + .collect(); - for hash in block.txdata.iter().map(Transaction::txid) { - matches.push(match_txids.contains(&hash)); - hashes.push(hash); + let pmt = PartialMerkleTree::from_txids(&block_txids, &matches); + MerkleBlock { + header: *header, + txn: pmt, } - - let pmt = PartialMerkleTree::from_txids(&hashes, &matches); - MerkleBlock { header, txn: pmt } } /// Extract the matching txid's represented by this partial merkle tree From f3b5a7187c982b38bfe505429ef9ef4312c9842c Mon Sep 17 00:00:00 2001 From: Nadav Ivgi Date: Mon, 23 Mar 2020 19:38:11 +0200 Subject: [PATCH 0031/1740] Add Transaction::get_size() --- src/blockdata/transaction.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index b262b995..6e83f97b 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -389,10 +389,21 @@ impl Transaction { /// with-witness consensus-serialized size. #[inline] pub fn get_weight(&self) -> usize { + self.get_scaled_size(WITNESS_SCALE_FACTOR) + } + + /// Gets the regular byte-wise consensus-serialized size of this transaction. + #[inline] + pub fn get_size(&self) -> usize { + self.get_scaled_size(1) + } + + /// Internal utility function for get_{size,weight} + fn get_scaled_size(&self, scale_factor: usize) -> usize { let mut input_weight = 0; let mut inputs_with_witnesses = 0; for input in &self.input { - input_weight += WITNESS_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() { @@ -419,9 +430,9 @@ impl Transaction { // lock_time 4; if inputs_with_witnesses == 0 { - non_input_size * WITNESS_SCALE_FACTOR + input_weight + non_input_size * scale_factor + input_weight } else { - non_input_size * WITNESS_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 } } @@ -718,6 +729,7 @@ mod tests { assert_eq!(format!("{:x}", realtx.wtxid()), "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); assert_eq!(realtx.get_weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR); + assert_eq!(realtx.get_size(), tx_bytes.len()); } #[test] @@ -749,6 +761,7 @@ mod tests { assert_eq!(format!("{:x}", realtx.wtxid()), "80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string()); assert_eq!(realtx.get_weight(), 442); + assert_eq!(realtx.get_size(), tx_bytes.len()); } #[test] From 94032f6817a9f715adac53316aa551dd3b6b3901 Mon Sep 17 00:00:00 2001 From: Nadav Ivgi Date: Mon, 23 Mar 2020 19:30:13 +0200 Subject: [PATCH 0032/1740] Add Block::get_size() and Block::get_weight() --- src/blockdata/block.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 059ab9ae..4b272183 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -29,7 +29,8 @@ use util::uint::Uint256; use consensus::encode::Encodable; use network::constants::Network; use blockdata::transaction::Transaction; -use blockdata::constants::max_target; +use blockdata::constants::{max_target, WITNESS_SCALE_FACTOR}; +use VarInt; /// A block header, which contains all the block's information except /// the actual transactions @@ -124,6 +125,21 @@ impl Block { ); bitcoin_merkle_root(hashes).into() } + + /// Get the size of the block + pub fn get_size(&self) -> usize { + // The size of the header + the size of the varint with the tx count + the txs themselves + let base_size = 80 + VarInt(self.txdata.len() as u64).len(); + let txs_size: usize = self.txdata.iter().map(Transaction::get_size).sum(); + base_size + txs_size + } + + /// Get the weight of the block + pub fn get_weight(&self) -> usize { + let base_weight = WITNESS_SCALE_FACTOR * (80 + VarInt(self.txdata.len() as u64).len()); + let txs_weight: usize = self.txdata.iter().map(Transaction::get_weight).sum(); + base_weight + txs_weight + } } impl BlockHeader { @@ -240,6 +256,9 @@ mod tests { assert_eq!(real_decode.header.nonce, 2067413810); // [test] TODO: check the transaction data + assert_eq!(real_decode.get_size(), some_block.len()); + assert_eq!(real_decode.get_weight(), some_block.len() * 4); + // should be also ok for a non-witness block as commitment is optional in that case assert!(real_decode.check_witness_commitment()); @@ -267,6 +286,9 @@ mod tests { assert_eq!(real_decode.header.nonce, 1879759182); // [test] TODO: check the transaction data + assert_eq!(real_decode.get_size(), segwit_block.len()); + assert_eq!(real_decode.get_weight(), 17168); + assert!(real_decode.check_witness_commitment()); assert_eq!(serialize(&real_decode), segwit_block); From 16eb81e1f7dd5c3285daf1d64016786c58730339 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 5 Aug 2019 14:35:51 -0400 Subject: [PATCH 0033/1740] Replaced slow vec initialization, and dual calls to hashmap --- src/consensus/encode.rs | 4 ++-- src/network/message_blockdata.rs | 2 +- src/util/psbt/macros.rs | 12 ++++++------ src/util/psbt/map/global.rs | 23 ++++++++--------------- src/util/psbt/map/input.rs | 9 +++------ src/util/psbt/map/output.rs | 10 ++++------ 6 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 9bd8fb45..4f81c42f 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -543,8 +543,8 @@ impl Decodable for [u16; 8] { #[inline] fn consensus_decode(mut d: D) -> Result { let mut res = [0; 8]; - for i in 0..8 { - res[i] = Decodable::consensus_decode(&mut d)?; + for item in &mut res { + *item = Decodable::consensus_decode(&mut d)?; } Ok(res) } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 3326fb52..e2795ef0 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -111,7 +111,7 @@ impl GetBlocksMessage { pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetBlocksMessage { GetBlocksMessage { version: constants::PROTOCOL_VERSION, - locator_hashes: locator_hashes.clone(), + locator_hashes: locator_hashes, stop_hash: stop_hash } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 7844b7ca..80f6678d 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -119,12 +119,12 @@ macro_rules! impl_psbt_insert_pair { if !$raw_key.key.is_empty() { let key_val: $keyed_key_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?; - if $slf.$keyed_name.contains_key(&key_val) { - return Err(::util::psbt::Error::DuplicateKey($raw_key).into()); - } else { - let val: $keyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; - - $slf.$keyed_name.insert(key_val, val); + match $slf.$keyed_name.entry(key_val) { + ::std::collections::btree_map::Entry::Vacant(empty_key) => { + let val: $keyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; + empty_key.insert(val); + } + ::std::collections::btree_map::Entry::Occupied(_) => return Err(::util::psbt::Error::DuplicateKey($raw_key).into()), } } else { return Err(::util::psbt::Error::InvalidKey($raw_key).into()); diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index b34b4114..f6b411d4 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -13,6 +13,7 @@ // use std::collections::BTreeMap; +use std::collections::btree_map::Entry; use std::io::{self, Cursor}; use blockdata::transaction::Transaction; @@ -60,15 +61,10 @@ impl Map for Global { } = pair; match raw_key.type_value { - 0u8 => { - return Err(Error::DuplicateKey(raw_key).into()); - } - _ => { - if self.unknown.contains_key(&raw_key) { - return Err(Error::DuplicateKey(raw_key).into()); - } else { - self.unknown.insert(raw_key, raw_value); - } + 0u8 => return Err(Error::DuplicateKey(raw_key).into()), + _ => match self.unknown.entry(raw_key) { + Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, + Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), } } @@ -158,12 +154,9 @@ impl Decodable for Global { return Err(Error::InvalidKey(pair.key).into()) } } - _ => { - if unknowns.contains_key(&pair.key) { - return Err(Error::DuplicateKey(pair.key).into()); - } else { - unknowns.insert(pair.key, pair.value); - } + _ => match unknowns.entry(pair.key) { + Entry::Vacant(empty_key) => {empty_key.insert(pair.value);}, + Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), } } } diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 32f19bc5..05a24432 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -112,12 +112,9 @@ impl Map for Input { self.hd_keypaths <= | } } - _ => { - if self.unknown.contains_key(&raw_key) { - return Err(Error::DuplicateKey(raw_key).into()); - } else { - self.unknown.insert(raw_key, raw_value); - } + _ => match self.unknown.entry(raw_key) { + ::std::collections::btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, + ::std::collections::btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), } } diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 8219e812..7e32a421 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -13,6 +13,7 @@ // use std::collections::BTreeMap; +use std::collections::btree_map::Entry; use blockdata::script::Script; use consensus::encode; @@ -61,12 +62,9 @@ impl Map for Output { self.hd_keypaths <= | } } - _ => { - if self.unknown.contains_key(&raw_key) { - return Err(Error::DuplicateKey(raw_key).into()); - } else { - self.unknown.insert(raw_key, raw_value); - } + _ => match self.unknown.entry(raw_key) { + Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, + Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), } } From 3f2d4287061c7b42a9609b21369a7acdab679091 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 5 Aug 2019 14:52:34 -0400 Subject: [PATCH 0034/1740] Remove needless references --- src/blockdata/opcodes.rs | 34 +++++++++++++++++----------------- src/blockdata/transaction.rs | 6 +++--- src/network/constants.rs | 13 ++++++------- src/util/amount.rs | 32 ++++++++++++++++---------------- src/util/bip158.rs | 4 ++-- src/util/bip32.rs | 16 ++++++++-------- src/util/psbt/mod.rs | 4 ++-- 7 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index 724b16c2..697eee54 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -658,29 +658,29 @@ impl fmt::Debug for All { impl All { /// Classifies an Opcode into a broad class #[inline] - pub fn classify(&self) -> Class { + pub fn classify(self) -> Class { // 17 opcodes - if *self == all::OP_VERIF || *self == all::OP_VERNOTIF || - *self == all::OP_CAT || *self == all::OP_SUBSTR || - *self == all::OP_LEFT || *self == all::OP_RIGHT || - *self == all::OP_INVERT || *self == all::OP_AND || - *self == all::OP_OR || *self == all::OP_XOR || - *self == all::OP_2MUL || *self == all::OP_2DIV || - *self == all::OP_MUL || *self == all::OP_DIV || *self == all::OP_MOD || - *self == all::OP_LSHIFT || *self == all::OP_RSHIFT { + if self == all::OP_VERIF || self == all::OP_VERNOTIF || + self == all::OP_CAT || self == all::OP_SUBSTR || + self == all::OP_LEFT || self == all::OP_RIGHT || + self == all::OP_INVERT || self == all::OP_AND || + self == all::OP_OR || self == all::OP_XOR || + self == all::OP_2MUL || self == all::OP_2DIV || + self == all::OP_MUL || self == all::OP_DIV || self == all::OP_MOD || + self == all::OP_LSHIFT || self == all::OP_RSHIFT { Class::IllegalOp // 11 opcodes - } else if *self == all::OP_NOP || + } else if self == all::OP_NOP || (all::OP_NOP1.code <= self.code && self.code <= all::OP_NOP10.code) { Class::NoOp // 75 opcodes - } else if *self == all::OP_RESERVED || *self == all::OP_VER || *self == all::OP_RETURN || - *self == all::OP_RESERVED1 || *self == all::OP_RESERVED2 || + } else if self == all::OP_RESERVED || self == all::OP_VER || self == all::OP_RETURN || + self == all::OP_RESERVED1 || self == all::OP_RESERVED2 || self.code >= all::OP_RETURN_186.code { Class::ReturnOp // 1 opcode - } else if *self == all::OP_PUSHNUM_NEG1 { + } else if self == all::OP_PUSHNUM_NEG1 { Class::PushNum(-1) // 16 opcodes } else if all::OP_PUSHNUM_1.code <= self.code && @@ -691,13 +691,13 @@ impl All { Class::PushBytes(self.code as u32) // 60 opcodes } else { - Class::Ordinary(Ordinary::try_from_all(*self).unwrap()) + Class::Ordinary(Ordinary::try_from_all(self).unwrap()) } } /// Encode as a byte #[inline] - pub fn into_u8(&self) -> u8 { + pub fn into_u8(self) -> u8 { self.code } } @@ -809,8 +809,8 @@ ordinary_opcode! { impl Ordinary { /// Encode as a byte #[inline] - pub fn into_u8(&self) -> u8 { - *self as u8 + pub fn into_u8(self) -> u8 { + self as u8 } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 6e83f97b..99b87f22 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -598,8 +598,8 @@ pub enum SigHashType { impl SigHashType { /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean - pub(crate) fn split_anyonecanpay_flag(&self) -> (SigHashType, bool) { - match *self { + pub(crate) fn split_anyonecanpay_flag(self) -> (SigHashType, bool) { + match self { SigHashType::All => (SigHashType::All, false), SigHashType::None => (SigHashType::None, false), SigHashType::Single => (SigHashType::Single, false), @@ -626,7 +626,7 @@ impl SigHashType { } /// Converts to a u32 - pub fn as_u32(&self) -> u32 { *self as u32 } + pub fn as_u32(self) -> u32 { self as u32 } } diff --git a/src/network/constants.rs b/src/network/constants.rs index 8724398a..0540981a 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -89,9 +89,9 @@ impl Network { /// let network = Network::Bitcoin; /// assert_eq!(network.magic(), 0xD9B4BEF9); /// ``` - pub fn magic(&self) -> u32 { + pub fn magic(self) -> u32 { // Note: any new entries here must be added to `from_magic` above - match *self { + match self { Network::Bitcoin => 0xD9B4BEF9, Network::Testnet => 0x0709110B, Network::Regtest => 0xDAB5BFFA, @@ -154,12 +154,12 @@ impl ServiceFlags { } /// Check whether [ServiceFlags] are included in this one. - pub fn has(&self, flags: ServiceFlags) -> bool { + pub fn has(self, flags: ServiceFlags) -> bool { (self.0 | flags.0) == self.0 } /// Get the integer representation of this [ServiceFlags]. - pub fn as_u64(&self) -> u64 { + pub fn as_u64(self) -> u64 { self.0 } } @@ -178,11 +178,10 @@ impl fmt::UpperHex for ServiceFlags { impl fmt::Display for ServiceFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if *self == ServiceFlags::NONE { + let mut flags = *self; + if flags == ServiceFlags::NONE { return write!(f, "ServiceFlags(NONE)"); } - - let mut flags = self.clone(); let mut first = true; macro_rules! write_flag { ($f:ident) => { diff --git a/src/util/amount.rs b/src/util/amount.rs index 1bbb6ec6..31cb31f6 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -340,7 +340,7 @@ impl Amount { /// Express this [Amount] as a floating-point value in the given denomination. /// /// Please be aware of the risk of using floating-point numbers. - pub fn to_float_in(&self, denom: Denomination) -> f64 { + pub fn to_float_in(self, denom: Denomination) -> f64 { f64::from_str(&self.to_string_in(denom)).unwrap() } @@ -349,7 +349,7 @@ impl Amount { /// Equivalent to `to_float_in(Denomination::Bitcoin)`. /// /// Please be aware of the risk of using floating-point numbers. - pub fn as_btc(&self) -> f64 { + pub fn as_btc(self) -> f64 { self.to_float_in(Denomination::Bitcoin) } @@ -370,14 +370,14 @@ impl Amount { /// Format the value of this [Amount] in the given denomination. /// /// Does not include the denomination. - pub fn fmt_value_in(&self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result { + pub fn fmt_value_in(self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result { fmt_satoshi_in(self.as_sat(), false, f, denom) } /// Get a string number of this [Amount] in the given denomination. /// /// Does not include the denomination. - pub fn to_string_in(&self, denom: Denomination) -> String { + pub fn to_string_in(self, denom: Denomination) -> String { let mut buf = String::new(); self.fmt_value_in(&mut buf, denom).unwrap(); buf @@ -385,7 +385,7 @@ impl Amount { /// Get a formatted string of this [Amount] in the given denomination, /// suffixed with the abbreviation for the denomination. - pub fn to_string_with_denomination(&self, denom: Denomination) -> String { + pub fn to_string_with_denomination(self, denom: Denomination) -> String { let mut buf = String::new(); self.fmt_value_in(&mut buf, denom).unwrap(); write!(buf, " {}", denom).unwrap(); @@ -637,7 +637,7 @@ impl SignedAmount { /// Express this [SignedAmount] as a floating-point value in the given denomination. /// /// Please be aware of the risk of using floating-point numbers. - pub fn to_float_in(&self, denom: Denomination) -> f64 { + pub fn to_float_in(self, denom: Denomination) -> f64 { f64::from_str(&self.to_string_in(denom)).unwrap() } @@ -646,7 +646,7 @@ impl SignedAmount { /// Equivalent to `to_float_in(Denomination::Bitcoin)`. /// /// Please be aware of the risk of using floating-point numbers. - pub fn as_btc(&self) -> f64 { + pub fn as_btc(self) -> f64 { self.to_float_in(Denomination::Bitcoin) } @@ -667,7 +667,7 @@ impl SignedAmount { /// Format the value of this [SignedAmount] in the given denomination. /// /// Does not include the denomination. - pub fn fmt_value_in(&self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result { + pub fn fmt_value_in(self, f: &mut 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 @@ -678,7 +678,7 @@ impl SignedAmount { /// Get a string number of this [SignedAmount] in the given denomination. /// /// Does not include the denomination. - pub fn to_string_in(&self, denom: Denomination) -> String { + pub fn to_string_in(self, denom: Denomination) -> String { let mut buf = String::new(); self.fmt_value_in(&mut buf, denom).unwrap(); buf @@ -686,7 +686,7 @@ impl SignedAmount { /// Get a formatted string of this [SignedAmount] in the given denomination, /// suffixed with the abbreviation for the denomination. - pub fn to_string_with_denomination(&self, denom: Denomination) -> String { + pub fn to_string_with_denomination(self, denom: Denomination) -> String { let mut buf = String::new(); self.fmt_value_in(&mut buf, denom).unwrap(); write!(buf, " {}", denom).unwrap(); @@ -1313,12 +1313,12 @@ mod tests { use super::Denomination as D; let amt = Amount::from_sat(42); let denom = Amount::to_string_with_denomination; - assert_eq!(Amount::from_str(&denom(&amt, D::Bitcoin)), Ok(amt)); - assert_eq!(Amount::from_str(&denom(&amt, D::MilliBitcoin)), Ok(amt)); - assert_eq!(Amount::from_str(&denom(&amt, D::MicroBitcoin)), Ok(amt)); - assert_eq!(Amount::from_str(&denom(&amt, D::Bit)), Ok(amt)); - assert_eq!(Amount::from_str(&denom(&amt, D::Satoshi)), Ok(amt)); - assert_eq!(Amount::from_str(&denom(&amt, D::MilliSatoshi)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::Bitcoin)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::MilliBitcoin)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::MicroBitcoin)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::Bit)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::Satoshi)), Ok(amt)); + assert_eq!(Amount::from_str(&denom(amt, D::MilliSatoshi)), Ok(amt)); assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat)); assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat)); diff --git a/src/util/bip158.rs b/src/util/bip158.rs index b7154bfe..d196a11d 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -241,7 +241,7 @@ impl GCSFilterReader { pub fn match_any(&self, reader: &mut io::Read, query: &mut Iterator) -> Result { let mut decoder = reader; let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0)); - let ref mut reader = decoder; + let reader = &mut decoder; // map hashes to [0, n_elements << grp] let nm = n_elements.0 * self.m; let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::>(); @@ -281,7 +281,7 @@ impl GCSFilterReader { pub fn match_all(&self, reader: &mut io::Read, query: &mut Iterator) -> Result { let mut decoder = reader; let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0)); - let ref mut reader = decoder; + let reader = &mut decoder; // map hashes to [0, n_elements << grp] let nm = n_elements.0 * self.m; let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::>(); diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 470e59e1..d66167ec 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -124,15 +124,15 @@ impl ChildNumber { /// Returns `true` if the child number is a [`Normal`] value. /// /// [`Normal`]: #variant.Normal - pub fn is_normal(&self) -> bool { + pub fn is_normal(self) -> bool { !self.is_hardened() } /// Returns `true` if the child number is a [`Hardened`] value. /// /// [`Hardened`]: #variant.Hardened - pub fn is_hardened(&self) -> bool { - match *self { + pub fn is_hardened(self) -> bool { + match self { ChildNumber::Hardened {..} => true, ChildNumber::Normal {..} => false, } @@ -548,7 +548,7 @@ impl ExtendedPubKey { i: ChildNumber, ) -> Result { let (sk, chain_code) = self.ckd_pub_tweak(i)?; - let mut pk = self.public_key.clone(); + let mut pk = self.public_key; pk.key.add_exp_assign(secp, &sk[..]).map_err(Error::Ecdsa)?; Ok(ExtendedPubKey { @@ -604,9 +604,9 @@ impl FromStr for ExtendedPrivKey { let cn_int: u32 = endian::slice_to_u32_be(&data[9..13]); let child_number: ChildNumber = ChildNumber::from(cn_int); - let network = if &data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] { + let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] { Network::Bitcoin - } else if &data[0..4] == [0x04u8, 0x35, 0x83, 0x94] { + } else if data[0..4] == [0x04u8, 0x35, 0x83, 0x94] { Network::Testnet } else { return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec())); @@ -661,9 +661,9 @@ impl FromStr for ExtendedPubKey { let child_number: ChildNumber = ChildNumber::from(cn_int); Ok(ExtendedPubKey { - network: if &data[0..4] == [0x04u8, 0x88, 0xB2, 0x1E] { + network: if data[0..4] == [0x04u8, 0x88, 0xB2, 0x1E] { Network::Bitcoin - } else if &data[0..4] == [0x04u8, 0x35, 0x87, 0xCF] { + } else if data[0..4] == [0x04u8, 0x35, 0x87, 0xCF] { Network::Testnet } else { return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec())); diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index d281f1ce..985039f8 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -67,8 +67,8 @@ impl PartiallySignedTransaction { let mut tx: Transaction = self.global.unsigned_tx; for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) { - vin.script_sig = psbtin.final_script_sig.unwrap_or_else(|| Script::new()); - vin.witness = psbtin.final_script_witness.unwrap_or_else(|| Vec::new()); + vin.script_sig = psbtin.final_script_sig.unwrap_or_else(Script::new); + vin.witness = psbtin.final_script_witness.unwrap_or_else(Vec::new); } tx From a473d01b1710bb556e4c8513ed72c939b8abf307 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 5 Aug 2019 15:41:07 -0400 Subject: [PATCH 0035/1740] Made some idiomatic changes --- src/blockdata/block.rs | 2 +- src/consensus/encode.rs | 6 ++--- src/network/address.rs | 6 ++--- src/network/message.rs | 4 +-- src/util/address.rs | 30 ++++++++++------------ src/util/amount.rs | 55 ++++++++++++++++++++++------------------- src/util/base58.rs | 2 +- src/util/bip158.rs | 46 +++++++++++++++++----------------- src/util/bip32.rs | 20 ++++++--------- src/util/hash.rs | 2 +- src/util/merkleblock.rs | 11 +-------- src/util/misc.rs | 4 +-- src/util/psbt/macros.rs | 2 +- 13 files changed, 87 insertions(+), 103 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 059ab9ae..c081609b 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -78,7 +78,7 @@ impl Block { if self.txdata.iter().all(|t| t.input.iter().all(|i| i.witness.is_empty())) { return true; } - if self.txdata.len() > 0 { + if !self.txdata.is_empty() { let coinbase = &self.txdata[0]; if coinbase.is_coin_base() { // commitment is in the last output that starts with below magic diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 4f81c42f..e3a38396 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -162,7 +162,7 @@ pub fn serialize_hex(data: &T) -> String { /// Deserialize an object from a vector, will error if said deserialization /// doesn't consume the entire vector. -pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result { +pub fn deserialize(data: &[u8]) -> Result { let (rv, consumed) = deserialize_partial(data)?; // Fail if data are not consumed entirely. @@ -175,8 +175,8 @@ pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result { /// Deserialize an object from a vector, but will not report an error if said deserialization /// doesn't consume the entire vector. -pub fn deserialize_partial<'a, T: Decodable>( - data: &'a [u8], +pub fn deserialize_partial( + data: &[u8], ) -> Result<(T, usize), Error> { let mut decoder = Cursor::new(data); let rv = Decodable::consensus_decode(&mut decoder)?; diff --git a/src/network/address.rs b/src/network/address.rs index f9dcbf0b..6edc5bb5 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -41,9 +41,9 @@ const ONION : [u16; 3] = [0xFD87, 0xD87E, 0xEB43]; impl Address { /// Create an address message for a socket pub fn new (socket :&SocketAddr, services: ServiceFlags) -> Address { - let (address, port) = match socket { - &SocketAddr::V4(ref addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()), - &SocketAddr::V6(ref addr) => (addr.ip().segments(), addr.port()) + let (address, port) = match *socket { + SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()), + SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()) }; Address { address: address, port: port, services: services } } diff --git a/src/network/message.rs b/src/network/message.rs index 5710023c..5147252b 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -72,9 +72,7 @@ impl Encodable for CommandString { if strbytes.len() > 12 { return Err(encode::Error::UnrecognizedNetworkCommand(self.0.clone().into_owned())); } - for x in 0..strbytes.len() { - rawbytes[x] = strbytes[x]; - } + rawbytes[..strbytes.len()].clone_from_slice(&strbytes[..]); rawbytes.consensus_encode(s) } } diff --git a/src/util/address.rs b/src/util/address.rs index 7715736f..dcb418d5 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -18,26 +18,22 @@ //! # Example: creating a new address from a randomly-generated key pair //! //! ```rust -//! extern crate secp256k1; -//! extern crate bitcoin; //! //! use bitcoin::network::constants::Network; //! use bitcoin::util::address::Address; //! use bitcoin::util::key; -//! use secp256k1::Secp256k1; -//! use secp256k1::rand::thread_rng; +//! use bitcoin::secp256k1::Secp256k1; +//! use bitcoin::secp256k1::rand::thread_rng; //! -//! fn main() { -//! // Generate random key pair -//! let s = Secp256k1::new(); -//! let public_key = key::PublicKey { -//! compressed: true, -//! key: s.generate_keypair(&mut thread_rng()).1, -//! }; +//! // Generate random key pair +//! let s = Secp256k1::new(); +//! let public_key = key::PublicKey { +//! compressed: true, +//! key: s.generate_keypair(&mut thread_rng()).1, +//! }; //! -//! // Generate pay-to-pubkey-hash address -//! let address = Address::p2pkh(&public_key, Network::Bitcoin); -//! } +//! // Generate pay-to-pubkey-hash address +//! let address = Address::p2pkh(&public_key, Network::Bitcoin); //! ``` use std::fmt::{self, Display, Formatter}; @@ -219,7 +215,7 @@ impl Payload { assert!(ver.to_u8() <= 16); let mut verop = ver.to_u8(); if verop > 0 { - verop = 0x50 + verop; + verop += 0x50; } script::Builder::new().push_opcode(verop.into()).push_slice(&prog) } @@ -406,7 +402,7 @@ impl Display for Address { /// Returns the same slice when no prefix is found. fn find_bech32_prefix(bech32: &str) -> &str { // Split at the last occurrence of the separator character '1'. - match bech32.rfind("1") { + match bech32.rfind('1') { None => bech32, Some(sep) => bech32.split_at(sep).0, } @@ -427,7 +423,7 @@ impl FromStr for Address { if let Some(network) = bech32_network { // decode as bech32 let (_, payload) = bech32::decode(s)?; - if payload.len() == 0 { + if payload.is_empty() { return Err(Error::EmptyBech32Payload); } diff --git a/src/util/amount.rs b/src/util/amount.rs index 31cb31f6..1fea2b15 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -19,6 +19,7 @@ use std::error; use std::fmt::{self, Write}; use std::ops; use std::str::FromStr; +use std::cmp::Ordering; /// A set of denominations in which amounts can be expressed. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] @@ -131,7 +132,7 @@ impl error::Error for ParseAmountError { fn is_too_precise(s: &str, precision: usize) -> bool { - s.contains(".") || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0') + s.contains('.') || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0') } /// Parse decimal string in the given denomination into a satoshi value and a @@ -140,14 +141,14 @@ fn parse_signed_to_satoshi( mut s: &str, denom: Denomination, ) -> Result<(bool, u64), ParseAmountError> { - if s.len() == 0 { + if s.is_empty() { return Err(ParseAmountError::InvalidFormat); } if s.len() > 50 { return Err(ParseAmountError::InputTooLarge); } - let is_negative = s.chars().next().unwrap() == '-'; + let is_negative = s.starts_with('-'); if is_negative { if s.len() == 1 { return Err(ParseAmountError::InvalidFormat); @@ -229,27 +230,29 @@ fn fmt_satoshi_in( f.write_str("-")?; } - if denom.precision() > 0 { - // add zeroes in the end - let width = denom.precision() as usize; - write!(f, "{}{:0width$}", satoshi, 0, width = width)?; - } else if denom.precision() < 0 { - // need to inject a comma in the number - let nb_decimals = denom.precision().abs() as usize; - let real = format!("{:0width$}", satoshi, width = nb_decimals); - if real.len() == nb_decimals { - write!(f, "0.{}", &real[real.len() - nb_decimals..])?; - } else { - write!( - f, - "{}.{}", - &real[0..(real.len() - nb_decimals)], - &real[real.len() - nb_decimals..] - )?; + let precision = denom.precision(); + match precision.cmp(&0) { + Ordering::Greater => { + // add zeroes in the end + let width = precision as usize; + write!(f, "{}{:0width$}", satoshi, 0, width = width)?; + } + Ordering::Less => { + // need to inject a comma in the number + let nb_decimals = precision.abs() as usize; + let real = format!("{:0width$}", satoshi, width = nb_decimals); + if real.len() == nb_decimals { + write!(f, "0.{}", &real[real.len() - nb_decimals..])?; + } else { + write!( + f, + "{}.{}", + &real[0..(real.len() - nb_decimals)], + &real[real.len() - nb_decimals..] + )?; + } } - } else { - // denom.precision() == 0 - write!(f, "{}", satoshi)?; + Ordering::Equal => write!(f, "{}", satoshi)?, } Ok(()) } @@ -327,7 +330,7 @@ impl Amount { /// If you want to parse only the amount without the denomination, /// use [from_str_in]. pub fn from_str_with_denomination(s: &str) -> Result { - let mut split = s.splitn(3, " "); + let mut split = s.splitn(3, ' '); let amt_str = split.next().unwrap(); let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?; if split.next().is_some() { @@ -614,7 +617,7 @@ impl SignedAmount { return Err(ParseAmountError::TooBig); } Ok(match negative { - true => SignedAmount(-1 * satoshi as i64), + true => SignedAmount(-(satoshi as i64)), false => SignedAmount(satoshi as i64), }) } @@ -624,7 +627,7 @@ impl SignedAmount { /// If you want to parse only the amount without the denomination, /// use [from_str_in]. pub fn from_str_with_denomination(s: &str) -> Result { - let mut split = s.splitn(3, " "); + let mut split = s.splitn(3, ' '); let amt_str = split.next().unwrap(); let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?; if split.next().is_some() { diff --git a/src/util/base58.rs b/src/util/base58.rs index 68a0a2b7..2134b5c6 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -103,7 +103,7 @@ impl SmallVec { } } -static BASE58_CHARS: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +static BASE58_CHARS: &[u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; static BASE58_DIGITS: [Option; 128] = [ None, None, None, None, None, None, None, None, // 0-7 diff --git a/src/util/bip158.rs b/src/util/bip158.rs index d196a11d..4cb896a5 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -49,6 +49,8 @@ use std::collections::HashSet; use std::error; use std::fmt::{Display, Formatter}; use std::io::Cursor; +use std::cmp::Ordering; + use hashes::{Hash, siphash24}; use hash_types::{BlockHash, FilterHash}; @@ -260,17 +262,17 @@ impl GCSFilterReader { let mut remaining = n_elements.0 - 1; for p in mapped { loop { - if data == p { - return Ok(true); - } else if data < p { - if remaining > 0 { - data += self.filter.golomb_rice_decode(&mut reader)?; - remaining -= 1; - } else { - return Ok(false); + match data.cmp(&p) { + Ordering::Equal => return Ok(true), + Ordering::Less => { + if remaining > 0 { + data += self.filter.golomb_rice_decode(&mut reader)?; + remaining -= 1; + } else { + return Ok(false); + } } - } else { - break; + Ordering::Greater => break, } } } @@ -301,17 +303,17 @@ impl GCSFilterReader { let mut remaining = n_elements.0 - 1; for p in mapped { loop { - if data == p { - break; - } else if data < p { - if remaining > 0 { - data += self.filter.golomb_rice_decode(&mut reader)?; - remaining -= 1; - } else { - return Ok(false); - } - } else { - return Ok(false); + match data.cmp(&p) { + Ordering::Equal => break, + Ordering::Less => { + if remaining > 0 { + data += self.filter.golomb_rice_decode(&mut reader)?; + remaining -= 1; + } else { + return Ok(false); + } + }, + Ordering::Greater => return Ok(false), } } } @@ -423,7 +425,7 @@ impl GCSFilter { q += 1; } let r = reader.read(self.p)?; - return Ok((q << self.p) + r); + Ok((q << self.p) + r) } /// Hash an arbitrary slice with siphash using parameters of this filter diff --git a/src/util/bip32.rs b/src/util/bip32.rs index d66167ec..be3e189c 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -179,13 +179,11 @@ impl FromStr for ChildNumber { type Err = Error; fn from_str(inp: &str) -> Result { - Ok(match inp.chars().last().map_or(false, |l| l == '\'' || l == 'h') { - true => ChildNumber::from_hardened_idx( - inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)? - )?, - false => ChildNumber::from_normal_idx( - inp.parse().map_err(|_| Error::InvalidChildNumberFormat)? - )?, + 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)?)? + } else { + ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)? }) } } @@ -258,7 +256,7 @@ impl FromStr for DerivationPath { type Err = Error; fn from_str(path: &str) -> Result { - let mut parts = path.split("/"); + let mut parts = path.split('/'); // First parts must be `m`. if parts.next().unwrap() != "m" { return Err(Error::InvalidDerivationPathFormat); @@ -292,11 +290,7 @@ impl<'a> Iterator for DerivationPathIterator<'a> { type Item = DerivationPath; fn next(&mut self) -> Option { - if self.next_child.is_none() { - return None; - } - - let ret = self.next_child.unwrap(); + let ret = self.next_child?; self.next_child = ret.increment().ok(); Some(self.base.child(ret)) } diff --git a/src/util/hash.rs b/src/util/hash.rs index ba7b6d20..fa089135 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -30,7 +30,7 @@ pub fn bitcoin_merkle_root_inline(data: &mut [T]) -> T ::Engine: io::Write, { // Base case - if data.len() < 1 { + if data.is_empty() { return Default::default(); } if data.len() < 2 { diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 2c097d9b..d4ce3973 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -25,12 +25,10 @@ //! # Examples //! //! ```rust -//! extern crate bitcoin; //! use bitcoin::hash_types::Txid; //! use bitcoin::hashes::hex::FromHex; //! use bitcoin::{Block, MerkleBlock}; //! -//! # fn main() { //! // Get the proof from a bitcoind by running in the terminal: //! // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2" //! // $ bitcoin-cli gettxoutproof [\"$TXID\"] @@ -52,7 +50,6 @@ //! ); //! assert_eq!(1, index.len()); //! assert_eq!(1, index[0]); -//! # } //! ``` use std::collections::HashSet; @@ -133,12 +130,10 @@ impl PartialMerkleTree { /// # Examples /// /// ```rust - /// extern crate bitcoin; /// use bitcoin::hash_types::Txid; /// use bitcoin::hashes::hex::FromHex; /// use bitcoin::util::merkleblock::PartialMerkleTree; /// - /// # fn main() { /// // Block 80000 /// let txids: Vec = [ /// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25", @@ -152,7 +147,6 @@ impl PartialMerkleTree { /// let matches = vec![false, true]; /// let tree = PartialMerkleTree::from_txids(&txids, &matches); /// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok()); - /// # } /// ``` pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self { // We can never have zero txs in a merkle block, we always need the coinbase tx @@ -271,7 +265,7 @@ impl PartialMerkleTree { if height == 0 || !parent_of_match { // If at height 0, or nothing interesting below, store hash and stop let hash = self.calc_hash(height, pos, txids); - self.hashes.push(hash.into()); + self.hashes.push(hash); } else { // Otherwise, don't store any hash, but descend into the subtrees self.traverse_and_build(height - 1, pos * 2, txids, matches); @@ -407,12 +401,10 @@ impl MerkleBlock { /// # Examples /// /// ```rust - /// extern crate bitcoin; /// use bitcoin::hash_types::Txid; /// use bitcoin::hashes::hex::FromHex; /// use bitcoin::{Block, MerkleBlock}; /// - /// # fn main() { /// // Block 80000 /// let block_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad2\ /// 7b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33\ @@ -437,7 +429,6 @@ impl MerkleBlock { /// let mut index: Vec = vec![]; /// assert!(mb.extract_matches(&mut matches, &mut index).is_ok()); /// assert_eq!(txid, matches[0]); - /// # } /// ``` pub fn from_block(block: &Block, match_txids: &HashSet) -> Self { let header = block.header; diff --git a/src/util/misc.rs b/src/util/misc.rs index f5c2a545..2ee4fb0c 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -20,14 +20,14 @@ use hashes::{sha256d, Hash}; use blockdata::opcodes; use consensus::encode; -static MSG_SIGN_PREFIX: &'static [u8] = b"\x18Bitcoin Signed Message:\n"; +static MSG_SIGN_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n"; /// Search for `needle` in the vector `haystack` and remove every /// instance of it, returning the number of instances removed. /// Loops through the vector opcode by opcode, skipping pushed data. pub fn script_find_and_remove(haystack: &mut Vec, needle: &[u8]) -> usize { if needle.len() > haystack.len() { return 0; } - if needle.len() == 0 { return 0; } + if needle.is_empty() { return 0; } let mut top = haystack.len() - needle.len(); let mut n_deleted = 0; diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 80f6678d..5109b94f 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -104,7 +104,7 @@ macro_rules! impl_psbtmap_consensus_enc_dec_oding { macro_rules! impl_psbt_insert_pair { ($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => { if $raw_key.key.is_empty() { - if let None = $slf.$unkeyed_name { + if $slf.$unkeyed_name.is_none() { let val: $unkeyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; $slf.$unkeyed_name = Some(val) From 2cc88a99aa45c04c2112f9ba23ef99f1f5297986 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 5 Aug 2019 15:44:32 -0400 Subject: [PATCH 0036/1740] Removed PartialEq,PartialOrd impls, shouldn't be manually impl when Hash is derived --- src/util/amount.rs | 42 ++---------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/src/util/amount.rs b/src/util/amount.rs index 1fea2b15..f945b190 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -274,7 +274,7 @@ fn fmt_satoshi_in( /// zero is considered an underflow and will cause a panic if you're not using /// the checked arithmetic methods. /// -#[derive(Copy, Clone, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Amount(u64); impl Amount { @@ -445,25 +445,6 @@ impl default::Default for Amount { } } -impl PartialEq for Amount { - fn eq(&self, other: &Amount) -> bool { - PartialEq::eq(&self.0, &other.0) - } -} -impl Eq for Amount {} - -impl PartialOrd for Amount { - fn partial_cmp(&self, other: &Amount) -> Option<::std::cmp::Ordering> { - PartialOrd::partial_cmp(&self.0, &other.0) - } -} - -impl Ord for Amount { - fn cmp(&self, other: &Amount) -> ::std::cmp::Ordering { - Ord::cmp(&self.0, &other.0) - } -} - impl fmt::Debug for Amount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Amount({} satoshi)", self.as_sat()) @@ -571,7 +552,7 @@ impl FromStr for Amount { /// start with `checked_`. The operations from [std::ops] that [Amount] /// implements will panic when overflow or underflow occurs. /// -#[derive(Copy, Clone, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SignedAmount(i64); impl SignedAmount { @@ -789,25 +770,6 @@ impl default::Default for SignedAmount { } } -impl PartialEq for SignedAmount { - fn eq(&self, other: &SignedAmount) -> bool { - PartialEq::eq(&self.0, &other.0) - } -} -impl Eq for SignedAmount {} - -impl PartialOrd for SignedAmount { - fn partial_cmp(&self, other: &SignedAmount) -> Option<::std::cmp::Ordering> { - PartialOrd::partial_cmp(&self.0, &other.0) - } -} - -impl Ord for SignedAmount { - fn cmp(&self, other: &SignedAmount) -> ::std::cmp::Ordering { - Ord::cmp(&self.0, &other.0) - } -} - impl fmt::Debug for SignedAmount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "SignedAmount({} satoshi)", self.as_sat()) From fea09a0a940484f096cb51ae44de89dc115892b0 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 23 Jan 2020 01:28:12 +0000 Subject: [PATCH 0037/1740] Improve the Instructions iterator for scripts - Rename the `iter` method to `instructions`. - Add `instructions_minimal` for minimal-enforced iteration. - Iterator has `Result` as items. --- fuzz/fuzz_targets/deserialize_script.rs | 11 +-- src/blockdata/script.rs | 99 +++++++++++++------------ src/util/contracthash.rs | 8 +- 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/fuzz/fuzz_targets/deserialize_script.rs b/fuzz/fuzz_targets/deserialize_script.rs index e7c36de0..63ab573c 100644 --- a/fuzz/fuzz_targets/deserialize_script.rs +++ b/fuzz/fuzz_targets/deserialize_script.rs @@ -8,13 +8,14 @@ use bitcoin::consensus::encode; fn do_test(data: &[u8]) { let s: Result = encode::deserialize(data); if let Ok(script) = s { - let _: Vec = script.iter(false).collect(); - let enforce_min: Vec = script.iter(true).collect(); + let _: Result, script::Error> = script.instructions().collect(); let mut b = script::Builder::new(); - for ins in enforce_min { - match ins { - script::Instruction::Error(_) => return, + for ins in script.instructions_minimal() { + if ins.is_err() { + return; + } + match ins.ok().unwrap() { script::Instruction::Op(op) => { b = b.push_opcode(op); } script::Instruction::PushBytes(bytes) => { // Any one-byte pushes, except -0, which can be interpreted as numbers, should be diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index d71b936c..3dcd9d85 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -329,10 +329,21 @@ impl Script { /// opcodes, datapushes and errors. At most one error will be returned and then the /// iterator will end. To instead iterate over the script as sequence of bytes, treat /// it as a slice using `script[..]` or convert it to a vector using `into_bytes()`. - pub fn iter(&self, enforce_minimal: bool) -> Instructions { + /// + /// To force minimal pushes, use [instructions_minimal]. + pub fn instructions(&self) -> Instructions { Instructions { data: &self.0[..], - enforce_minimal: enforce_minimal, + enforce_minimal: false, + } + } + + /// Iterate 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, } } @@ -437,8 +448,6 @@ pub enum Instruction<'a> { PushBytes(&'a [u8]), /// Some non-push opcode Op(opcodes::All), - /// An opcode we were unable to parse - Error(Error) } /// Iterator over a script returning parsed opcodes @@ -448,9 +457,9 @@ pub struct Instructions<'a> { } impl<'a> Iterator for Instructions<'a> { - type Item = Instruction<'a>; + type Item = Result, Error>; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option, Error>> { if self.data.is_empty() { return None; } @@ -460,93 +469,93 @@ impl<'a> Iterator for Instructions<'a> { let n = n as usize; if self.data.len() < n + 1 { self.data = &[]; // Kill iterator so that it does not return an infinite stream of errors - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } if self.enforce_minimal { if n == 1 && (self.data[1] == 0x81 || (self.data[1] > 0 && self.data[1] <= 16)) { self.data = &[]; - return Some(Instruction::Error(Error::NonMinimalPush)); + return Some(Err(Error::NonMinimalPush)); } } - let ret = Some(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 } opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => { if self.data.len() < 2 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } let n = match read_uint(&self.data[1..], 1) { Ok(n) => n, Err(e) => { self.data = &[]; - return Some(Instruction::Error(e)); + return Some(Err(e)); } }; if self.data.len() < n + 2 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } if self.enforce_minimal && n < 76 { self.data = &[]; - return Some(Instruction::Error(Error::NonMinimalPush)); + return Some(Err(Error::NonMinimalPush)); } - let ret = Some(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 } opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => { if self.data.len() < 3 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } let n = match read_uint(&self.data[1..], 2) { Ok(n) => n, Err(e) => { self.data = &[]; - return Some(Instruction::Error(e)); + return Some(Err(e)); } }; if self.enforce_minimal && n < 0x100 { self.data = &[]; - return Some(Instruction::Error(Error::NonMinimalPush)); + return Some(Err(Error::NonMinimalPush)); } if self.data.len() < n + 3 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } - let ret = Some(Instruction::PushBytes(&self.data[3..n + 3])); + let ret = Some(Ok(Instruction::PushBytes(&self.data[3..n + 3]))); self.data = &self.data[n + 3..]; ret } opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => { if self.data.len() < 5 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } let n = match read_uint(&self.data[1..], 4) { Ok(n) => n, Err(e) => { self.data = &[]; - return Some(Instruction::Error(e)); + return Some(Err(e)); } }; if self.enforce_minimal && n < 0x10000 { self.data = &[]; - return Some(Instruction::Error(Error::NonMinimalPush)); + return Some(Err(Error::NonMinimalPush)); } if self.data.len() < n + 5 { self.data = &[]; - return Some(Instruction::Error(Error::EarlyEndOfScript)); + return Some(Err(Error::EarlyEndOfScript)); } - let ret = Some(Instruction::PushBytes(&self.data[5..n + 5])); + let ret = Some(Ok(Instruction::PushBytes(&self.data[5..n + 5]))); self.data = &self.data[n + 5..]; ret } // Everything else we can push right through _ => { - let ret = Some(Instruction::Op(opcodes::All::from(self.data[0]))); + let ret = Some(Ok(Instruction::Op(opcodes::All::from(self.data[0])))); self.data = &self.data[1..]; ret } @@ -676,8 +685,8 @@ impl Default for Builder { impl From> for Builder { fn from(v: Vec) -> Builder { let script = Script(v.into_boxed_slice()); - let last_op = match script.iter(false).last() { - Some(Instruction::Op(op)) => Some(op), + let last_op = match script.instructions().last() { + Some(Ok(Instruction::Op(op))) => Some(op), _ => None, }; Builder(script.into_bytes(), last_op) @@ -1009,31 +1018,31 @@ mod test { let minimal = hex_script!("0169b2"); // minimal let nonminimal_alt = hex_script!("026900b2"); // non-minimal number but minimal push (should be OK) - let v_zero: Vec = zero.iter(true).collect(); - let v_zeropush: Vec = zeropush.iter(true).collect(); + let v_zero: Result, Error> = zero.instructions_minimal().collect(); + let v_zeropush: Result, Error> = zeropush.instructions_minimal().collect(); - let v_min: Vec = minimal.iter(true).collect(); - let v_nonmin: Vec = nonminimal.iter(true).collect(); - let v_nonmin_alt: Vec = nonminimal_alt.iter(true).collect(); - let slop_v_min: Vec = minimal.iter(false).collect(); - let slop_v_nonmin: Vec = nonminimal.iter(false).collect(); - let slop_v_nonmin_alt: Vec = nonminimal_alt.iter(false).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 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(); assert_eq!( - v_zero, + v_zero.unwrap(), vec![ Instruction::PushBytes(&[]), ] ); assert_eq!( - v_zeropush, + v_zeropush.unwrap(), vec![ Instruction::PushBytes(&[0]), ] ); assert_eq!( - v_min, + v_min.clone().unwrap(), vec![ Instruction::PushBytes(&[105]), Instruction::Op(opcodes::OP_NOP3), @@ -1041,23 +1050,21 @@ mod test { ); assert_eq!( - v_nonmin, - vec![ - Instruction::Error(Error::NonMinimalPush), - ] + v_nonmin.err().unwrap(), + Error::NonMinimalPush ); assert_eq!( - v_nonmin_alt, + v_nonmin_alt.clone().unwrap(), vec![ Instruction::PushBytes(&[105, 0]), Instruction::Op(opcodes::OP_NOP3), ] ); - assert_eq!(v_min, slop_v_min); - assert_eq!(v_min, slop_v_nonmin); - assert_eq!(v_nonmin_alt, slop_v_nonmin_alt); + assert_eq!(v_min.clone().unwrap(), slop_v_min.unwrap()); + assert_eq!(v_min.unwrap(), slop_v_nonmin.unwrap()); + assert_eq!(v_nonmin_alt.unwrap(), slop_v_nonmin_alt.unwrap()); } #[test] diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 539944dd..345e9bc4 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -227,8 +227,11 @@ pub fn untemplate(script: &script::Script) -> Result<(Template, Vec), } let mut mode = Mode::SeekingKeys; - for instruction in script.iter(false) { - match instruction { + for instruction in script.instructions() { + if let Err(e) = instruction { + return Err(Error::Script(e)); + } + match instruction.unwrap() { script::Instruction::PushBytes(data) => { let n = data.len(); ret = match PublicKey::from_slice(data) { @@ -275,7 +278,6 @@ pub fn untemplate(script: &script::Script) -> Result<(Template, Vec), } ret = ret.push_opcode(op); } - script::Instruction::Error(e) => { return Err(Error::Script(e)); } } } Ok((Template::from(&ret[..]), retkeys)) From 41e447172175a55c1e1274179486fc58fe82a84e Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 8 Apr 2020 14:35:48 +0300 Subject: [PATCH 0038/1740] Remove alloc when hashing sighash --- src/blockdata/transaction.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 99b87f22..f24d8727 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -33,7 +33,7 @@ use util::endian; use blockdata::constants::WITNESS_SCALE_FACTOR; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; -use consensus::{encode, serialize, Decodable, Encodable}; +use consensus::{encode, Decodable, Encodable}; use hash_types::*; use VarInt; @@ -378,9 +378,12 @@ impl Transaction { _ => unreachable!() }; // hash the result - let mut raw_vec = serialize(&tx); - raw_vec.extend_from_slice(&endian::u32_to_array_le(sighash_u32)); - SigHash::hash(&raw_vec) + // TODO: Sanity assert that consensus_encode returned length matches the hashed length in the hasher. + let sighash_arr = endian::u32_to_array_le(sighash_u32); + let mut engine = SigHash::engine(); + tx.consensus_encode(&mut engine).unwrap(); + sighash_arr.consensus_encode(&mut engine).unwrap(); + SigHash::from_engine(engine) } /// Gets the "weight" of this transaction, as defined by BIP141. For transactions with an empty @@ -441,7 +444,7 @@ impl Transaction { /// The lambda spent should not return the same TxOut twice! pub fn verify(&self, mut spent: S) -> Result<(), script::Error> where S: FnMut(&OutPoint) -> Option { - let tx = serialize(&*self); + let tx = encode::serialize(&*self); for (idx, input) in self.input.iter().enumerate() { if let Some(output) = spent(&input.previous_output) { output.script_pubkey.verify(idx, output.value, tx.as_slice())?; From 25cb3d3539306a075cf434bfe947e98e16a19a66 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 8 Apr 2020 15:01:47 +0300 Subject: [PATCH 0039/1740] Remove alloc when hashing for Bitcoin message signing format --- src/util/misc.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/util/misc.rs b/src/util/misc.rs index 2ee4fb0c..5a925e34 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -16,9 +16,9 @@ //! //! Various utility functions -use hashes::{sha256d, Hash}; +use hashes::{sha256d, Hash, HashEngine}; use blockdata::opcodes; -use consensus::encode; +use consensus::{encode, Encodable}; static MSG_SIGN_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n"; @@ -59,14 +59,15 @@ pub fn script_find_and_remove(haystack: &mut Vec, needle: &[u8]) -> usize { /// Hash message for signature using Bitcoin's message signing format pub fn signed_msg_hash(msg: &str) -> sha256d::Hash { - sha256d::Hash::hash( - &[ - MSG_SIGN_PREFIX, - &encode::serialize(&encode::VarInt(msg.len() as u64)), - msg.as_bytes(), - ] - .concat(), - ) + let msg_len = encode::VarInt(msg.len() as u64); + + // TODO: Sanity assert that consensus_encode returned length matches the hashed length in the hasher. + let mut engine = sha256d::Hash::engine(); + engine.input(MSG_SIGN_PREFIX); + msg_len.consensus_encode(&mut engine).unwrap(); + engine.input(msg.as_bytes()); + + sha256d::Hash::from_engine(engine) } #[cfg(test)] From 654232a3dc4d7cbf42eb32d9aa9ce4a489ccd081 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Sun, 29 Mar 2020 16:49:48 +0300 Subject: [PATCH 0040/1740] Deprecate Error::description --- src/blockdata/script.rs | 20 +++++++++---------- src/blockdata/transaction.rs | 9 ++------- src/consensus/encode.rs | 3 ++- src/network/mod.rs | 12 +++++------- src/util/address.rs | 5 +++-- src/util/amount.rs | 28 ++++++++++---------------- src/util/base58.rs | 13 +++--------- src/util/bip158.rs | 6 ++---- src/util/bip32.rs | 9 +-------- src/util/contracthash.rs | 13 +++--------- src/util/key.rs | 2 +- src/util/mod.rs | 11 ++++------- src/util/psbt/error.rs | 38 +++++++++++++----------------------- 13 files changed, 60 insertions(+), 109 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index d71b936c..bbcf732b 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -105,15 +105,7 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(error::Error::description(self)) - } -} - -impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { None } - - fn description(&self) -> &'static str { - match *self { + let str = match *self { Error::NonMinimalPush => "non-minimal datapush", Error::EarlyEndOfScript => "unexpected end of script", Error::NumericOverflow => "numeric overflow (number on stack larger than 4 bytes)", @@ -123,7 +115,15 @@ impl error::Error for Error { Error::UnknownSpentOutput(ref _point) => "unknown spent output Transaction::verify()", #[cfg(feature="bitcoinconsensus")] Error::SerializationError => "can not serialize the spending transaction in Transaction::verify()", - } + }; + f.write_str(str) + } +} + +#[allow(deprecated)] +impl error::Error for Error { + fn description(&self) -> &str { + "description() is deprecated; use Display" } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 6e83f97b..d66dd2d3 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -128,15 +128,10 @@ impl fmt::Display for ParseOutPointError { } } +#[allow(deprecated)] impl ::std::error::Error for ParseOutPointError { fn description(&self) -> &str { - match *self { - ParseOutPointError::Txid(_) => "TXID parse error", - ParseOutPointError::Vout(_) => "vout parse error", - ParseOutPointError::Format => "outpoint format error", - ParseOutPointError::TooLong => "size error", - ParseOutPointError::VoutNotCanonical => "vout canonical error", - } + "description() is deprecated; use Display" } fn cause(&self) -> Option<&::std::error::Error> { diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 9bd8fb45..4e22e810 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -109,6 +109,7 @@ impl fmt::Display for Error { } } +#[allow(deprecated)] impl error::Error for Error { fn cause(&self) -> Option<&error::Error> { match *self { @@ -127,7 +128,7 @@ impl error::Error for Error { } fn description(&self) -> &str { - "Bitcoin encoding error" + "description() is deprecated; use Display" } } diff --git a/src/network/mod.rs b/src/network/mod.rs index 4ba6d16a..de8ee96a 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -14,7 +14,7 @@ //! Network Support //! -//! This module defines support for (de)serialization and network transport +//! This module defines support for (de)serialization and network transport //! of Bitcoin data and network messages. //! @@ -47,7 +47,8 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Io(ref e) => fmt::Display::fmt(e, f), - Error::SocketMutexPoisoned | Error::SocketNotConnectedToPeer => f.write_str(error::Error::description(self)), + Error::SocketMutexPoisoned => f.write_str("socket mutex was poisoned"), + Error::SocketNotConnectedToPeer => f.write_str("not connected to peer"), } } } @@ -59,13 +60,10 @@ impl From for Error { } } +#[allow(deprecated)] impl error::Error for Error { fn description(&self) -> &str { - match *self { - Error::Io(ref e) => e.description(), - Error::SocketMutexPoisoned => "socket mutex was poisoned", - Error::SocketNotConnectedToPeer => "not connected to peer", - } + "description() is deprecated; use Display" } fn cause(&self) -> Option<&error::Error> { diff --git a/src/util/address.rs b/src/util/address.rs index 7715736f..ac9d3625 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -91,6 +91,7 @@ impl fmt::Display for Error { } } +#[allow(deprecated)] impl ::std::error::Error for Error { fn cause(&self) -> Option<&::std::error::Error> { match *self { @@ -100,8 +101,8 @@ impl ::std::error::Error for Error { } } - fn description(&self) -> &'static str { - "std::error::Error::description is deprecated" + fn description(&self) -> &str { + "description() is deprecated; use Display" } } diff --git a/src/util/amount.rs b/src/util/amount.rs index 1bbb6ec6..cd71877b 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -102,30 +102,22 @@ pub enum ParseAmountError { impl fmt::Display for ParseAmountError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let desc = ::std::error::Error::description(self); match *self { - ParseAmountError::InvalidCharacter(c) => write!(f, "{}: {}", desc, c), - ParseAmountError::UnknownDenomination(ref d) => write!(f, "{}: {}", desc, d), - _ => f.write_str(desc), + ParseAmountError::Negative => f.write_str("amount is negative"), + ParseAmountError::TooBig => f.write_str("amount is too big"), + ParseAmountError::TooPrecise => f.write_str("amount has a too high precision"), + 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), } } } +#[allow(deprecated)] impl error::Error for ParseAmountError { - fn cause(&self) -> Option<&error::Error> { - None - } - - fn description(&self) -> &'static str { - match *self { - ParseAmountError::Negative => "amount is negative", - ParseAmountError::TooBig => "amount is too big", - ParseAmountError::TooPrecise => "amount has a too high precision", - ParseAmountError::InvalidFormat => "invalid number format", - ParseAmountError::InputTooLarge => "input string was too large", - ParseAmountError::InvalidCharacter(_) => "invalid character in input", - ParseAmountError::UnknownDenomination(_) => "unknown denomination", - } + fn description(&self) -> &str { + "description() is deprecated; use Display" } } diff --git a/src/util/base58.rs b/src/util/base58.rs index 68a0a2b7..5eb2750f 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -52,17 +52,10 @@ impl fmt::Display for Error { } } +#[allow(deprecated)] impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { None } - fn description(&self) -> &'static str { - match *self { - Error::BadByte(_) => "invalid b58 character", - Error::BadChecksum(_, _) => "invalid b58ck checksum", - Error::InvalidLength(_) => "invalid length for b58 type", - Error::InvalidVersion(_) => "invalid version for b58 type", - Error::TooShort(_) => "b58ck data less than 4 bytes", - Error::Other(_) => "unknown b58 error" - } + fn description(&self) -> &str { + "description() is deprecated; use Display" } } diff --git a/src/util/bip158.rs b/src/util/bip158.rs index b7154bfe..60e4a032 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -73,12 +73,10 @@ pub enum Error { Io(io::Error), } +#[allow(deprecated)] impl error::Error for Error { fn description(&self) -> &str { - match *self { - Error::UtxoMissing(_) => "unresolved UTXO", - Error::Io(_) => "IO Error" - } + "description() is deprecated; use Display" } } diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 470e59e1..d8e49223 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -391,14 +391,7 @@ impl error::Error for Error { } fn description(&self) -> &str { - match *self { - Error::CannotDeriveFromHardenedKey => "cannot derive hardened key from public key", - Error::Ecdsa(ref e) => error::Error::description(e), - Error::InvalidChildNumber(_) => "child number is invalid", - Error::RngError(_) => "rng error", - Error::InvalidChildNumberFormat => "invalid child number format", - Error::InvalidDerivationPathFormat => "invalid derivation path format", - } + "description() is deprecated; use Display" } } diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 539944dd..15df0a57 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -69,6 +69,7 @@ impl fmt::Display for Error { } } +#[allow(deprecated)] impl error::Error for Error { fn cause(&self) -> Option<&error::Error> { match *self { @@ -78,16 +79,8 @@ impl error::Error for Error { } } - fn description(&self) -> &'static str { - match *self { - Error::Secp(_) => "libsecp256k1 error", - Error::Script(_) => "script error", - Error::UncompressedKey => "encountered uncompressed secp public key", - Error::ExpectedKey => "expected key when deserializing script", - Error::ExpectedChecksig => "expected OP_*CHECKSIG* when deserializing script", - Error::TooFewKeys(_) => "too few keys for template", - Error::TooManyKeys(_) => "too many keys for template" - } + fn description(&self) -> &str { + "description() is deprecated; use Display" } } diff --git a/src/util/key.rs b/src/util/key.rs index c9f81faf..89946be7 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -52,7 +52,7 @@ impl error::Error for Error { } fn description(&self) -> &str { - "Bitcoin key error" + "description() is deprecated; use Display" } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 36ebc5ee..856757d8 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -77,11 +77,13 @@ impl fmt::Display for Error { match *self { Error::Encode(ref e) => fmt::Display::fmt(e, f), Error::Network(ref e) => fmt::Display::fmt(e, f), - Error::BlockBadProofOfWork | Error::BlockBadTarget => f.write_str(error::Error::description(self)), + Error::BlockBadProofOfWork => f.write_str("block target correct but not attained"), + Error::BlockBadTarget => f.write_str("block target incorrect"), } } } +#[allow(deprecated)] impl error::Error for Error { fn cause(&self) -> Option<&error::Error> { match *self { @@ -92,12 +94,7 @@ impl error::Error for Error { } fn description(&self) -> &str { - match *self { - Error::Encode(ref e) => e.description(), - Error::Network(ref e) => e.description(), - Error::BlockBadProofOfWork => "block target correct but not attained", - Error::BlockBadTarget => "block target incorrect", - } + "description() is deprecated; use Display" } } diff --git a/src/util/psbt/error.rs b/src/util/psbt/error.rs index 1f3cb928..15ab268d 100644 --- a/src/util/psbt/error.rs +++ b/src/util/psbt/error.rs @@ -53,35 +53,25 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::InvalidKey(ref rkey) => write!(f, "{}: {}", error::Error::description(self), rkey), - Error::DuplicateKey(ref rkey) => write!(f, "{}: {}", error::Error::description(self), rkey), - Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e.txid(), a.txid()), - Error::NonStandardSigHashType(ref sht) => write!(f, "{}: {}", error::Error::description(self), sht), - Error::InvalidMagic - | Error::InvalidSeparator - | Error::UnsignedTxHasScriptSigs - | Error::UnsignedTxHasScriptWitnesses - | Error::MustHaveUnsignedTx - | Error::NoMorePairs => f.write_str(error::Error::description(self)) + Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), + 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::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::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"), } } } +#[allow(deprecated)] impl error::Error for Error { fn description(&self) -> &str { - match *self { - Error::InvalidMagic => "invalid magic", - Error::InvalidSeparator => "invalid separator", - Error::InvalidKey(..) => "invalid key", - Error::DuplicateKey(..) => "duplicate key", - Error::UnsignedTxHasScriptSigs => "the unsigned transaction has script sigs", - Error::UnsignedTxHasScriptWitnesses => "the unsigned transaction has script witnesses", - Error::MustHaveUnsignedTx => { - "partially signed transactions must have an unsigned transaction" - } - Error::NoMorePairs => "no more key-value pairs for this psbt map", - Error::UnexpectedUnsignedTx { .. } => "different unsigned transaction", - Error::NonStandardSigHashType(..) => "non-standard sighash type", - } + "description() is deprecated; use Display" } } From 81c061a68c62f31fedd35fa68243b5952ef42f86 Mon Sep 17 00:00:00 2001 From: Jake Rawsthorne Date: Tue, 14 Apr 2020 14:11:44 +0100 Subject: [PATCH 0041/1740] Change WitnessTransaction inv type to use txid --- src/network/message_blockdata.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index e2795ef0..60320749 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -24,7 +24,7 @@ use hashes::sha256d; use network::constants; use consensus::encode::{self, Decodable, Encodable}; -use hash_types::{BlockHash, Txid, Wtxid}; +use hash_types::{BlockHash, Txid}; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)] @@ -36,7 +36,7 @@ pub enum Inventory { /// Block Block(BlockHash), /// Witness Transaction - WitnessTransaction(Wtxid), + WitnessTransaction(Txid), /// Witness Block WitnessBlock(BlockHash), } From 604f1aa56e40254ba530db3c58a7eb3a75c6a0e4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 30 Apr 2020 19:20:28 -0400 Subject: [PATCH 0042/1740] Add fuzz target comparing native u128 to our Uint type --- fuzz/Cargo.toml | 4 ++ fuzz/fuzz_targets/uint128_fuzz.rs | 101 ++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 fuzz/fuzz_targets/uint128_fuzz.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 4b3941da..a5addd67 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -51,3 +51,7 @@ path = "fuzz_targets/deserialize_psbt.rs" [[bin]] name = "deser_net_msg" path = "fuzz_targets/deser_net_msg.rs" + +[[bin]] +name = "uint128_fuzz" +path = "fuzz_targets/uint128_fuzz.rs" diff --git a/fuzz/fuzz_targets/uint128_fuzz.rs b/fuzz/fuzz_targets/uint128_fuzz.rs new file mode 100644 index 00000000..ce00c350 --- /dev/null +++ b/fuzz/fuzz_targets/uint128_fuzz.rs @@ -0,0 +1,101 @@ +extern crate bitcoin; +use std::str::FromStr; + +fn do_test(data: &[u8]) { + macro_rules! read_ints { + ($start: expr) => { { + let mut native = 0; + for c in data[$start..$start + 16].iter() { + native <<= 8; + native |= (*c) as u128; + } + // Note BE: + let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]); + (native, uint128) + } } + } + macro_rules! check_eq { + ($native: expr, $uint: expr) => { { + assert_eq!(&[$native as u64, ($native >> 8*8) as u64], $uint.as_bytes()); + } } + } + + if data.len() != 16*2 + 1 { return; } + let (a_native, a) = read_ints!(0); + + // Checks using only a: + for i in 0..128 { + check_eq!(a_native << i, a << i); + check_eq!(a_native >> i, a >> i); + } + assert_eq!(a_native as u64, a.low_u64()); + assert_eq!(a_native as u32, a.low_u32()); + assert_eq!(128 - a_native.leading_zeros() as usize, a.bits()); + assert_eq!(a_native as u64, bitcoin::util::uint::Uint128::from_u64(a_native as u64).unwrap().low_u64()); + + // Checks with two numbers: + let (b_native, b) = read_ints!(16); + + check_eq!(a_native.wrapping_add(b_native), a + b); + check_eq!(a_native.wrapping_sub(b_native), a - b); + if b_native != 0 { + check_eq!(a_native.wrapping_div(b_native), a / b); + } + check_eq!(a_native.wrapping_mul(b_native), a * b); + check_eq!(a_native & b_native, a & b); + check_eq!(a_native | b_native, a | b); + check_eq!(a_native ^ b_native, a ^ b); + check_eq!(a_native.wrapping_mul((b_native as u32) as u128), a.mul_u32(b.low_u32())); + + assert_eq!(a_native > b_native, a > b); + assert_eq!(a_native >= b_native, a >= b); + assert_eq!(a_native < b_native, a < b); + assert_eq!(a_native <= b_native, a <= b); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(&data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(test)] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'...b'F' => b |= c - b'A' + 10, + b'a'...b'f' => b |= c - b'a' + 10, + b'0'...b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("100000a70000000000000000000000000000000000000000000000000000000054", &mut a); + super::do_test(&a); + } +} From af31017eb19cadc8072a5efb7cf3f596b2d40bab Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Sun, 12 Apr 2020 19:00:55 +0300 Subject: [PATCH 0043/1740] Remove the cursor overhead, write is implemented on vec these days --- src/blockdata/transaction.rs | 3 +-- src/consensus/encode.rs | 6 +++--- src/util/misc.rs | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f24d8727..1317032d 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -378,10 +378,9 @@ impl Transaction { _ => unreachable!() }; // hash the result - // TODO: Sanity assert that consensus_encode returned length matches the hashed length in the hasher. - let sighash_arr = endian::u32_to_array_le(sighash_u32); let mut engine = SigHash::engine(); tx.consensus_encode(&mut engine).unwrap(); + let sighash_arr = endian::u32_to_array_le(sighash_u32); sighash_arr.consensus_encode(&mut engine).unwrap(); SigHash::from_engine(engine) } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index e3a38396..d6dbcb4b 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -149,10 +149,10 @@ impl From for Error { /// Encode an object into a vector pub fn serialize(data: &T) -> Vec { - let mut encoder = Cursor::new(vec![]); + let mut encoder = Vec::new(); let len = data.consensus_encode(&mut encoder).unwrap(); - assert_eq!(len, encoder.get_ref().len()); - encoder.into_inner() + assert_eq!(len, encoder.len()); + encoder } /// Encode an object into a hex-encoded string diff --git a/src/util/misc.rs b/src/util/misc.rs index 5a925e34..98e0f709 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -59,11 +59,10 @@ pub fn script_find_and_remove(haystack: &mut Vec, needle: &[u8]) -> usize { /// Hash message for signature using Bitcoin's message signing format pub fn signed_msg_hash(msg: &str) -> sha256d::Hash { - let msg_len = encode::VarInt(msg.len() as u64); - // TODO: Sanity assert that consensus_encode returned length matches the hashed length in the hasher. let mut engine = sha256d::Hash::engine(); engine.input(MSG_SIGN_PREFIX); + let msg_len = encode::VarInt(msg.len() as u64); msg_len.consensus_encode(&mut engine).unwrap(); engine.input(msg.as_bytes()); From 59b5a73a553fe4d49d484196aa0bee805a2f030d Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Sat, 23 May 2020 23:20:19 +0100 Subject: [PATCH 0044/1740] Fix typo and minor formatting in address::Error --- src/util/address.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/util/address.rs b/src/util/address.rs index dcb418d5..d1418ed8 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -73,15 +73,12 @@ impl fmt::Display for Error { Error::Bech32(ref e) => write!(f, "bech32: {}", e), Error::EmptyBech32Payload => write!(f, "the bech32 payload was empty"), Error::InvalidWitnessVersion(v) => write!(f, "invalid witness script version: {}", v), - Error::InvalidWitnessProgramLength(l) => write!( - f, - "the witness program must be between 2 and 40 bytes in length: lengh={}", - l + Error::InvalidWitnessProgramLength(l) => write!(f, + "the witness program must be between 2 and 40 bytes in length: length={}", l, + ), + Error::InvalidSegwitV0ProgramLength(l) => write!(f, + "a v0 witness program must be either of length 20 or 32 bytes: length={}", l, ), - Error::InvalidSegwitV0ProgramLength(l) => write!( - f, - "a v0 witness program must be either of length 20 or 32 bytes: length={}", - l ), } } From ed9bf41ff5316517443fe99a706af0fc975f3658 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Sat, 23 May 2020 23:20:46 +0100 Subject: [PATCH 0045/1740] Don't allow uncompressed pks in witness addresses --- src/util/address.rs | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/util/address.rs b/src/util/address.rs index d1418ed8..97748ac0 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -64,6 +64,8 @@ pub enum Error { InvalidWitnessProgramLength(usize), /// A v0 witness program must be either of length 20 or 32. InvalidSegwitV0ProgramLength(usize), + /// An uncompressed pubkey was used where it is not allowed. + UncompressedPubkey, } impl fmt::Display for Error { @@ -79,6 +81,8 @@ impl fmt::Display for Error { Error::InvalidSegwitV0ProgramLength(l) => write!(f, "a v0 witness program must be either of length 20 or 32 bytes: length={}", l, ), + Error::UncompressedPubkey => write!(f, + "an uncompressed pubkey was used where it is not allowed", ), } } @@ -257,22 +261,34 @@ impl Address { /// Create a witness pay to public key address from a public key /// This is the native segwit address type for an output redeemable with a single signature - pub fn p2wpkh(pk: &key::PublicKey, network: Network) -> Address { + /// + /// Will only return an Error when an uncompressed public key is provided. + pub fn p2wpkh(pk: &key::PublicKey, network: Network) -> Result { + if !pk.compressed { + return Err(Error::UncompressedPubkey); + } + let mut hash_engine = WPubkeyHash::engine(); pk.write_into(&mut hash_engine); - Address { + Ok(Address { network: network, payload: Payload::WitnessProgram { version: bech32::u5::try_from_u8(0).expect("0<32"), program: WPubkeyHash::from_engine(hash_engine)[..].to_vec(), }, - } + }) } /// Create a pay to script address that embeds a witness pay to public key /// This is a segwit address type that looks familiar (as p2sh) to legacy clients - pub fn p2shwpkh(pk: &key::PublicKey, network: Network) -> Address { + /// + /// Will only return an Error when an uncompressed public key is provided. + pub fn p2shwpkh(pk: &key::PublicKey, network: Network) -> Result { + if !pk.compressed { + return Err(Error::UncompressedPubkey); + } + let mut hash_engine = WPubkeyHash::engine(); pk.write_into(&mut hash_engine); @@ -280,10 +296,10 @@ impl Address { .push_int(0) .push_slice(&WPubkeyHash::from_engine(hash_engine)[..]); - Address { + Ok(Address { network: network, payload: Payload::ScriptHash(ScriptHash::hash(builder.into_script().as_bytes())), - } + }) } /// Create a witness pay to script hash address @@ -587,11 +603,15 @@ mod tests { #[test] fn test_p2wpkh() { // stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20 - let key = hex_key!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"); - let addr = Address::p2wpkh(&key, Bitcoin); + 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)); roundtrips(&addr); + + // Test uncompressed pubkey + key.compressed = false; + assert_eq!(Address::p2wpkh(&key, Bitcoin), Err(Error::UncompressedPubkey)); } #[test] @@ -610,11 +630,15 @@ mod tests { #[test] fn test_p2shwpkh() { // stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01 - let key = hex_key!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"); - let addr = Address::p2shwpkh(&key, Bitcoin); + 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)); roundtrips(&addr); + + // Test uncompressed pubkey + key.compressed = false; + assert_eq!(Address::p2wpkh(&key, Bitcoin), Err(Error::UncompressedPubkey)); } #[test] From ed76e0823b90abfa66b4cffa0e4b76a13b9c9ca0 Mon Sep 17 00:00:00 2001 From: Tao Wei Date: Wed, 3 Jun 2020 17:17:13 +0800 Subject: [PATCH 0046/1740] Remove duplicate code Duplicated with L38 --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4cb27089..4804f697 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,6 @@ #![deny(dead_code)] #![deny(unused_imports)] #![deny(missing_docs)] -#![forbid(unsafe_code)] // In general, rust is absolutely horrid at supporting users doing things like, // for example, compiling Rust code for real environments. Disable useless lints From 139fc02592231a5cd6e5623787c17b6c51e14bbb Mon Sep 17 00:00:00 2001 From: Sebastian Geisler Date: Mon, 1 Jun 2020 14:44:39 +0200 Subject: [PATCH 0047/1740] Fix #430: ruy rust 1.22 inccompatibility --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index fe90e8e3..4374ce0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,5 @@ serde_derive = "<1.0.99" serde_json = "<1.0.45" serde_test = "1" secp256k1 = { version = "0.17.1", features = ["rand-std"] } +# We need to pin ryu (transitive dep from serde_json) to stay compatible with Rust 1.22.0 +ryu = "<1.0.5" From e8cecfe1d3cd6e9945e8c540121e4baf865d28fe Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sun, 31 May 2020 23:22:25 +0200 Subject: [PATCH 0048/1740] Add `BlockHeader::u256_from_compact_target` function This implements the counterparty to BlockHeader::compact_target_from_u256, to convert a compact u32 to a Uint256. --- src/blockdata/block.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 600e22f2..64392a10 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -152,16 +152,31 @@ impl BlockHeader { /// Computes the target [0, T] that a blockhash must land in to be valid pub fn target(&self) -> Uint256 { + Self::u256_from_compact_target(self.bits) + } + + /// Computes the target value in Uint256 format, from a compact representation. + /// + /// ``` + /// use bitcoin::blockdata::block::BlockHeader; + /// + /// assert_eq!(0x1d00ffff, + /// BlockHeader::compact_target_from_u256( + /// &BlockHeader::u256_from_compact_target(0x1d00ffff) + /// ) + /// ); + /// ``` + pub fn u256_from_compact_target(bits: u32) -> Uint256 { // This is a floating-point "compact" encoding originally used by // OpenSSL, which satoshi put into consensus code, so we're stuck // with it. The exponent needs to have 3 subtracted from it, hence // this goofy decoding code: let (mant, expt) = { - let unshifted_expt = self.bits >> 24; + let unshifted_expt = bits >> 24; if unshifted_expt <= 3 { - ((self.bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) + ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) } else { - (self.bits & 0xFFFFFF, 8 * ((self.bits >> 24) - 3)) + (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3)) } }; From 9cb5d2e711589d118264732c4c73faec72573179 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Mon, 1 Jun 2020 21:26:52 +0200 Subject: [PATCH 0049/1740] Link type in rustdoc --- src/blockdata/block.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 64392a10..5a415594 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -155,7 +155,9 @@ impl BlockHeader { Self::u256_from_compact_target(self.bits) } - /// Computes the target value in Uint256 format, from a compact representation. + /// Computes the target value in [`Uint256`] format, from a compact representation. + /// + /// [`Uint256`]: ../../util/uint/struct.Uint256.html /// /// ``` /// use bitcoin::blockdata::block::BlockHeader; From a3bb03eeb9dfdf29ad13135766b704127c8b5322 Mon Sep 17 00:00:00 2001 From: Sebastian Geisler Date: Wed, 3 Jun 2020 17:44:42 +0200 Subject: [PATCH 0050/1740] Derive more traits to use DerivationPath in rust-miniscript --- src/util/bip32.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 2e8103e7..5d66841b 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -64,7 +64,7 @@ pub struct ExtendedPrivKey { serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key"); /// Extended public key -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] pub struct ExtendedPubKey { /// The network this key is to be used on pub network: Network, @@ -82,7 +82,7 @@ pub struct ExtendedPubKey { serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key"); /// A child number for a derived key -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] pub enum ChildNumber { /// Non-hardened key Normal { @@ -209,7 +209,7 @@ impl serde::Serialize for ChildNumber { } /// A BIP-32 derivation path. -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] pub struct DerivationPath(Vec); impl_index_newtype!(DerivationPath, ChildNumber); serde_string_impl!(DerivationPath, "a BIP-32 derivation path"); From 7588b211ff51d58315b402a0e54e627764a49294 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Thu, 18 Jun 2020 18:36:09 +0200 Subject: [PATCH 0051/1740] Adding Rem op (%) to Uint128 & Uint256 types --- src/util/uint.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/util/uint.rs b/src/util/uint.rs index 9456df0a..e05e9b99 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -166,6 +166,15 @@ macro_rules! construct_uint { } } + impl ::std::ops::Rem<$name> for $name { + type Output = $name; + + fn rem(self, other: $name) -> $name { + let times = self / other; + self - (times * other) + } + } + impl $crate::util::BitArray for $name { #[inline] fn bit(&self, index: usize) -> bool { @@ -479,6 +488,14 @@ mod tests { Uint256::from_u64(21).unwrap()); let div = mult / Uint256::from_u64(300).unwrap(); assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); + + assert_eq!(Uint256::from_u64(105).unwrap() % Uint256::from_u64(5).unwrap(), + Uint256::from_u64(0).unwrap()); + assert_eq!(Uint256::from_u64(35498456).unwrap() % Uint256::from_u64(3435).unwrap(), + Uint256::from_u64(1166).unwrap()); + let rem_src = mult * Uint256::from_u64(39842).unwrap() + Uint256::from_u64(9054).unwrap(); + assert_eq!(rem_src % Uint256::from_u64(39842).unwrap(), + Uint256::from_u64(9054).unwrap()); // TODO: bit inversion } From 19f88212afcdffbf6c14c21441e3474faebb5650 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 21 Jul 2020 14:54:56 +0200 Subject: [PATCH 0052/1740] Fuzz tests for u128 modulo division --- fuzz/fuzz_targets/uint128_fuzz.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/fuzz/fuzz_targets/uint128_fuzz.rs b/fuzz/fuzz_targets/uint128_fuzz.rs index ce00c350..11b2b620 100644 --- a/fuzz/fuzz_targets/uint128_fuzz.rs +++ b/fuzz/fuzz_targets/uint128_fuzz.rs @@ -40,6 +40,7 @@ fn do_test(data: &[u8]) { check_eq!(a_native.wrapping_sub(b_native), a - b); if b_native != 0 { check_eq!(a_native.wrapping_div(b_native), a / b); + check_eq!(a_native.wrapping_rem(b_native), a % b); } check_eq!(a_native.wrapping_mul(b_native), a * b); check_eq!(a_native & b_native, a & b); From 3a5e8d85043501c8dc826dafdddafd7806f99b29 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 25 Jan 2020 05:19:46 +0100 Subject: [PATCH 0053/1740] Namespace hygiene for internal macros --- src/internal_macros.rs | 159 +++++++++++++++++++++-------------------- src/util/bip32.rs | 2 +- 2 files changed, 82 insertions(+), 79 deletions(-) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index ef0d815f..6baae6b8 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -18,31 +18,32 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( - impl ::consensus::Encodable for $thing { + impl $crate::consensus::Encodable for $thing { #[inline] - fn consensus_encode( + fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; $(len += self.$field.consensus_encode(&mut s)?;)+ Ok(len) } } - impl ::consensus::Decodable for $thing { + impl $crate::consensus::Decodable for $thing { #[inline] - fn consensus_decode( + fn consensus_decode( mut d: D, - ) -> Result<$thing, ::consensus::encode::Error> { + ) -> Result<$thing, $crate::consensus::encode::Error> { Ok($thing { - $($field: ::consensus::Decodable::consensus_decode(&mut d)?),+ + $($field: $crate::consensus::Decodable::consensus_decode(&mut d)?),+ }) } } ); } +/// Implements standard array methods for a given wrapper type macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:expr) => { impl $thing { @@ -81,7 +82,7 @@ macro_rules! impl_array_newtype { pub fn into_bytes(self) -> [$ty; $len] { self.0 } } - impl<'a> From<&'a [$ty]> for $thing { + impl<'a> $crate::std::convert::From<&'a [$ty]> for $thing { fn from(data: &'a [$ty]) -> $thing { assert_eq!(data.len(), $len); let mut ret = [0; $len]; @@ -90,7 +91,7 @@ macro_rules! impl_array_newtype { } } - impl ::std::ops::Index for $thing { + impl $crate::std::ops::Index for $thing { type Output = $ty; #[inline] @@ -102,57 +103,57 @@ macro_rules! impl_array_newtype { impl_index_newtype!($thing, $ty); - impl PartialEq for $thing { + impl $crate::std::cmp::PartialEq for $thing { #[inline] fn eq(&self, other: &$thing) -> bool { &self[..] == &other[..] } } - impl Eq for $thing {} + impl $crate::std::cmp::Eq for $thing {} - impl PartialOrd for $thing { + impl $crate::std::cmp::PartialOrd for $thing { #[inline] - fn partial_cmp(&self, other: &$thing) -> Option<::std::cmp::Ordering> { + fn partial_cmp(&self, other: &$thing) -> Option<$crate::std::cmp::Ordering> { Some(self.cmp(&other)) } } - impl Ord for $thing { + impl $crate::std::cmp::Ord for $thing { #[inline] - fn cmp(&self, other: &$thing) -> ::std::cmp::Ordering { + fn cmp(&self, other: &$thing) -> $crate::std::cmp::Ordering { // manually implement comparison to get little-endian ordering // (we need this for our numeric types; non-numeric ones shouldn't // be ordered anyway except to put them in BTrees or whatever, and // they don't care how we order as long as we're consistent). for i in 0..$len { - if self[$len - 1 - i] < other[$len - 1 - i] { return ::std::cmp::Ordering::Less; } - if self[$len - 1 - i] > other[$len - 1 - i] { return ::std::cmp::Ordering::Greater; } + if self[$len - 1 - i] < other[$len - 1 - i] { return $crate::std::cmp::Ordering::Less; } + if self[$len - 1 - i] > other[$len - 1 - i] { return $crate::std::cmp::Ordering::Greater; } } - ::std::cmp::Ordering::Equal + $crate::std::cmp::Ordering::Equal } } #[cfg_attr(feature = "clippy", allow(expl_impl_clone_on_copy))] // we don't define the `struct`, we have to explicitly impl - impl Clone for $thing { + impl $crate::std::clone::Clone for $thing { #[inline] fn clone(&self) -> $thing { $thing::from(&self[..]) } } - impl Copy for $thing {} + impl $crate::std::marker::Copy for $thing {} - impl ::std::hash::Hash for $thing { + impl $crate::std::hash::Hash for $thing { #[inline] fn hash(&self, state: &mut H) - where H: ::std::hash::Hasher + where H: $crate::std::hash::Hasher { (&self[..]).hash(state); } fn hash_slice(data: &[$thing], state: &mut H) - where H: ::std::hash::Hasher + where H: $crate::std::hash::Hasher { for d in data.iter() { (&d[..]).hash(state); @@ -162,50 +163,52 @@ macro_rules! impl_array_newtype { } } +/// Implements debug formatting for a given wrapper type macro_rules! impl_array_newtype_show { ($thing:ident) => { - impl ::std::fmt::Debug for $thing { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + impl $crate::std::fmt::Debug for $thing { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { write!(f, concat!(stringify!($thing), "({:?})"), &self[..]) } } } } +/// Implements standard indexing methods for a given wrapper type macro_rules! impl_index_newtype { ($thing:ident, $ty:ty) => { - impl ::std::ops::Index<::std::ops::Range> for $thing { + impl $crate::std::ops::Index<$crate::std::ops::Range> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: ::std::ops::Range) -> &[$ty] { + fn index(&self, index: $crate::std::ops::Range) -> &[$ty] { &self.0[index] } } - impl ::std::ops::Index<::std::ops::RangeTo> for $thing { + impl $crate::std::ops::Index<$crate::std::ops::RangeTo> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: ::std::ops::RangeTo) -> &[$ty] { + fn index(&self, index: $crate::std::ops::RangeTo) -> &[$ty] { &self.0[index] } } - impl ::std::ops::Index<::std::ops::RangeFrom> for $thing { + impl $crate::std::ops::Index<$crate::std::ops::RangeFrom> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: ::std::ops::RangeFrom) -> &[$ty] { + fn index(&self, index: $crate::std::ops::RangeFrom) -> &[$ty] { &self.0[index] } } - impl ::std::ops::Index<::std::ops::RangeFull> for $thing { + impl $crate::std::ops::Index<$crate::std::ops::RangeFull> for $thing { type Output = [$ty]; #[inline] - fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] { + fn index(&self, _: $crate::std::ops::RangeFull) -> &[$ty] { &self.0[..] } } @@ -215,19 +218,19 @@ macro_rules! impl_index_newtype { macro_rules! display_from_debug { ($thing:ident) => { - impl ::std::fmt::Display for $thing { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(self, f) + impl $crate::std::fmt::Display for $thing { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> Result<(), $crate::std::fmt::Error> { + $crate::std::fmt::Debug::fmt(self, f) } } } } #[cfg(test)] -macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from( as ::hashes::hex::FromHex>::from_hex($s).unwrap()))); +macro_rules! hex_script (($s:expr) => ($crate::blockdata::script::Script::from( as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()))); #[cfg(test)] -macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(& as ::hashes::hex::FromHex>::from_hex($s).unwrap()).unwrap())); +macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(& as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()).unwrap())); macro_rules! serde_struct_impl { ($name:ident, $($fe:ident),*) => ( @@ -267,7 +270,7 @@ macro_rules! serde_struct_impl { impl<'de> $crate::serde::Deserialize<'de> for Enum { fn deserialize(deserializer: D) -> Result where - D: ::serde::de::Deserializer<'de>, + D: $crate::serde::de::Deserializer<'de>, { deserializer.deserialize_str(EnumVisitor) } @@ -623,8 +626,8 @@ macro_rules! serde_struct_human_string_impl { macro_rules! impl_bytes_newtype { ($t:ident, $len:expr) => ( - impl ::std::fmt::LowerHex for $t { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + impl $crate::std::fmt::LowerHex for $t { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { for &ch in self.0.iter() { write!(f, "{:02x}", ch)?; } @@ -632,17 +635,17 @@ macro_rules! impl_bytes_newtype { } } - impl ::std::fmt::Display for $t { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + impl $crate::std::fmt::Display for $t { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { fmt::LowerHex::fmt(self, f) } } - impl ::hashes::hex::FromHex for $t { - fn from_byte_iter(iter: I) -> Result - where I: Iterator> + - ExactSizeIterator + - DoubleEndedIterator, + impl $crate::hashes::hex::FromHex for $t { + fn from_byte_iter(iter: I) -> Result + where I: $crate::std::iter::Iterator> + + $crate::std::iter::ExactSizeIterator + + $crate::std::iter::DoubleEndedIterator, { if iter.len() == $len { let mut ret = [0; $len]; @@ -651,23 +654,23 @@ macro_rules! impl_bytes_newtype { } Ok($t(ret)) } else { - Err(::hashes::hex::Error::InvalidLength(2 * $len, 2 * iter.len())) + Err($crate::hashes::hex::Error::InvalidLength(2 * $len, 2 * iter.len())) } } } - impl ::std::str::FromStr for $t { - type Err = ::hashes::hex::Error; + impl $crate::std::str::FromStr for $t { + type Err = $crate::hashes::hex::Error; fn from_str(s: &str) -> Result { - hex::FromHex::from_hex(s) + $crate::hashes::hex::FromHex::from_hex(s) } } #[cfg(feature="serde")] - impl ::serde::Serialize for $t { - fn serialize(&self, s: S) -> Result { + impl $crate::serde::Serialize for $t { + fn serialize(&self, s: S) -> Result { if s.is_human_readable() { - s.serialize_str(&::hashes::hex::ToHex::to_hex(self)) + s.serialize_str(&$crate::hashes::hex::ToHex::to_hex(self)) } else { s.serialize_bytes(&self[..]) } @@ -675,34 +678,34 @@ macro_rules! impl_bytes_newtype { } #[cfg(feature="serde")] - impl<'de> ::serde::Deserialize<'de> for $t { - fn deserialize>(d: D) -> Result<$t, D::Error> { + impl<'de> $crate::serde::Deserialize<'de> for $t { + fn deserialize>(d: D) -> Result<$t, D::Error> { if d.is_human_readable() { struct HexVisitor; - impl<'de> ::serde::de::Visitor<'de> for HexVisitor { + impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor { type Value = $t; - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn expecting(&self, formatter: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { formatter.write_str("an ASCII hex string") } fn visit_bytes(self, v: &[u8]) -> Result where - E: ::serde::de::Error, + E: $crate::serde::de::Error, { - if let Ok(hex) = ::std::str::from_utf8(v) { - ::hashes::hex::FromHex::from_hex(hex).map_err(E::custom) + if let Ok(hex) = $crate::std::str::from_utf8(v) { + $crate::hashes::hex::FromHex::from_hex(hex).map_err(E::custom) } else { - return Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)); + return Err(E::invalid_value($crate::serde::de::Unexpected::Bytes(v), &self)); } } fn visit_str(self, v: &str) -> Result where - E: ::serde::de::Error, + E: $crate::serde::de::Error, { - ::hashes::hex::FromHex::from_hex(v).map_err(E::custom) + $crate::hashes::hex::FromHex::from_hex(v).map_err(E::custom) } } @@ -710,16 +713,16 @@ macro_rules! impl_bytes_newtype { } else { struct BytesVisitor; - impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { + impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor { type Value = $t; - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn expecting(&self, formatter: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { formatter.write_str("a bytestring") } fn visit_bytes(self, v: &[u8]) -> Result where - E: ::serde::de::Error, + E: $crate::serde::de::Error, { if v.len() != $len { Err(E::invalid_length(v.len(), &stringify!($len))) @@ -751,30 +754,30 @@ macro_rules! user_enum { $(#[$doc] $elem),* } - impl ::std::fmt::Debug for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + impl $crate::std::fmt::Debug for $name { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } - impl ::std::fmt::Display for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + impl $crate::std::fmt::Display for $name { + fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } - impl ::std::str::FromStr for $name { - type Err = ::std::io::Error; + impl $crate::std::str::FromStr for $name { + type Err = $crate::std::io::Error; #[inline] fn from_str(s: &str) -> Result { match s { $($txt => Ok($name::$elem)),*, - _ => Err(::std::io::Error::new( - ::std::io::ErrorKind::InvalidInput, + _ => Err($crate::std::io::Error::new( + $crate::std::io::ErrorKind::InvalidInput, format!("Unknown network (type {})", s), )), } @@ -831,10 +834,10 @@ macro_rules! user_enum { } #[cfg(feature = "serde")] - impl ::serde::Serialize for $name { + impl $crate::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where - S: ::serde::Serializer, + S: $crate::serde::Serializer, { serializer.collect_str(&self) } diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 2e8103e7..0288484a 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -22,7 +22,7 @@ use std::str::FromStr; #[cfg(feature = "serde")] use serde; use hash_types::XpubIdentifier; -use hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine}; use secp256k1::{self, Secp256k1}; use network::constants::Network; From f6aa8853a00eb679fd62f4fd94f0ad4f4cda406d Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 25 Jan 2020 05:21:57 +0100 Subject: [PATCH 0054/1740] Namespace hygiene for macros.rs --- src/util/psbt/macros.rs | 68 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 5109b94f..43970504 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -14,7 +14,7 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { ::consensus::deserialize(& as ::hashes::hex::FromHex>::from_hex($s).unwrap()) }; + ($s:expr) => { $crate::consensus::deserialize(& as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) }; } macro_rules! merge { @@ -34,9 +34,9 @@ macro_rules! impl_psbt_de_serialize { macro_rules! impl_psbt_deserialize { ($thing:ty) => { - impl ::util::psbt::serialize::Deserialize for $thing { - fn deserialize(bytes: &[u8]) -> Result { - ::consensus::deserialize(&bytes[..]) + impl $crate::util::psbt::serialize::Deserialize for $thing { + fn deserialize(bytes: &[u8]) -> Result { + $crate::consensus::deserialize(&bytes[..]) } } }; @@ -44,9 +44,9 @@ macro_rules! impl_psbt_deserialize { macro_rules! impl_psbt_serialize { ($thing:ty) => { - impl ::util::psbt::serialize::Serialize for $thing { + impl $crate::util::psbt::serialize::Serialize for $thing { fn serialize(&self) -> Vec { - ::consensus::serialize(self) + $crate::consensus::serialize(self) } } }; @@ -54,20 +54,20 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { - impl ::consensus::Encodable for $thing { - fn consensus_encode( + impl $crate::consensus::Encodable for $thing { + fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; - for pair in ::util::psbt::Map::get_pairs(self)? { - len += ::consensus::Encodable::consensus_encode( + for pair in $crate::util::psbt::Map::get_pairs(self)? { + len += $crate::consensus::Encodable::consensus_encode( &pair, &mut s, )?; } - Ok(len + ::consensus::Encodable::consensus_encode(&0x00_u8, s)?) + Ok(len + $crate::consensus::Encodable::consensus_encode(&0x00_u8, s)?) } } }; @@ -75,16 +75,16 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { - impl ::consensus::Decodable for $thing { - fn consensus_decode( + impl $crate::consensus::Decodable for $thing { + fn consensus_decode( mut d: D, - ) -> Result { - let mut rv: Self = ::std::default::Default::default(); + ) -> Result { + let mut rv: Self = $crate::std::default::Default::default(); loop { - match ::consensus::Decodable::consensus_decode(&mut d) { - Ok(pair) => ::util::psbt::Map::insert_pair(&mut rv, pair)?, - Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => return Ok(rv), + match $crate::consensus::Decodable::consensus_decode(&mut d) { + Ok(pair) => $crate::util::psbt::Map::insert_pair(&mut rv, pair)?, + Err($crate::consensus::encode::Error::Psbt($crate::util::psbt::Error::NoMorePairs)) => return Ok(rv), Err(e) => return Err(e), } } @@ -105,29 +105,27 @@ macro_rules! impl_psbt_insert_pair { ($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => { if $raw_key.key.is_empty() { if $slf.$unkeyed_name.is_none() { - let val: $unkeyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; - + let val: $unkeyed_value_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; $slf.$unkeyed_name = Some(val) } else { - return Err(::util::psbt::Error::DuplicateKey($raw_key).into()); + return Err($crate::util::psbt::Error::DuplicateKey($raw_key).into()); } } else { - return Err(::util::psbt::Error::InvalidKey($raw_key).into()); + return Err($crate::util::psbt::Error::InvalidKey($raw_key).into()); } }; ($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>) => { if !$raw_key.key.is_empty() { - let key_val: $keyed_key_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?; - + let key_val: $keyed_key_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?; match $slf.$keyed_name.entry(key_val) { ::std::collections::btree_map::Entry::Vacant(empty_key) => { - let val: $keyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; + let val: $keyed_value_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; empty_key.insert(val); } - ::std::collections::btree_map::Entry::Occupied(_) => return Err(::util::psbt::Error::DuplicateKey($raw_key).into()), + ::std::collections::btree_map::Entry::Occupied(_) => return Err($crate::util::psbt::Error::DuplicateKey($raw_key).into()), } } else { - return Err(::util::psbt::Error::InvalidKey($raw_key).into()); + return Err($crate::util::psbt::Error::InvalidKey($raw_key).into()); } }; } @@ -136,23 +134,23 @@ macro_rules! impl_psbt_insert_pair { macro_rules! impl_psbt_get_pair { ($rv:ident.push($slf:ident.$unkeyed_name:ident as <$unkeyed_typeval:expr, _>|<$unkeyed_value_type:ty>)) => { if let Some(ref $unkeyed_name) = $slf.$unkeyed_name { - $rv.push(::util::psbt::raw::Pair { - key: ::util::psbt::raw::Key { + $rv.push($crate::util::psbt::raw::Pair { + key: $crate::util::psbt::raw::Key { type_value: $unkeyed_typeval, key: vec![], }, - value: ::util::psbt::serialize::Serialize::serialize($unkeyed_name), + value: $crate::util::psbt::serialize::Serialize::serialize($unkeyed_name), }); } }; ($rv:ident.push($slf:ident.$keyed_name:ident as <$keyed_typeval:expr, $keyed_key_type:ty>|<$keyed_value_type:ty>)) => { for (key, val) in &$slf.$keyed_name { - $rv.push(::util::psbt::raw::Pair { - key: ::util::psbt::raw::Key { + $rv.push($crate::util::psbt::raw::Pair { + key: $crate::util::psbt::raw::Key { type_value: $keyed_typeval, - key: ::util::psbt::serialize::Serialize::serialize(key), + key: $crate::util::psbt::serialize::Serialize::serialize(key), }, - value: ::util::psbt::serialize::Serialize::serialize(val), + value: $crate::util::psbt::serialize::Serialize::serialize(val), }); } }; From 257ca8e504bd40b4ed13563bc8157b4c843be1fd Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 25 Jan 2020 05:43:39 +0100 Subject: [PATCH 0055/1740] Using :: for std namespaces in macro --- src/internal_macros.rs | 114 ++++++++++++++++++++-------------------- src/util/psbt/macros.rs | 6 +-- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 6baae6b8..873ae88f 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -20,7 +20,7 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl $crate::consensus::Encodable for $thing { #[inline] - fn consensus_encode( + fn consensus_encode( &self, mut s: S, ) -> Result { @@ -32,7 +32,7 @@ macro_rules! impl_consensus_encoding { impl $crate::consensus::Decodable for $thing { #[inline] - fn consensus_decode( + fn consensus_decode( mut d: D, ) -> Result<$thing, $crate::consensus::encode::Error> { Ok($thing { @@ -82,7 +82,7 @@ macro_rules! impl_array_newtype { pub fn into_bytes(self) -> [$ty; $len] { self.0 } } - impl<'a> $crate::std::convert::From<&'a [$ty]> for $thing { + impl<'a> ::std::convert::From<&'a [$ty]> for $thing { fn from(data: &'a [$ty]) -> $thing { assert_eq!(data.len(), $len); let mut ret = [0; $len]; @@ -91,7 +91,7 @@ macro_rules! impl_array_newtype { } } - impl $crate::std::ops::Index for $thing { + impl ::std::ops::Index for $thing { type Output = $ty; #[inline] @@ -103,57 +103,57 @@ macro_rules! impl_array_newtype { impl_index_newtype!($thing, $ty); - impl $crate::std::cmp::PartialEq for $thing { + impl ::std::cmp::PartialEq for $thing { #[inline] fn eq(&self, other: &$thing) -> bool { &self[..] == &other[..] } } - impl $crate::std::cmp::Eq for $thing {} + impl ::std::cmp::Eq for $thing {} - impl $crate::std::cmp::PartialOrd for $thing { + impl ::std::cmp::PartialOrd for $thing { #[inline] - fn partial_cmp(&self, other: &$thing) -> Option<$crate::std::cmp::Ordering> { + fn partial_cmp(&self, other: &$thing) -> Option<::std::cmp::Ordering> { Some(self.cmp(&other)) } } - impl $crate::std::cmp::Ord for $thing { + impl ::std::cmp::Ord for $thing { #[inline] - fn cmp(&self, other: &$thing) -> $crate::std::cmp::Ordering { + fn cmp(&self, other: &$thing) -> ::std::cmp::Ordering { // manually implement comparison to get little-endian ordering // (we need this for our numeric types; non-numeric ones shouldn't // be ordered anyway except to put them in BTrees or whatever, and // they don't care how we order as long as we're consistent). for i in 0..$len { - if self[$len - 1 - i] < other[$len - 1 - i] { return $crate::std::cmp::Ordering::Less; } - if self[$len - 1 - i] > other[$len - 1 - i] { return $crate::std::cmp::Ordering::Greater; } + if self[$len - 1 - i] < other[$len - 1 - i] { return ::std::cmp::Ordering::Less; } + if self[$len - 1 - i] > other[$len - 1 - i] { return ::std::cmp::Ordering::Greater; } } - $crate::std::cmp::Ordering::Equal + ::std::cmp::Ordering::Equal } } #[cfg_attr(feature = "clippy", allow(expl_impl_clone_on_copy))] // we don't define the `struct`, we have to explicitly impl - impl $crate::std::clone::Clone for $thing { + impl ::std::clone::Clone for $thing { #[inline] fn clone(&self) -> $thing { $thing::from(&self[..]) } } - impl $crate::std::marker::Copy for $thing {} + impl ::std::marker::Copy for $thing {} - impl $crate::std::hash::Hash for $thing { + impl ::std::hash::Hash for $thing { #[inline] fn hash(&self, state: &mut H) - where H: $crate::std::hash::Hasher + where H: ::std::hash::Hasher { (&self[..]).hash(state); } fn hash_slice(data: &[$thing], state: &mut H) - where H: $crate::std::hash::Hasher + where H: ::std::hash::Hasher { for d in data.iter() { (&d[..]).hash(state); @@ -166,8 +166,8 @@ macro_rules! impl_array_newtype { /// Implements debug formatting for a given wrapper type macro_rules! impl_array_newtype_show { ($thing:ident) => { - impl $crate::std::fmt::Debug for $thing { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + impl ::std::fmt::Debug for $thing { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, concat!(stringify!($thing), "({:?})"), &self[..]) } } @@ -177,38 +177,38 @@ macro_rules! impl_array_newtype_show { /// Implements standard indexing methods for a given wrapper type macro_rules! impl_index_newtype { ($thing:ident, $ty:ty) => { - impl $crate::std::ops::Index<$crate::std::ops::Range> for $thing { + impl ::std::ops::Index<::std::ops::Range> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: $crate::std::ops::Range) -> &[$ty] { + fn index(&self, index: ::std::ops::Range) -> &[$ty] { &self.0[index] } } - impl $crate::std::ops::Index<$crate::std::ops::RangeTo> for $thing { + impl ::std::ops::Index<::std::ops::RangeTo> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: $crate::std::ops::RangeTo) -> &[$ty] { + fn index(&self, index: ::std::ops::RangeTo) -> &[$ty] { &self.0[index] } } - impl $crate::std::ops::Index<$crate::std::ops::RangeFrom> for $thing { + impl ::std::ops::Index<::std::ops::RangeFrom> for $thing { type Output = [$ty]; #[inline] - fn index(&self, index: $crate::std::ops::RangeFrom) -> &[$ty] { + fn index(&self, index: ::std::ops::RangeFrom) -> &[$ty] { &self.0[index] } } - impl $crate::std::ops::Index<$crate::std::ops::RangeFull> for $thing { + impl ::std::ops::Index<::std::ops::RangeFull> for $thing { type Output = [$ty]; #[inline] - fn index(&self, _: $crate::std::ops::RangeFull) -> &[$ty] { + fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] { &self.0[..] } } @@ -218,9 +218,9 @@ macro_rules! impl_index_newtype { macro_rules! display_from_debug { ($thing:ident) => { - impl $crate::std::fmt::Display for $thing { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> Result<(), $crate::std::fmt::Error> { - $crate::std::fmt::Debug::fmt(self, f) + impl ::std::fmt::Display for $thing { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Debug::fmt(self, f) } } } @@ -240,7 +240,7 @@ macro_rules! serde_struct_impl { where D: $crate::serde::de::Deserializer<'de>, { - use $crate::std::fmt::{self, Formatter}; + use ::std::fmt::{self, Formatter}; use $crate::serde::de::IgnoredAny; #[allow(non_camel_case_types)] @@ -382,8 +382,8 @@ macro_rules! serde_string_impl { where D: $crate::serde::de::Deserializer<'de>, { - use $crate::std::fmt::{self, Formatter}; - use $crate::std::str::FromStr; + use ::std::fmt::{self, Formatter}; + use ::std::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { @@ -443,8 +443,8 @@ macro_rules! serde_struct_human_string_impl { D: $crate::serde::de::Deserializer<'de>, { if deserializer.is_human_readable() { - use $crate::std::fmt::{self, Formatter}; - use $crate::std::str::FromStr; + use ::std::fmt::{self, Formatter}; + use ::std::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { @@ -478,7 +478,7 @@ macro_rules! serde_struct_human_string_impl { deserializer.deserialize_str(Visitor) } else { - use $crate::std::fmt::{self, Formatter}; + use ::std::fmt::{self, Formatter}; use $crate::serde::de::IgnoredAny; #[allow(non_camel_case_types)] @@ -626,8 +626,8 @@ macro_rules! serde_struct_human_string_impl { macro_rules! impl_bytes_newtype { ($t:ident, $len:expr) => ( - impl $crate::std::fmt::LowerHex for $t { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + impl ::std::fmt::LowerHex for $t { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { for &ch in self.0.iter() { write!(f, "{:02x}", ch)?; } @@ -635,17 +635,17 @@ macro_rules! impl_bytes_newtype { } } - impl $crate::std::fmt::Display for $t { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + impl ::std::fmt::Display for $t { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fmt::LowerHex::fmt(self, f) } } impl $crate::hashes::hex::FromHex for $t { fn from_byte_iter(iter: I) -> Result - where I: $crate::std::iter::Iterator> + - $crate::std::iter::ExactSizeIterator + - $crate::std::iter::DoubleEndedIterator, + where I: ::std::iter::Iterator> + + ::std::iter::ExactSizeIterator + + ::std::iter::DoubleEndedIterator, { if iter.len() == $len { let mut ret = [0; $len]; @@ -659,7 +659,7 @@ macro_rules! impl_bytes_newtype { } } - impl $crate::std::str::FromStr for $t { + impl ::std::str::FromStr for $t { type Err = $crate::hashes::hex::Error; fn from_str(s: &str) -> Result { $crate::hashes::hex::FromHex::from_hex(s) @@ -686,7 +686,7 @@ macro_rules! impl_bytes_newtype { impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor { type Value = $t; - fn expecting(&self, formatter: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { formatter.write_str("an ASCII hex string") } @@ -694,7 +694,7 @@ macro_rules! impl_bytes_newtype { where E: $crate::serde::de::Error, { - if let Ok(hex) = $crate::std::str::from_utf8(v) { + if let Ok(hex) = ::std::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)); @@ -716,7 +716,7 @@ macro_rules! impl_bytes_newtype { impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor { type Value = $t; - fn expecting(&self, formatter: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { formatter.write_str("a bytestring") } @@ -754,30 +754,30 @@ macro_rules! user_enum { $(#[$doc] $elem),* } - impl $crate::std::fmt::Debug for $name { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + impl ::std::fmt::Debug for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } - impl $crate::std::fmt::Display for $name { - fn fmt(&self, f: &mut $crate::std::fmt::Formatter) -> $crate::std::fmt::Result { + impl ::std::fmt::Display for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } - impl $crate::std::str::FromStr for $name { - type Err = $crate::std::io::Error; + impl ::std::str::FromStr for $name { + type Err = ::std::io::Error; #[inline] fn from_str(s: &str) -> Result { match s { $($txt => Ok($name::$elem)),*, - _ => Err($crate::std::io::Error::new( - $crate::std::io::ErrorKind::InvalidInput, + _ => Err(::std::io::Error::new( + ::std::io::ErrorKind::InvalidInput, format!("Unknown network (type {})", s), )), } @@ -791,7 +791,7 @@ macro_rules! user_enum { where D: $crate::serde::Deserializer<'de>, { - use $crate::std::fmt::{self, Formatter}; + use ::std::fmt::{self, Formatter}; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 43970504..9c3bcab0 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -55,7 +55,7 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { impl $crate::consensus::Encodable for $thing { - fn consensus_encode( + fn consensus_encode( &self, mut s: S, ) -> Result { @@ -76,10 +76,10 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { impl $crate::consensus::Decodable for $thing { - fn consensus_decode( + fn consensus_decode( mut d: D, ) -> Result { - let mut rv: Self = $crate::std::default::Default::default(); + let mut rv: Self = ::std::default::Default::default(); loop { match $crate::consensus::Decodable::consensus_decode(&mut d) { From c20d356d7ee8a770e12fa03951a808a7345b9a6a Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 22 Jul 2020 12:39:32 +0300 Subject: [PATCH 0056/1740] Use the remainder from div_rem instead of recomputing it --- src/util/uint.rs | 70 ++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/util/uint.rs b/src/util/uint.rs index e05e9b99..29f7d1c4 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -84,6 +84,42 @@ macro_rules! construct_uint { assert!(init >= 0); $name::from_u64(init as u64) } + + // divmod like operation, returns (quotient, remainder) + #[inline] + fn div_rem(self, other: Self) -> (Self, Self) { + let mut sub_copy = self; + let mut shift_copy = other; + let mut ret = [0u64; $n_words]; + + let my_bits = self.bits(); + let your_bits = other.bits(); + + // Check for division by 0 + assert!(your_bits != 0); + + // Early return in case we are dividing by a larger number than us + if my_bits < your_bits { + return ($name(ret), sub_copy); + } + + // Bitwise long division + let mut shift = my_bits - your_bits; + shift_copy = shift_copy << shift; + loop { + if sub_copy >= shift_copy { + ret[shift / 64] |= 1 << (shift % 64); + sub_copy = sub_copy - shift_copy; + } + shift_copy = shift_copy >> 1; + if shift == 0 { + break; + } + shift -= 1; + } + + ($name(ret), sub_copy) + } } impl ::std::ops::Add<$name> for $name { @@ -134,35 +170,7 @@ macro_rules! construct_uint { type Output = $name; fn div(self, other: $name) -> $name { - let mut sub_copy = self; - let mut shift_copy = other; - let mut ret = [0u64; $n_words]; - - let my_bits = self.bits(); - let your_bits = other.bits(); - - // Check for division by 0 - assert!(your_bits != 0); - - // Early return in case we are dividing by a larger number than us - if my_bits < your_bits { - return $name(ret); - } - - // Bitwise long division - let mut shift = my_bits - your_bits; - shift_copy = shift_copy << shift; - loop { - if sub_copy >= shift_copy { - ret[shift / 64] |= 1 << (shift % 64); - sub_copy = sub_copy - shift_copy; - } - shift_copy = shift_copy >> 1; - if shift == 0 { break; } - shift -= 1; - } - - $name(ret) + self.div_rem(other).0 } } @@ -170,8 +178,7 @@ macro_rules! construct_uint { type Output = $name; fn rem(self, other: $name) -> $name { - let times = self / other; - self - (times * other) + self.div_rem(other).1 } } @@ -568,4 +575,3 @@ mod tests { assert_eq!(end2.ok(), Some(start2)); } } - From e47fcae4354eb9cba061fb15fcf2b8d3be346ba2 Mon Sep 17 00:00:00 2001 From: Jake Rawsthorne Date: Thu, 30 Jul 2020 17:25:21 +0100 Subject: [PATCH 0057/1740] feefilter message --- src/network/message.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/network/message.rs b/src/network/message.rs index 5147252b..19a8e4ea 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -154,7 +154,9 @@ pub enum NetworkMessage { /// `alert` Alert(Vec), /// `reject` - Reject(message_network::Reject) + Reject(message_network::Reject), + /// `feefilter` + FeeFilter(i64), } impl NetworkMessage { @@ -185,6 +187,7 @@ impl NetworkMessage { NetworkMessage::CFCheckpt(_) => "cfcheckpt", NetworkMessage::Alert(_) => "alert", NetworkMessage::Reject(_) => "reject", + NetworkMessage::FeeFilter(_) => "feefilter", } } @@ -253,6 +256,7 @@ impl Encodable for RawNetworkMessage { NetworkMessage::CFCheckpt(ref dat) => serialize(dat), NetworkMessage::Alert(ref dat) => serialize(dat), NetworkMessage::Reject(ref dat) => serialize(dat), + NetworkMessage::FeeFilter(ref data) => serialize(data), NetworkMessage::Verack | NetworkMessage::SendHeaders | NetworkMessage::MemPool @@ -319,6 +323,7 @@ impl Decodable for RawNetworkMessage { "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)?), + "feefilter" => NetworkMessage::FeeFilter(Decodable::consensus_decode(&mut mem_d)?), _ => return Err(encode::Error::UnrecognizedNetworkCommand(cmd.into_owned())), }; Ok(RawNetworkMessage { @@ -381,6 +386,7 @@ mod test { 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: "Test reject".into(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}), + NetworkMessage::FeeFilter(1000), ]; for msg in msgs { From 1ffdce99ed31325ff438e58e92c9a175ac615026 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 6 Aug 2020 12:24:08 +0200 Subject: [PATCH 0058/1740] Deprecate the util::contracthash module --- src/util/contracthash.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 15df0a57..fce63f85 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -18,6 +18,8 @@ //! at http://blockstream.com/sidechains.pdf for details of //! what this does. +#![deprecated] + use secp256k1::{self, Secp256k1}; use PrivateKey; use PublicKey; From 0a25d87f2ef2df2fd0a34c4777983942c6c0b192 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 6 Aug 2020 21:01:40 +0300 Subject: [PATCH 0059/1740] Remove empty code block --- src/util/merkleblock.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 74ee2f4b..9c241ca4 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -439,8 +439,6 @@ impl MerkleBlock { /// /// The `header` is the block header, `block_txids` is the full list of txids included in the block and /// `match_txids` is a set containing the transaction ids that should be included in the partial merkle tree. - /// ``` - pub fn from_header_txids( header: &BlockHeader, block_txids: &[Txid], From 2fd353d5ab0ef96376cda80bc5162e7fb3232a20 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 9 Aug 2020 18:00:00 +0200 Subject: [PATCH 0060/1740] Big integers (Uint*) from byte slice array with `from_be_bytes` --- fuzz/fuzz_targets/uint128_fuzz.rs | 7 +++++++ src/util/endian.rs | 2 ++ src/util/uint.rs | 25 ++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/fuzz/fuzz_targets/uint128_fuzz.rs b/fuzz/fuzz_targets/uint128_fuzz.rs index 11b2b620..1c72b927 100644 --- a/fuzz/fuzz_targets/uint128_fuzz.rs +++ b/fuzz/fuzz_targets/uint128_fuzz.rs @@ -1,5 +1,6 @@ extern crate bitcoin; use std::str::FromStr; +use std::convert::Into; fn do_test(data: &[u8]) { macro_rules! read_ints { @@ -11,6 +12,12 @@ fn do_test(data: &[u8]) { } // Note BE: let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]); + + // Checking two conversion methods against each other + let mut slice = [0u8; 16]; + slice.copy_from_slice(&data[$start..$start + 16]); + assert_eq!(uint128, bitcoin::util::uint::Uint128::from_be_bytes(slice)); + (native, uint128) } } } diff --git a/src/util/endian.rs b/src/util/endian.rs index 8c10b57a..37b59a19 100644 --- a/src/util/endian.rs +++ b/src/util/endian.rs @@ -52,6 +52,7 @@ macro_rules! define_le_to_array { } define_slice_to_be!(slice_to_u32_be, u32); +define_slice_to_be!(slice_to_u64_be, u64); define_be_to_array!(u32_to_array_be, u32, 4); define_slice_to_le!(slice_to_u16_le, u16); define_slice_to_le!(slice_to_u32_le, u32); @@ -105,6 +106,7 @@ 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!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]); assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead); diff --git a/src/util/uint.rs b/src/util/uint.rs index 29f7d1c4..a3a87b9b 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -73,6 +73,7 @@ macro_rules! construct_uint { } /// Create an object from a given unsigned 64-bit integer + #[inline] pub fn from_u64(init: u64) -> Option<$name> { let mut ret = [0; $n_words]; ret[0] = init; @@ -80,11 +81,23 @@ macro_rules! construct_uint { } /// Create an object from a given signed 64-bit integer + #[inline] pub fn from_i64(init: i64) -> Option<$name> { assert!(init >= 0); $name::from_u64(init as u64) } + /// Creates big integer value from a byte slice array using + /// big-endian encoding + pub fn from_be_bytes(bytes: [u8; $n_words * 8]) -> $name { + use super::endian::slice_to_u64_be; + let mut slice = [0u64; $n_words]; + for n in 0..$n_words { + slice[$n_words - n - 1] = slice_to_u64_be(&bytes[(n * 8)..(n * 8 + 8)]); + } + $name(slice) + } + // divmod like operation, returns (quotient, remainder) #[inline] fn div_rem(self, other: Self) -> (Self, Self) { @@ -409,7 +422,7 @@ impl Uint256 { #[cfg(test)] mod tests { use consensus::{deserialize, serialize}; - use util::uint::Uint256; + use util::uint::{Uint256, Uint128}; use util::BitArray; #[test] @@ -467,6 +480,16 @@ mod tests { assert!(small <= small); } + #[test] + pub fn uint_from_be_bytes() { + assert_eq!(Uint128::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed]), + Uint128([0xdeafbabe2bedfeed, 0x1badcafedeadbeef])); + + assert_eq!(Uint256::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed, + 0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0]), + Uint256([0x11fed2bad1c0ffe0, 0xbaadf00ddefaceda, 0xdeafbabe2bedfeed, 0x1badcafedeadbeef])); + } + #[test] pub fn uint256_arithmetic_test() { let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); From e9f1f11c2ce6512aae7f9b5918179e48970f6542 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 17 Aug 2020 10:28:33 -0700 Subject: [PATCH 0061/1740] Transaction and header version is signed int --- src/blockdata/block.rs | 3 +-- src/blockdata/transaction.rs | 7 +++---- src/util/bip143.rs | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 5a415594..989201db 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -37,7 +37,7 @@ use VarInt; #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub struct BlockHeader { /// The protocol version. Should always be 1. - pub version: u32, + pub version: i32, /// Reference to the previous block in the chain pub prev_blockhash: BlockHash, /// The root hash of the merkle tree of transactions in the block @@ -320,4 +320,3 @@ mod tests { assert_eq!(header.bits, BlockHeader::compact_target_from_u256(&header.target())); } } - diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 6b091f82..bc9cd2fb 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -260,7 +260,7 @@ impl Default for TxOut { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Transaction { /// The protocol version, is currently expected to be 1 or 2 (BIP 68). - pub version: u32, + pub version: i32, /// Block number before which this transaction is valid, or 0 for /// valid immediately. pub lock_time: u32, @@ -531,7 +531,7 @@ impl Encodable for Transaction { impl Decodable for Transaction { fn consensus_decode(mut d: D) -> Result { - let version = u32::consensus_decode(&mut d)?; + let version = i32::consensus_decode(&mut d)?; let input = Vec::::consensus_decode(&mut d)?; // segwit if input.is_empty() { @@ -662,7 +662,7 @@ mod tests { 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(), @@ -1229,4 +1229,3 @@ mod tests { } } } - diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 8b805e61..59e36961 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -30,7 +30,7 @@ use consensus::encode::Encodable; #[derive(Clone, PartialEq, Eq, Debug)] #[deprecated(since="0.24.0", note="please use `SigHashCache` instead")] pub struct SighashComponents { - tx_version: u32, + tx_version: i32, tx_locktime: u32, /// Hash of all the previous outputs pub hash_prevouts: SigHash, From 945db009b2638151ac80e3750a11ade455c2a034 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 19 Aug 2020 13:46:07 -0700 Subject: [PATCH 0062/1740] Add test for transaction and block version serialization --- src/blockdata/block.rs | 15 +++++++++++++++ src/blockdata/transaction.rs | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 989201db..93d7c591 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -311,6 +311,21 @@ mod tests { assert_eq!(serialize(&real_decode), segwit_block); } + #[test] + fn block_version_test() { + let block = Vec::from_hex("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let decode: Result = deserialize(&block); + assert!(decode.is_ok()); + let real_decode = decode.unwrap(); + assert_eq!(real_decode.header.version, 2147483647); + + let block2 = Vec::from_hex("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let decode2: Result = deserialize(&block2); + assert!(decode2.is_ok()); + let real_decode2 = decode2.unwrap(); + assert_eq!(real_decode2.header.version, -2147483648); + } + #[test] fn compact_roundrtip_test() { let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index bc9cd2fb..8cc37d84 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -761,6 +761,21 @@ mod tests { assert_eq!(realtx.get_size(), tx_bytes.len()); } + #[test] + fn test_transaction_version() { + let tx_bytes = Vec::from_hex("ffffff7f0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000").unwrap(); + let tx: Result = deserialize(&tx_bytes); + assert!(tx.is_ok()); + let realtx = tx.unwrap(); + assert_eq!(realtx.version, 2147483647); + + let tx2_bytes = Vec::from_hex("000000800100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000").unwrap(); + let tx2: Result = deserialize(&tx2_bytes); + assert!(tx2.is_ok()); + let realtx2 = tx2.unwrap(); + assert_eq!(realtx2.version, -2147483648); + } + #[test] fn tx_no_input_deserialization() { let tx_bytes = Vec::from_hex( From 3d80a0c962fbda0ad368b48ef81ab26b1e8f1dbd Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 25 Aug 2020 20:06:28 -0400 Subject: [PATCH 0063/1740] Expose the witnesses of the tx being hashed in SigHashCache See docuemntation of the new method for more, but this allows certain use patterns which were broken with the introduction of SigHashCache. --- src/util/bip143.rs | 54 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 8b805e61..d558fb3e 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -25,6 +25,8 @@ use blockdata::script::Script; use blockdata::transaction::{Transaction, TxIn, SigHashType}; use consensus::encode::Encodable; +use std::ops::{Deref, DerefMut}; + /// Parts of a sighash which are common across inputs or signatures, and which are /// sufficient (in conjunction with a private key) to sign the transaction #[derive(Clone, PartialEq, Eq, Debug)] @@ -102,9 +104,9 @@ impl SighashComponents { } /// A replacement for SigHashComponents which supports all sighash modes -pub struct SigHashCache<'a> { +pub struct SigHashCache> { /// Access to transaction required for various introspection - tx: &'a Transaction, + tx: R, /// Hash of all the previous outputs, computed as required hash_prevouts: Option, /// Hash of all the input sequence nos, computed as required @@ -113,12 +115,12 @@ pub struct SigHashCache<'a> { hash_outputs: Option, } -impl<'a> SigHashCache<'a> { +impl> SigHashCache { /// Compute the sighash components from an unsigned transaction and auxiliary /// in a lazy manner when required. /// For the generated sighashes to be valid, no fields in the transaction may change except for /// script_sig and witnesses. - pub fn new(tx: &Transaction) -> SigHashCache { + pub fn new(tx: R) -> Self { SigHashCache { tx: tx, hash_prevouts: None, @@ -189,15 +191,17 @@ impl<'a> SigHashCache<'a> { zero_hash.consensus_encode(&mut enc).unwrap(); } - let txin = &self.tx.input[input_index]; + { + let txin = &self.tx.input[input_index]; - txin - .previous_output - .consensus_encode(&mut enc) - .unwrap(); - script_code.consensus_encode(&mut enc).unwrap(); - value.consensus_encode(&mut enc).unwrap(); - txin.sequence.consensus_encode(&mut enc).unwrap(); + txin + .previous_output + .consensus_encode(&mut enc) + .unwrap(); + script_code.consensus_encode(&mut enc).unwrap(); + value.consensus_encode(&mut enc).unwrap(); + txin.sequence.consensus_encode(&mut enc).unwrap(); + } if sighash != SigHashType::Single && sighash != SigHashType::None { self.hash_outputs().consensus_encode(&mut enc).unwrap(); @@ -215,6 +219,32 @@ impl<'a> SigHashCache<'a> { } } +impl> SigHashCache { + /// When the SigHashCache is initialized with a mutable reference to a transaction instead of a + /// regular reference, this method is available to allow modification to the witnesses. + /// + /// This allows in-line signing such as + /// ``` + /// use bitcoin::blockdata::transaction::{Transaction, SigHashType}; + /// use bitcoin::util::bip143::SigHashCache; + /// use bitcoin::Script; + /// + /// let mut tx_to_sign = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() }; + /// let input_count = tx_to_sign.input.len(); + /// + /// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign); + /// for inp in 0..input_count { + /// let prevout_script = Script::new(); + /// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, SigHashType::All); + /// // ... sign the sighash + /// sig_hasher.access_witness(inp).push(Vec::new()); + /// } + /// ``` + pub fn access_witness(&mut self, input_index: usize) -> &mut Vec> { + &mut self.tx.input[input_index].witness + } +} + #[cfg(test)] #[allow(deprecated)] mod tests { From 5017b333262f7b3e22445831aab11f23ef08e9e5 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Mon, 31 Aug 2020 19:21:29 +0200 Subject: [PATCH 0064/1740] Add `Clone` instance to `RawNetworkMessage` --- src/network/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/message.rs b/src/network/message.rs index 19a8e4ea..d71c723b 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -90,7 +90,7 @@ impl Decodable for CommandString { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] /// A Network message pub struct RawNetworkMessage { /// Magic bytes to identify the network these messages are meant for From c5204c001f3ba192219b7da251b6126085b86211 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 31 Aug 2020 15:06:21 -0500 Subject: [PATCH 0065/1740] Added Hash Preimages to psbt Added hash preimages to psbt as per updated bip174 --- src/util/psbt/error.rs | 31 +++++++++++++++++++ src/util/psbt/macros.rs | 54 +++++++++++++++++++++++++++++++++ src/util/psbt/map/input.rs | 61 +++++++++++++++++++++++++++++++++++--- src/util/psbt/serialize.rs | 5 ++++ 4 files changed, 147 insertions(+), 4 deletions(-) diff --git a/src/util/psbt/error.rs b/src/util/psbt/error.rs index 15ab268d..1e006bc1 100644 --- a/src/util/psbt/error.rs +++ b/src/util/psbt/error.rs @@ -18,6 +18,16 @@ use std::fmt; use blockdata::transaction::Transaction; use util::psbt::raw; +use hashes::{self, sha256, hash160, sha256d, ripemd160}; + +/// Support hash-preimages in psbt +#[derive(Debug)] +pub enum PsbtHash{ + Ripemd160(ripemd160::Hash), + Sha256(sha256::Hash), + Hash256(sha256d::Hash), + Hash160(hash160::Hash), +} /// Ways that a Partially Signed Transaction might fail. #[derive(Debug)] pub enum Error { @@ -48,6 +58,15 @@ pub enum Error { }, /// Unable to parse as a standard SigHash type. NonStandardSigHashType(u32), + /// Parsing errors from bitcoin_hashes + HashParseError(hashes::Error), + /// The pre-image must hash to the correponding psbt hash + InvalidPreimageHashPair{ + /// Pre-image + preimage: Vec, + /// Hash value + hash: PsbtHash, + } } impl fmt::Display for Error { @@ -65,6 +84,11 @@ impl fmt::Display for Error { 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} => { + // directly using debug forms of psbthash enums + write!(f, "Preimage {:?} does not match hash {:?}", preimage, hash ) + } } } } @@ -75,3 +99,10 @@ impl error::Error for Error { "description() is deprecated; use Display" } } + +#[doc(hidden)] +impl From for Error { + fn from(e: hashes::Error) -> Error { + Error::HashParseError(e) + } +} diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 9c3bcab0..0901fcda 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -130,6 +130,30 @@ macro_rules! impl_psbt_insert_pair { }; } +#[cfg_attr(rustfmt, rustfmt_skip)] +macro_rules! impl_psbt_insert_hash_pair { + ($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>; $err_name: ident ) => { + if !$raw_key.key.is_empty() { + let key_val: $keyed_key_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?; + match $slf.$keyed_name.entry(key_val) { + ::std::collections::btree_map::Entry::Vacant(empty_key) => { + let val: $keyed_value_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?; + if <$keyed_key_type>::hash(&val) != key_val{ + return Err($crate::util::psbt::Error::InvalidPreimageHashPair{ + preimage: val, + hash: $crate::util::psbt::error::PsbtHash::$err_name(key_val), + }.into()); + } + empty_key.insert(val); + } + ::std::collections::btree_map::Entry::Occupied(_) => return Err($crate::util::psbt::Error::DuplicateKey($raw_key).into()), + } + } else { + return Err($crate::util::psbt::Error::InvalidKey($raw_key).into()); + } + }; +} + #[cfg_attr(rustfmt, rustfmt_skip)] macro_rules! impl_psbt_get_pair { ($rv:ident.push($slf:ident.$unkeyed_name:ident as <$unkeyed_typeval:expr, _>|<$unkeyed_value_type:ty>)) => { @@ -155,3 +179,33 @@ macro_rules! impl_psbt_get_pair { } }; } + +// macros for serde of hashes +macro_rules! impl_psbt_hash_de_serialize { + ($thing:ty) => { + impl_psbt_hash_serialize!($thing); + impl_psbt_hash_deserialize!($thing); + }; +} + +macro_rules! impl_psbt_hash_deserialize { + ($thing:ty) => { + impl $crate::util::psbt::serialize::Deserialize for $thing { + fn deserialize(bytes: &[u8]) -> Result { + <$thing>::from_slice(&bytes[..]).map_err(|e| { + $crate::util::psbt::Error::from(e).into() + }) + } + } + }; +} + +macro_rules! impl_psbt_hash_serialize { + ($thing:ty) => { + impl $crate::util::psbt::serialize::Serialize for $thing { + fn serialize(&self) -> Vec { + self.into_inner().to_vec() + } + } + }; +} diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 05a24432..9f22cbab 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -17,13 +17,13 @@ use std::collections::BTreeMap; use blockdata::script::Script; use blockdata::transaction::{SigHashType, Transaction, TxOut}; use consensus::encode; +use hashes::{Hash, hash160, ripemd160, sha256, sha256d}; use util::bip32::{DerivationPath, Fingerprint}; use util::key::PublicKey; use util::psbt; use util::psbt::map::Map; use util::psbt::raw; use util::psbt::Error; - /// A key-value map for an input of the corresponding index in the unsigned /// transaction. #[derive(Clone, Default, Debug, PartialEq)] @@ -55,6 +55,15 @@ pub struct Input { /// The finalized, fully-constructed scriptWitness with signatures and any /// other scripts necessary for this input to pass validation. pub final_script_witness: Option>>, + /// TODO: Proof of reserves commitment + /// RIPEMD hash to preimage map + pub ripemd_preimages: BTreeMap>, + /// SHA256 hash to preimage map + pub sha256_preimages: BTreeMap>, + /// HSAH160 hash to preimage map + pub hash160_preimages: BTreeMap>, + /// HAS256 hash to preimage map + pub hash256_preimages: BTreeMap>, /// Unknown key-value pairs for this input. pub unknown: BTreeMap>, } @@ -112,10 +121,34 @@ impl Map for Input { self.hd_keypaths <= | } } - _ => match self.unknown.entry(raw_key) { - ::std::collections::btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, - ::std::collections::btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), + 10u8 => { + impl_psbt_insert_hash_pair! { + self.ripemd_preimages <= |>; Ripemd160 + } + } + 11u8 => { + impl_psbt_insert_hash_pair! { + self.sha256_preimages <= |>; Sha256 + } + } + 12u8 => { + impl_psbt_insert_hash_pair! { + self.hash160_preimages <= |>; Hash160 + } + } + 13u8 => { + impl_psbt_insert_hash_pair! { + self.hash256_preimages <= |>; Hash256 + } } + _ => match self.unknown.entry(raw_key) { + ::std::collections::btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(raw_value); + } + ::std::collections::btree_map::Entry::Occupied(k) => { + return Err(Error::DuplicateKey(k.key().clone()).into()) + } + }, } Ok(()) @@ -160,6 +193,22 @@ impl Map for Input { rv.push(self.final_script_witness as <8u8, _>|