From b88f00c698efecd210b5c1b84122f70387349418 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Tue, 15 Jan 2019 18:34:48 -0500 Subject: [PATCH 1/7] Add bitcoin_hashes dependency, rename some features Because features and dependencies share the same namespace, and we want to pass down the optional dependence on serde to bitcoin_hashes, we need to rename the feature to something other than serde. Right now only features can be passed down to dependencies. Note that we could have also renamed the dependency to something like serde-dep and kept the same feature name, however, dependency renaming has only been available since cargo 0.27.0 Features that represent optional dependencies have been prefixed with 'use-'. The travis file has also been modified to conform to this change. --- .travis.yml | 4 ++-- Cargo.toml | 6 ++++-- src/lib.rs | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d01a8575..6300003a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ script: - cargo test --verbose - cargo build --verbose --features=bitcoinconsensus - cargo test --verbose --features=bitcoinconsensus - - cargo build --verbose --features=serde - - cargo test --verbose --features=serde + - cargo build --verbose --features=use-serde + - cargo test --verbose --features=use-serde - cargo build --verbose --features=serde-decimal - cargo test --verbose --features=serde-decimal - if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi diff --git a/Cargo.toml b/Cargo.toml index fd294d71..eae14d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,15 +15,17 @@ name = "bitcoin" path = "src/lib.rs" [features] -fuzztarget = ["secp256k1/fuzztarget"] -serde-decimal = ["serde", "strason"] +fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"] +serde-decimal = ["use-serde", "strason"] unstable = [] +use-serde = ["serde", "bitcoin_hashes/serde"] [dependencies] bitcoin-bech32 = "0.8.0" byteorder = "1.2" rand = "0.3" rust-crypto = "0.2" +bitcoin_hashes = "0.3" bitcoinconsensus = { version = "0.16", optional = true } [dependencies.serde] diff --git a/src/lib.rs b/src/lib.rs index 362f0591..9f187492 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ #![deny(missing_docs)] extern crate bitcoin_bech32; +extern crate bitcoin_hashes; extern crate byteorder; extern crate crypto; extern crate hex; From 45aa709467fdb95ed8b908275ad486e8a348873b Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 13:27:14 -0500 Subject: [PATCH 2/7] Implement En/Decodable for sha256d::Hash --- src/consensus/encode.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 521cd8ee..49d0229c 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -43,6 +43,7 @@ use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt}; use hex::encode as hex_encode; use bitcoin_bech32; +use bitcoin_hashes::{sha256d, Hash as HashTrait}; use util::base58; @@ -678,7 +679,18 @@ impl Decodable for HashMap } } +impl Encodable for sha256d::Hash { + fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + self.into_inner().consensus_encode(s) + } +} +impl Decodable for sha256d::Hash { + fn consensus_decode(d: &mut D) -> Result { + let inner: [u8; 32] = Decodable::consensus_decode(d)?; + Ok(sha256d::Hash::from_slice(&inner).unwrap()) + } +} // Tests #[cfg(test)] From 99f63a8ca4a531fed7cc684c12c0fe66045440f4 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 15:45:31 -0500 Subject: [PATCH 3/7] Convert codebase from util::hash to bitcoin_hashes Also replace unsafe transmute with call to read_u64_into --- src/blockdata/block.rs | 21 +++++--- src/blockdata/constants.rs | 10 ++-- src/blockdata/script.rs | 18 ++----- src/blockdata/transaction.rs | 72 +++++++++++++-------------- src/consensus/encode.rs | 4 +- src/internal_macros.rs | 2 +- src/network/message_blockdata.rs | 16 +++--- src/util/address.rs | 61 +++++++++++------------ src/util/base58.rs | 9 ++-- src/util/bip143.rs | 27 ++++++----- src/util/bip32.rs | 83 ++++++++++---------------------- src/util/contracthash.rs | 28 +++++------ src/util/hash.rs | 15 +++--- 13 files changed, 162 insertions(+), 204 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index ca098519..cd81c8f4 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -20,9 +20,11 @@ //! these blocks and the blockchain. //! +use bitcoin_hashes::{sha256d, Hash}; + use util; use util::Error::{SpvBadTarget, SpvBadProofOfWork}; -use util::hash::{BitcoinHash, Sha256dHash}; +use util::hash::BitcoinHash; use util::uint::Uint256; use consensus::encode::VarInt; use network::constants::Network; @@ -36,9 +38,9 @@ pub struct BlockHeader { /// The protocol version. Should always be 1. pub version: u32, /// Reference to the previous block in the chain - pub prev_blockhash: Sha256dHash, + pub prev_blockhash: sha256d::Hash, /// The root hash of the merkle tree of transactions in the block - pub merkle_root: Sha256dHash, + pub merkle_root: sha256d::Hash, /// The timestamp of the block, as claimed by the miner pub time: u32, /// The target value below which the blockhash must lie, encoded as a @@ -120,11 +122,16 @@ impl BlockHeader { /// is correct, but does not verify that the transactions are valid or encoded /// correctly. pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> { + use byteorder::{ByteOrder, LittleEndian}; + let target = &self.target(); if target != required_target { return Err(SpvBadTarget); } - let hash = &self.bitcoin_hash().into_le(); + let data: [u8; 32] = self.bitcoin_hash().into_inner(); + let mut ret = [0u64; 4]; + LittleEndian::read_u64_into(&data, &mut ret); + let hash = &Uint256(ret); if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) } } @@ -141,14 +148,14 @@ impl BlockHeader { } impl BitcoinHash for BlockHeader { - fn bitcoin_hash(&self) -> Sha256dHash { + fn bitcoin_hash(&self) -> sha256d::Hash { use consensus::encode::serialize; - Sha256dHash::from_data(&serialize(self)) + sha256d::Hash::hash(&serialize(self)) } } impl BitcoinHash for Block { - fn bitcoin_hash(&self) -> Sha256dHash { + fn bitcoin_hash(&self) -> sha256d::Hash { self.header.bitcoin_hash() } } diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 3f0ebcc9..76f040b8 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -166,7 +166,7 @@ mod test { assert_eq!(gen.output[0].value, 50 * COIN_VALUE); assert_eq!(gen.lock_time, 0); - assert_eq!(gen.bitcoin_hash().be_hex_string(), + assert_eq!(format!("{:x}", gen.bitcoin_hash()), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); } @@ -176,12 +176,12 @@ mod test { assert_eq!(gen.header.version, 1); assert_eq!(gen.header.prev_blockhash, Default::default()); - assert_eq!(gen.header.merkle_root.be_hex_string(), + assert_eq!(format!("{:x}", gen.header.merkle_root), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); assert_eq!(gen.header.time, 1231006505); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 2083236893); - assert_eq!(gen.header.bitcoin_hash().be_hex_string(), + assert_eq!(format!("{:x}", gen.header.bitcoin_hash()), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f".to_string()); } @@ -190,12 +190,12 @@ mod test { let gen = genesis_block(Network::Testnet); assert_eq!(gen.header.version, 1); assert_eq!(gen.header.prev_blockhash, Default::default()); - assert_eq!(gen.header.merkle_root.be_hex_string(), + assert_eq!(format!("{:x}", gen.header.merkle_root), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); assert_eq!(gen.header.time, 1296688602); assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.nonce, 414098458); - assert_eq!(gen.header.bitcoin_hash().be_hex_string(), + assert_eq!(format!("{:x}", gen.header.bitcoin_hash()), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string()); } } diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 8cb1b9e6..a053bc37 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -27,19 +27,15 @@ use std::default::Default; use std::{error, fmt}; -use crypto::digest::Digest; #[cfg(feature = "serde")] use serde; use blockdata::opcodes; use consensus::encode::{Decodable, Encodable}; use consensus::encode::{self, Decoder, Encoder}; -use util::hash::Hash160; +use bitcoin_hashes::{hash160, sha256, Hash}; #[cfg(feature="bitcoinconsensus")] use bitcoinconsensus; #[cfg(feature="bitcoinconsensus")] use std::convert; -#[cfg(feature="bitcoinconsensus")] use util::hash::Sha256dHash; - -#[cfg(feature="fuzztarget")] use fuzz_util::sha2::Sha256; -#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256; +#[cfg(feature="bitcoinconsensus")] use bitcoin_hashes::sha256d; #[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)] /// A Bitcoin script @@ -163,7 +159,7 @@ pub enum Error { BitcoinConsensus(bitcoinconsensus::Error), #[cfg(feature="bitcoinconsensus")] /// Can not find the spent transaction - UnknownSpentTransaction(Sha256dHash), + UnknownSpentTransaction(sha256d::Hash), #[cfg(feature="bitcoinconsensus")] /// The spent transaction does not have the referred output WrongSpentOutputIndex(usize), @@ -305,7 +301,7 @@ impl Script { /// Compute the P2SH output corresponding to this redeem script pub fn to_p2sh(&self) -> Script { Builder::new().push_opcode(opcodes::all::OP_HASH160) - .push_slice(&Hash160::from_data(&self.0)[..]) + .push_slice(&hash160::Hash::hash(&self.0)[..]) .push_opcode(opcodes::all::OP_EQUAL) .into_script() } @@ -313,12 +309,8 @@ impl Script { /// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem /// script") pub fn to_v0_p2wsh(&self) -> Script { - let mut tmp = [0; 32]; - let mut sha2 = Sha256::new(); - sha2.input(&self.0); - sha2.result(&mut tmp); Builder::new().push_int(0) - .push_slice(&tmp) + .push_slice(&sha256::Hash::hash(&self.0)[..]) .into_script() } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 227f87c4..dbe1b111 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -28,7 +28,10 @@ use std::default::Default; use std::fmt; #[cfg(feature="bitcoinconsensus")] use std::collections::HashMap; -use util::hash::{BitcoinHash, Sha256dHash, HexError}; +use bitcoin_hashes::{self, sha256d, Hash}; +use bitcoin_hashes::hex::FromHex; + +use util::hash::BitcoinHash; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; use consensus::encode::{self, serialize, Encoder, Decoder}; @@ -38,7 +41,7 @@ use consensus::encode::{Encodable, Decodable, VarInt}; #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct OutPoint { /// The referenced transaction's txid - pub txid: Sha256dHash, + pub txid: sha256d::Hash, /// The index of the referenced output in its transaction's vout pub vout: u32, } @@ -93,7 +96,7 @@ impl fmt::Display for OutPoint { #[derive(Clone, PartialEq, Eq, Debug)] pub enum ParseOutPointError { /// Error in TXID part. - Txid(HexError), + Txid(bitcoin_hashes::Error), /// Error in vout part. Vout(::std::num::ParseIntError), /// Error in general format. @@ -164,7 +167,7 @@ impl ::std::str::FromStr for OutPoint { return Err(ParseOutPointError::Format); } Ok(OutPoint { - txid: Sha256dHash::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?, + txid: sha256d::Hash::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?, vout: parse_vout(&s[colon+1..])?, }) } @@ -257,7 +260,7 @@ impl Transaction { /// Computes a "normalized TXID" which does not include any signatures. /// This gives a way to identify a transaction that is ``the same'' as /// another in the sense of having same inputs and outputs. - pub fn ntxid(&self) -> Sha256dHash { + pub fn ntxid(&self) -> sha256d::Hash { let cloned_tx = Transaction { version: self.version, lock_time: self.lock_time, @@ -271,15 +274,13 @@ impl Transaction { /// to the output of `BitcoinHash::bitcoin_hash()`, but for segwit transactions, /// this will give the correct txid (not including witnesses) while `bitcoin_hash` /// will also hash witnesses. - pub fn txid(&self) -> Sha256dHash { - use util::hash::Sha256dEncoder; - - let mut enc = Sha256dEncoder::new(); + pub fn txid(&self) -> sha256d::Hash { + let mut enc = sha256d::Hash::engine(); self.version.consensus_encode(&mut enc).unwrap(); self.input.consensus_encode(&mut enc).unwrap(); self.output.consensus_encode(&mut enc).unwrap(); self.lock_time.consensus_encode(&mut enc).unwrap(); - enc.into_hash() + sha256d::Hash::from_engine(enc) } /// Computes a signature hash for a given input index with a given sighash flag. @@ -295,17 +296,17 @@ impl Transaction { /// # Panics /// Panics if `input_index` is greater than or equal to `self.input.len()` /// - pub fn signature_hash(&self, input_index: usize, script_pubkey: &Script, sighash_u32: u32) -> Sha256dHash { + pub fn signature_hash(&self, input_index: usize, script_pubkey: &Script, sighash_u32: u32) -> sha256d::Hash { assert!(input_index < self.input.len()); // Panic on OOB let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_u32).split_anyonecanpay_flag(); // Special-case sighash_single bug because this is easy enough. if sighash == SigHashType::Single && input_index >= self.output.len() { - return Sha256dHash::from(&[1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0][..]); + return sha256d::Hash::from_slice(&[1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0]).unwrap(); } // Build tx to sign @@ -350,7 +351,7 @@ impl Transaction { // hash the result let mut raw_vec = serialize(&tx); raw_vec.write_u32::(sighash_u32).unwrap(); - Sha256dHash::from_data(&raw_vec) + sha256d::Hash::hash(&raw_vec) } /// Gets the "weight" of this transaction, as defined by BIP141. For transactions with an empty @@ -397,7 +398,7 @@ impl Transaction { #[cfg(feature="bitcoinconsensus")] /// Verify that this transaction is able to spend some outputs of spent transactions - pub fn verify(&self, spent: &HashMap) -> Result<(), script::Error> { + pub fn verify(&self, spent: &HashMap) -> Result<(), script::Error> { let tx = serialize(&*self); for (idx, input) in self.input.iter().enumerate() { if let Some(ref s) = spent.get(&input.previous_output.txid) { @@ -420,12 +421,10 @@ impl Transaction { } impl BitcoinHash for Transaction { - fn bitcoin_hash(&self) -> Sha256dHash { - use util::hash::Sha256dEncoder; - - let mut enc = Sha256dEncoder::new(); + fn bitcoin_hash(&self) -> sha256d::Hash { + let mut enc = sha256d::Hash::engine(); self.consensus_encode(&mut enc).unwrap(); - enc.into_hash() + sha256d::Hash::from_engine(enc) } } @@ -599,9 +598,12 @@ mod tests { use blockdata::script::Script; use consensus::encode::serialize; use consensus::encode::deserialize; - use util::hash::{BitcoinHash, Sha256dHash}; + use util::hash::BitcoinHash; use util::misc::hex_bytes; + use bitcoin_hashes::{sha256d, Hash}; + use bitcoin_hashes::hex::FromHex; + #[test] fn test_outpoint() { assert_eq!(OutPoint::from_str("i don't care"), @@ -617,20 +619,20 @@ mod tests { assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"), Err(ParseOutPointError::VoutNotCanonical)); assert_eq!(OutPoint::from_str("i don't care:1"), - Err(ParseOutPointError::Txid(Sha256dHash::from_hex("i don't care").unwrap_err()))); + Err(ParseOutPointError::Txid(sha256d::Hash::from_hex("i don't care").unwrap_err()))); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"), - Err(ParseOutPointError::Txid(Sha256dHash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X").unwrap_err()))); + Err(ParseOutPointError::Txid(sha256d::Hash::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: Sha256dHash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), + txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), vout: 42, })); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"), Ok(OutPoint{ - txid: Sha256dHash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), + txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), vout: 0, })); } @@ -665,13 +667,13 @@ mod tests { assert_eq!(realtx.input.len(), 1); // In particular this one is easy to get backward -- in bitcoin hashes are encoded // as little-endian 256-bit numbers rather than as data strings. - assert_eq!(realtx.input[0].previous_output.txid.be_hex_string(), + assert_eq!(format!("{:x}", realtx.input[0].previous_output.txid), "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string()); assert_eq!(realtx.input[0].previous_output.vout, 1); assert_eq!(realtx.output.len(), 1); assert_eq!(realtx.lock_time, 0); - assert_eq!(realtx.bitcoin_hash().be_hex_string(), + assert_eq!(format!("{:x}", realtx.bitcoin_hash()), "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); assert_eq!(realtx.get_weight(), 193*4); } @@ -696,7 +698,7 @@ mod tests { let mut tx: Transaction = deserialize(&hex_tx).unwrap(); let old_ntxid = tx.ntxid(); - assert_eq!(old_ntxid.be_hex_string(), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"); + assert_eq!(format!("{:x}", old_ntxid), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"); // changing sigs does not affect it tx.input[0].script_sig = Script::new(); assert_eq!(old_ntxid, tx.ntxid()); @@ -740,8 +742,8 @@ mod tests { ).unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap(); - assert_eq!(tx.bitcoin_hash().be_hex_string(), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); - assert_eq!(tx.txid().be_hex_string(), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); + assert_eq!(format!("{:x}", tx.bitcoin_hash()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); + assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); assert_eq!(tx.get_weight(), 2718); // non-segwit tx from my mempool @@ -755,8 +757,8 @@ mod tests { ).unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap(); - assert_eq!(tx.bitcoin_hash().be_hex_string(), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); - assert_eq!(tx.txid().be_hex_string(), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); + assert_eq!(format!("{:x}", tx.bitcoin_hash()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); + assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); } #[test] @@ -775,7 +777,7 @@ mod tests { let script = Script::from(hex_bytes(script).unwrap()); let mut raw_expected = hex_bytes(expected_result).unwrap(); raw_expected.reverse(); - let expected_result = Sha256dHash::from(&raw_expected[..]); + let expected_result = sha256d::Hash::from_slice(&raw_expected[..]).unwrap(); let actual_result = tx.signature_hash(input_index, &script, hash_type as u32); assert_eq!(actual_result, expected_result); diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 49d0229c..cdbe2732 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -33,8 +33,6 @@ use std::collections::HashMap; use std::hash::Hash; use std::{mem, u32}; -use util::hash::Sha256dHash; - use std::error; use std::fmt; use std::io; @@ -566,7 +564,7 @@ impl> Decodable for Option { /// Do a double-SHA256 on some data and return the first 4 bytes fn sha2_checksum(data: &[u8]) -> [u8; 4] { - let checksum = Sha256dHash::from_data(data); + let checksum = ::hash(data); [checksum[0], checksum[1], checksum[2], checksum[3]] } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 8d5d51fa..d4f39f6e 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -299,7 +299,7 @@ macro_rules! display_from_debug { macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from(::hex::decode($s).unwrap()))); #[cfg(test)] -macro_rules! hex_hash (($s:expr) => (::util::hash::Sha256dHash::from(&::hex::decode($s).unwrap()[..]))); +macro_rules! hex_hash (($s:expr) => (::bitcoin_hashes::sha256d::Hash::from_slice(&::hex::decode($s).unwrap()).unwrap())); macro_rules! serde_struct_impl { ($name:ident, $($fe:ident),*) => ( diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 8c9755f1..67834d86 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -21,7 +21,7 @@ use network::constants; use consensus::encode::{Decodable, Encodable}; use consensus::encode::{self, Decoder, Encoder}; -use util::hash::Sha256dHash; +use bitcoin_hashes::sha256d; #[derive(PartialEq, Eq, Clone, Debug)] /// The type of an inventory object @@ -48,9 +48,9 @@ pub struct GetBlocksMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the block to stop at, or zero to just fetch the maximum 500 blocks - pub stop_hash: Sha256dHash + pub stop_hash: sha256d::Hash, } /// The `getheaders` message @@ -61,9 +61,9 @@ pub struct GetHeadersMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the header to stop at, or zero to just fetch the maximum 2000 headers - pub stop_hash: Sha256dHash + pub stop_hash: sha256d::Hash } /// An inventory object --- a reference to a Bitcoin object @@ -72,12 +72,12 @@ pub struct Inventory { /// The type of object that is referenced pub inv_type: InvType, /// The object's hash - pub hash: Sha256dHash + pub hash: sha256d::Hash } impl GetBlocksMessage { /// Construct a new `getblocks` message - pub fn new(locator_hashes: Vec, stop_hash: Sha256dHash) -> GetBlocksMessage { + pub fn new(locator_hashes: Vec, stop_hash: sha256d::Hash) -> GetBlocksMessage { GetBlocksMessage { version: constants::PROTOCOL_VERSION, locator_hashes: locator_hashes.clone(), @@ -90,7 +90,7 @@ impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash); impl GetHeadersMessage { /// Construct a new `getheaders` message - pub fn new(locator_hashes: Vec, stop_hash: Sha256dHash) -> GetHeadersMessage { + pub fn new(locator_hashes: Vec, stop_hash: sha256d::Hash) -> GetHeadersMessage { GetHeadersMessage { version: constants::PROTOCOL_VERSION, locator_hashes: locator_hashes, diff --git a/src/util/address.rs b/src/util/address.rs index 08787ab3..74ca6a43 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -51,6 +51,7 @@ use std::fmt::{self, Display, Formatter}; use std::str::FromStr; use bitcoin_bech32::{self, WitnessProgram, u5}; +use bitcoin_hashes::{hash160, Hash}; use secp256k1::key::PublicKey; #[cfg(feature = "serde")] @@ -60,7 +61,6 @@ use blockdata::opcodes; use blockdata::script; use network::constants::Network; use consensus::encode; -use util::hash::Hash160; use util::base58; /// The method used to produce an address @@ -69,9 +69,9 @@ pub enum Payload { /// pay-to-pubkey Pubkey(PublicKey), /// pay-to-pkhash address - PubkeyHash(Hash160), + PubkeyHash(hash160::Hash), /// P2SH address - ScriptHash(Hash160), + ScriptHash(hash160::Hash), /// Segwit address WitnessProgram(WitnessProgram), } @@ -92,7 +92,7 @@ impl Address { pub fn p2pkh(pk: &PublicKey, network: Network) -> Address { Address { network: network, - payload: Payload::PubkeyHash(Hash160::from_data(&pk.serialize()[..])) + payload: Payload::PubkeyHash(hash160::Hash::hash(&pk.serialize()[..])) } } @@ -103,7 +103,7 @@ impl Address { pub fn p2upkh(pk: &PublicKey, network: Network) -> Address { Address { network: network, - payload: Payload::PubkeyHash(Hash160::from_data(&pk.serialize_uncompressed()[..])) + payload: Payload::PubkeyHash(hash160::Hash::hash(&pk.serialize_uncompressed()[..])) } } @@ -124,7 +124,7 @@ impl Address { pub fn p2sh(script: &script::Script, network: Network) -> Address { Address { network: network, - payload: Payload::ScriptHash(Hash160::from_data(&script[..])) + payload: Payload::ScriptHash(hash160::Hash::hash(&script[..])) } } @@ -136,7 +136,7 @@ impl Address { payload: Payload::WitnessProgram( // unwrap is safe as witness program is known to be correct as above WitnessProgram::new(u5::try_from_u8(0).expect("0<32"), - Hash160::from_data(&pk.serialize()[..])[..].to_vec(), + hash160::Hash::hash(&pk.serialize()[..])[..].to_vec(), Address::bech_network(network)).unwrap()) } } @@ -146,24 +146,19 @@ impl Address { pub fn p2shwpkh (pk: &PublicKey, network: Network) -> Address { let builder = script::Builder::new() .push_int(0) - .push_slice(&Hash160::from_data(&pk.serialize()[..])[..]); + .push_slice(&hash160::Hash::hash(&pk.serialize()[..])[..]); Address { network: network, payload: Payload::ScriptHash( - Hash160::from_data(builder.into_script().as_bytes()) + hash160::Hash::hash(builder.into_script().as_bytes()) ) } } /// Create a witness pay to script hash address pub fn p2wsh (script: &script::Script, network: Network) -> Address { - use crypto::sha2::Sha256; - use crypto::digest::Digest; - - let mut digest = Sha256::new(); - digest.input(script.as_bytes()); - let mut d = [0u8; 32]; - digest.result(&mut d); + use bitcoin_hashes::sha256; + use bitcoin_hashes::Hash; Address { network: network, @@ -171,7 +166,7 @@ impl Address { // unwrap is safe as witness program is known to be correct as above WitnessProgram::new( u5::try_from_u8(0).expect("0<32"), - d.to_vec(), + sha256::Hash::hash(&script[..])[..].to_vec(), Address::bech_network(network) ).unwrap() ) @@ -181,18 +176,17 @@ impl Address { /// Create a pay to script address that embeds a witness pay to script hash address /// This is a segwit address type that looks familiar (as p2sh) to legacy clients pub fn p2shwsh (script: &script::Script, network: Network) -> Address { - use crypto::sha2::Sha256; - use crypto::digest::Digest; + use bitcoin_hashes::sha256; + use bitcoin_hashes::Hash; + use bitcoin_hashes::hash160; - let mut digest = Sha256::new(); - digest.input(script.as_bytes()); - let mut d = [0u8; 32]; - digest.result(&mut d); - let ws = script::Builder::new().push_int(0).push_slice(&d).into_script(); + let ws = script::Builder::new().push_int(0) + .push_slice(&sha256::Hash::hash(&script[..])[..]) + .into_script(); Address { network: network, - payload: Payload::ScriptHash(Hash160::from_data(ws.as_bytes())) + payload: Payload::ScriptHash(hash160::Hash::hash(&ws[..])) } } @@ -242,7 +236,7 @@ impl Display for Address { match self.payload { // note: serialization for pay-to-pk is defined, but is irreversible Payload::Pubkey(ref pk) => { - let hash = &Hash160::from_data(&pk.serialize_uncompressed()[..]); + let hash = &hash160::Hash::hash(&pk.serialize_uncompressed()[..]); let mut prefixed = [0; 21]; prefixed[0] = match self.network { Network::Bitcoin => 0, @@ -315,19 +309,19 @@ impl FromStr for Address { let (network, payload) = match data[0] { 0 => ( Network::Bitcoin, - Payload::PubkeyHash(Hash160::from(&data[1..])) + Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap()) ), 5 => ( Network::Bitcoin, - Payload::ScriptHash(Hash160::from(&data[1..])) + Payload::ScriptHash(hash160::Hash::from_slice(&data[1..]).unwrap()) ), 111 => ( Network::Testnet, - Payload::PubkeyHash(Hash160::from(&data[1..])) + Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap()) ), 196 => ( Network::Testnet, - Payload::ScriptHash(Hash160::from(&data[1..])) + Payload::ScriptHash(hash160::Hash::from_slice(&data[1..]).unwrap()) ), x => return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![x]))) }; @@ -403,24 +397,25 @@ mod tests { use std::str::FromStr; use std::string::ToString; + use bitcoin_hashes::{hash160, Hash}; use secp256k1::key::PublicKey; use hex::decode as hex_decode; use blockdata::script::Script; use network::constants::Network::{Bitcoin, Testnet, Regtest}; - use util::hash::Hash160; use super::*; macro_rules! hex (($hex:expr) => (hex_decode($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_hash160 (($hex:expr) => (hash160::Hash::from_slice(&hex!($hex)).unwrap())); #[test] fn test_p2pkh_address_58() { let addr = Address { network: Bitcoin, payload: Payload::PubkeyHash( - Hash160::from(&hex_decode("162c5ea71c0b23f5b9022ef047c4a86470a5b070").unwrap()[..]) + hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070") ) }; @@ -453,7 +448,7 @@ mod tests { let addr = Address { network: Bitcoin, payload: Payload::ScriptHash( - Hash160::from(&hex_decode("162c5ea71c0b23f5b9022ef047c4a86470a5b070").unwrap()[..]) + hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070") ) }; diff --git a/src/util/base58.rs b/src/util/base58.rs index 296bef53..8036e8d8 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -17,7 +17,8 @@ use std::{error, fmt, str, slice, iter}; use byteorder::{ByteOrder, LittleEndian}; -use util::hash::Sha256dHash; + +use bitcoin_hashes::{sha256d, Hash}; /// An error that might occur during base58 decoding #[derive(Debug, PartialEq, Eq, Clone)] @@ -161,7 +162,7 @@ pub fn from_check(data: &str) -> Result, Error> { return Err(Error::TooShort(ret.len())); } let ck_start = ret.len() - 4; - let expected = Sha256dHash::from_data(&ret[..ck_start]).into_le().low_u32(); + let expected = LittleEndian::read_u32(&sha256d::Hash::hash(&ret[..ck_start])[..4]); let actual = LittleEndian::read_u32(&ret[ck_start..(ck_start + 4)]); if expected != actual { return Err(Error::BadChecksum(expected, actual)); @@ -230,7 +231,7 @@ pub fn encode_slice(data: &[u8]) -> String { /// Obtain a string with the base58check encoding of a slice /// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.) pub fn check_encode_slice(data: &[u8]) -> String { - let checksum = Sha256dHash::from_data(&data); + let checksum = sha256d::Hash::hash(&data); encode_iter( data.iter() .cloned() @@ -241,7 +242,7 @@ pub fn check_encode_slice(data: &[u8]) -> String { /// Obtain a string with the base58check encoding of a slice /// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.) pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result { - let checksum = Sha256dHash::from_data(&data); + let checksum = sha256d::Hash::hash(&data); let iter = data.iter() .cloned() .chain(checksum[0..4].iter().cloned()); diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 525b4ec5..72712f19 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -19,10 +19,11 @@ //! signatures, which are placed in the scriptSig. //! +use bitcoin_hashes::{sha256d, Hash}; + use blockdata::script::Script; use blockdata::transaction::{Transaction, TxIn}; use consensus::encode::Encodable; -use util::hash::{Sha256dHash, Sha256dEncoder}; /// 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 @@ -31,11 +32,11 @@ pub struct SighashComponents { tx_version: u32, tx_locktime: u32, /// Hash of all the previous outputs - pub hash_prevouts: Sha256dHash, + pub hash_prevouts: sha256d::Hash, /// Hash of all the input sequence nos - pub hash_sequence: Sha256dHash, + pub hash_sequence: sha256d::Hash, /// Hash of all the outputs in this transaction - pub hash_outputs: Sha256dHash, + pub hash_outputs: sha256d::Hash, } impl SighashComponents { @@ -45,27 +46,27 @@ impl SighashComponents { /// script_sig and witnesses. pub fn new(tx: &Transaction) -> SighashComponents { let hash_prevouts = { - let mut enc = Sha256dEncoder::new(); + let mut enc = sha256d::Hash::engine(); for txin in &tx.input { txin.previous_output.consensus_encode(&mut enc).unwrap(); } - enc.into_hash() + sha256d::Hash::from_engine(enc) }; let hash_sequence = { - let mut enc = Sha256dEncoder::new(); + let mut enc = sha256d::Hash::engine(); for txin in &tx.input { txin.sequence.consensus_encode(&mut enc).unwrap(); } - enc.into_hash() + sha256d::Hash::from_engine(enc) }; let hash_outputs = { - let mut enc = Sha256dEncoder::new(); + let mut enc = sha256d::Hash::engine(); for txout in &tx.output { txout.consensus_encode(&mut enc).unwrap(); } - enc.into_hash() + sha256d::Hash::from_engine(enc) }; SighashComponents { @@ -79,8 +80,8 @@ impl SighashComponents { /// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given /// input. - pub fn sighash_all(&self, txin: &TxIn, witness_script: &Script, value: u64) -> Sha256dHash { - let mut enc = Sha256dEncoder::new(); + pub fn sighash_all(&self, txin: &TxIn, witness_script: &Script, value: u64) -> sha256d::Hash { + let mut enc = sha256d::Hash::engine(); self.tx_version.consensus_encode(&mut enc).unwrap(); self.hash_prevouts.consensus_encode(&mut enc).unwrap(); self.hash_sequence.consensus_encode(&mut enc).unwrap(); @@ -94,7 +95,7 @@ impl SighashComponents { self.hash_outputs.consensus_encode(&mut enc).unwrap(); self.tx_locktime.consensus_encode(&mut enc).unwrap(); 1u32.consensus_encode(&mut enc).unwrap(); // hashtype - enc.into_hash() + sha256d::Hash::from_engine(enc) } } diff --git a/src/util/bip32.rs b/src/util/bip32.rs index a250dc3a..dc2f6eeb 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -23,19 +23,13 @@ use std::str::FromStr; #[cfg(feature = "serde")] use serde; use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; -use crypto::digest::Digest; -use crypto::hmac::Hmac; -use crypto::mac::Mac; -use crypto::ripemd160::Ripemd160; +use bitcoin_hashes::{hash160, sha512, Hash, HashEngine, Hmac, HmacEngine}; use secp256k1::key::{PublicKey, SecretKey}; use secp256k1::{self, Secp256k1}; use network::constants::Network; use util::base58; -#[cfg(feature="fuzztarget")] use fuzz_util::sha2::{Sha256, Sha512}; -#[cfg(not(feature="fuzztarget"))] use crypto::sha2::{Sha256, Sha512}; - /// A chain code pub struct ChainCode([u8; 32]); impl_array_newtype!(ChainCode, u8, 32); @@ -49,7 +43,7 @@ impl_array_newtype_show!(Fingerprint); impl_array_newtype_encodable!(Fingerprint, u8, 4); impl Default for Fingerprint { - fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) } + fn default() -> Fingerprint { Fingerprint([0; 4]) } } /// Extended private key @@ -237,18 +231,17 @@ impl From for Error { impl ExtendedPrivKey { /// Construct a new master key from a seed value pub fn new_master(network: Network, seed: &[u8]) -> Result { - let mut result = [0; 64]; - let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed"); - hmac.input(seed); - hmac.raw_result(&mut result); + let mut hmac_engine: HmacEngine = HmacEngine::new(b"Bitcoin seed"); + hmac_engine.input(seed); + let hmac_result: Hmac = Hmac::from_engine(hmac_engine); Ok(ExtendedPrivKey { network: network, depth: 0, parent_fingerprint: Default::default(), child_number: ChildNumber::from_normal_idx(0), - secret_key: SecretKey::from_slice(&result[..32]).map_err(Error::Ecdsa)?, - chain_code: ChainCode::from(&result[32..]) + secret_key: SecretKey::from_slice(&hmac_result[..32]).map_err(Error::Ecdsa)?, + chain_code: ChainCode::from(&hmac_result[32..]), }) } @@ -267,25 +260,24 @@ impl ExtendedPrivKey { /// Private->Private child key derivation pub fn ckd_priv(&self, secp: &Secp256k1, i: ChildNumber) -> Result { - let mut result = [0; 64]; - let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]); + let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); let mut be_n = [0; 4]; match i { ChildNumber::Normal {..} => { // Non-hardened key: compute public data and use that - hmac.input(&PublicKey::from_secret_key(secp, &self.secret_key).serialize()[..]); + hmac_engine.input(&PublicKey::from_secret_key(secp, &self.secret_key).serialize()[..]); } ChildNumber::Hardened {..} => { // Hardened key: use only secret data to prevent public derivation - hmac.input(&[0u8]); - hmac.input(&self.secret_key[..]); + hmac_engine.input(&[0u8]); + hmac_engine.input(&self.secret_key[..]); } } BigEndian::write_u32(&mut be_n, u32::from(i)); - hmac.input(&be_n); - hmac.raw_result(&mut result); - let mut sk = SecretKey::from_slice(&result[..32]).map_err(Error::Ecdsa)?; + hmac_engine.input(&be_n); + let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + let mut sk = SecretKey::from_slice(&hmac_result[..32]).map_err(Error::Ecdsa)?; sk.add_assign(&self.secret_key[..]).map_err(Error::Ecdsa)?; Ok(ExtendedPrivKey { @@ -294,26 +286,13 @@ impl ExtendedPrivKey { parent_fingerprint: self.fingerprint(secp), child_number: i, secret_key: sk, - chain_code: ChainCode::from(&result[32..]) + chain_code: ChainCode::from(&hmac_result[32..]) }) } /// Returns the HASH160 of the chaincode - pub fn identifier(&self, secp: &Secp256k1) -> [u8; 20] { - let mut sha2_res = [0; 32]; - let mut ripemd_res = [0; 20]; - // Compute extended public key - let pk = ExtendedPubKey::from_private(secp, self); - // Do SHA256 of just the ECDSA pubkey - let mut sha2 = Sha256::new(); - sha2.input(&pk.public_key.serialize()[..]); - sha2.result(&mut sha2_res); - // do RIPEMD160 - let mut ripemd = Ripemd160::new(); - ripemd.input(&sha2_res); - ripemd.result(&mut ripemd_res); - // Return - ripemd_res + pub fn identifier(&self, secp: &Secp256k1) -> hash160::Hash { + ExtendedPubKey::from_private(secp, self).identifier() } /// Returns the first four bytes of the identifier @@ -355,17 +334,16 @@ impl ExtendedPubKey { Err(Error::CannotDeriveFromHardenedKey) } ChildNumber::Normal { index: n } => { - let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]); - hmac.input(&self.public_key.serialize()[..]); + let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); + hmac_engine.input(&self.public_key.serialize()[..]); let mut be_n = [0; 4]; BigEndian::write_u32(&mut be_n, n); - hmac.input(&be_n); + hmac_engine.input(&be_n); - let mut result = [0; 64]; - hmac.raw_result(&mut result); + let hmac_result: Hmac = Hmac::from_engine(hmac_engine); - let secret_key = SecretKey::from_slice(&result[..32])?; - let chain_code = ChainCode::from(&result[32..]); + let secret_key = SecretKey::from_slice(&hmac_result[..32])?; + let chain_code = ChainCode::from(&hmac_result[32..]); Ok((secret_key, chain_code)) } } @@ -392,19 +370,8 @@ impl ExtendedPubKey { } /// Returns the HASH160 of the chaincode - pub fn identifier(&self) -> [u8; 20] { - let mut sha2_res = [0; 32]; - let mut ripemd_res = [0; 20]; - // Do SHA256 of just the ECDSA pubkey - let mut sha2 = Sha256::new(); - sha2.input(&self.public_key.serialize()[..]); - sha2.result(&mut sha2_res); - // do RIPEMD160 - let mut ripemd = Ripemd160::new(); - ripemd.input(&sha2_res); - ripemd.result(&mut ripemd_res); - // Return - ripemd_res + pub fn identifier(&self) -> hash160::Hash { + hash160::Hash::hash(&self.public_key.serialize()) } /// Returns the first four bytes of the identifier diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 152da1d5..2bcd5842 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -20,17 +20,13 @@ use secp256k1::{self, Secp256k1}; use secp256k1::key::{PublicKey, SecretKey}; +use bitcoin_hashes::{hash160, sha256, Hash, HashEngine, Hmac, HmacEngine}; use blockdata::{opcodes, script}; -use crypto::hmac; -use crypto::mac::Mac; use std::{error, fmt}; use network::constants::Network; -use util::{address, hash}; - -#[cfg(feature="fuzztarget")] use fuzz_util::sha2; -#[cfg(not(feature="fuzztarget"))] use crypto::sha2; +use util::address; /// Encoding of "pubkey here" in script; from Bitcoin Core `src/script/script.h` static PUBKEY: u8 = 0xFE; @@ -173,11 +169,10 @@ impl<'a> From<&'a [u8]> for Template { pub fn tweak_keys(secp: &Secp256k1, keys: &[PublicKey], contract: &[u8]) -> Result, Error> { let mut ret = Vec::with_capacity(keys.len()); for mut key in keys.iter().cloned() { - let mut hmac_raw = [0; 32]; - let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &key.serialize()); - hmac.input(contract); - hmac.raw_result(&mut hmac_raw); - let hmac_sk = SecretKey::from_slice(&hmac_raw).map_err(Error::BadTweak)?; + let mut hmac_engine: HmacEngine = HmacEngine::new(&key.serialize()); + hmac_engine.input(contract); + let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + let hmac_sk = SecretKey::from_slice(&hmac_result[..]).map_err(Error::BadTweak)?; key.add_exp_assign(secp, &hmac_sk[..]).map_err(Error::Secp)?; ret.push(key); } @@ -186,11 +181,10 @@ pub fn tweak_keys(secp: &Secp256k1, keys: &[Publi /// Compute a tweak from some given data for the given public key pub fn compute_tweak(pk: &PublicKey, contract: &[u8]) -> Result { - let mut hmac_raw = [0; 32]; - let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &pk.serialize()); - hmac.input(contract); - hmac.raw_result(&mut hmac_raw); - SecretKey::from_slice(&hmac_raw).map_err(Error::BadTweak) + let mut hmac_engine: HmacEngine = HmacEngine::new(&pk.serialize()); + hmac_engine.input(contract); + let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + SecretKey::from_slice(&hmac_result[..]).map_err(Error::BadTweak) } /// Tweak a secret key using some arbitrary data (calls `compute_tweak` internally) @@ -218,7 +212,7 @@ pub fn create_address(secp: &Secp256k1, Ok(address::Address { network: network, payload: address::Payload::ScriptHash( - hash::Hash160::from_data(&script[..]) + hash160::Hash::hash(&script[..]) ) }) } diff --git a/src/util/hash.rs b/src/util/hash.rs index e0475b2c..f7d5ab0c 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -26,6 +26,7 @@ use std::mem; use crypto::digest::Digest; use crypto::ripemd160::Ripemd160; +use bitcoin_hashes::{sha256d, Hash}; use consensus::encode::{Encodable, Decodable}; use util::uint::Uint256; @@ -390,11 +391,11 @@ impl FromStr for Sha256dHash { pub trait MerkleRoot { /// Construct a merkle tree from a collection, with elements ordered as /// they were in the original collection, and return the merkle root. - fn merkle_root(&self) -> Sha256dHash; + fn merkle_root(&self) -> sha256d::Hash; } /// Calculates the merkle root of a list of txids hashes directly -pub fn bitcoin_merkle_root(data: Vec) -> Sha256dHash { +pub fn bitcoin_merkle_root(data: Vec) -> sha256d::Hash { // Base case if data.len() < 1 { return Default::default(); @@ -407,22 +408,22 @@ pub fn bitcoin_merkle_root(data: Vec) -> Sha256dHash { for idx in 0..((data.len() + 1) / 2) { let idx1 = 2 * idx; let idx2 = min(idx1 + 1, data.len() - 1); - let mut encoder = Sha256dEncoder::new(); + let mut encoder = sha256d::Hash::engine(); data[idx1].consensus_encode(&mut encoder).unwrap(); data[idx2].consensus_encode(&mut encoder).unwrap(); - next.push(encoder.into_hash()); + next.push(sha256d::Hash::from_engine(encoder)); } bitcoin_merkle_root(next) } impl<'a, T: BitcoinHash> MerkleRoot for &'a [T] { - fn merkle_root(&self) -> Sha256dHash { + fn merkle_root(&self) -> sha256d::Hash { bitcoin_merkle_root(self.iter().map(|obj| obj.bitcoin_hash()).collect()) } } impl MerkleRoot for Vec { - fn merkle_root(&self) -> Sha256dHash { + fn merkle_root(&self) -> sha256d::Hash { (&self[..]).merkle_root() } } @@ -430,7 +431,7 @@ impl MerkleRoot for Vec { /// 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) -> Sha256dHash; + fn bitcoin_hash(&self) -> sha256d::Hash; } #[cfg(test)] From c830fb4629c7ab495248e23a766e0ee30cc51ed1 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 15:50:49 -0500 Subject: [PATCH 4/7] Remove code deprecated by bitcoin_hashes from util::hash --- src/util/hash.rs | 486 +---------------------------------------------- 1 file changed, 1 insertion(+), 485 deletions(-) diff --git a/src/util/hash.rs b/src/util/hash.rs index f7d5ab0c..1de0f1b5 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -15,377 +15,12 @@ //! //! Utility functions related to hashing data, including merkleization -use std::char::from_digit; use std::cmp::min; use std::default::Default; -use std::error; -use std::fmt; -use std::io::{self, Write}; -use std::mem; -#[cfg(feature = "serde")] use serde; -use crypto::digest::Digest; -use crypto::ripemd160::Ripemd160; use bitcoin_hashes::{sha256d, Hash}; -use consensus::encode::{Encodable, Decodable}; -use util::uint::Uint256; - -#[cfg(feature="fuzztarget")] use fuzz_util::sha2::Sha256; -#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256; -use std::str::FromStr; - -/// Hex deserialization error -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum HexError { - /// Length was not 64 characters - BadLength(usize), - /// Non-hex character in string - BadCharacter(char) -} - -impl fmt::Display for HexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - HexError::BadLength(n) => write!(f, "bad length {} for sha256d hex string", n), - HexError::BadCharacter(c) => write!(f, "bad character {} in sha256d hex string", c) - } - } -} - -impl error::Error for HexError { - fn cause(&self) -> Option<&error::Error> { None } - fn description(&self) -> &str { - match *self { - HexError::BadLength(_) => "sha256d hex string non-64 length", - HexError::BadCharacter(_) => "sha256d bad hex character" - } - } -} - -/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x)) -pub struct Sha256dHash([u8; 32]); -impl_array_newtype!(Sha256dHash, u8, 32); - -/// An object that allows serializing data into a sha256d -pub struct Sha256dEncoder(Sha256); - -/// A RIPEMD-160 hash -pub struct Ripemd160Hash([u8; 20]); -impl_array_newtype!(Ripemd160Hash, u8, 20); - -/// A Bitcoin hash160, 20-bytes, computed from x as RIPEMD160(SHA256(x)) -pub struct Hash160([u8; 20]); -impl_array_newtype!(Hash160, u8, 20); - -/// A 32-bit hash obtained by truncating a real hash -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Hash32((u8, u8, u8, u8)); - -/// A 48-bit hash obtained by truncating a real hash -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Hash48((u8, u8, u8, u8, u8, u8)); - -/// A 64-bit hash obtained by truncating a real hash -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Hash64((u8, u8, u8, u8, u8, u8, u8, u8)); - -impl Sha256dEncoder { - /// Create a new encoder - pub fn new() -> Sha256dEncoder { - Sha256dEncoder(Sha256::new()) - } - - /// Extract the hash from an encoder - pub fn into_hash(mut self) -> Sha256dHash { - let mut second_sha = Sha256::new(); - let mut tmp = [0; 32]; - self.0.result(&mut tmp); - second_sha.input(&tmp); - second_sha.result(&mut tmp); - Sha256dHash(tmp) - } -} - -impl Write for Sha256dEncoder { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.input(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl Ripemd160Hash { - /// Create a hash by hashing some data - pub fn from_data(data: &[u8]) -> Ripemd160Hash { - let mut ret = [0; 20]; - let mut rmd = Ripemd160::new(); - rmd.input(data); - rmd.result(&mut ret); - Ripemd160Hash(ret) - } -} - -impl Hash160 { - /// Create a hash by hashing some data - pub fn from_data(data: &[u8]) -> Hash160 { - let mut tmp = [0; 32]; - let mut ret = [0; 20]; - let mut sha2 = Sha256::new(); - let mut rmd = Ripemd160::new(); - sha2.input(data); - sha2.result(&mut tmp); - rmd.input(&tmp); - rmd.result(&mut ret); - Hash160(ret) - } -} - -// This doesn't make much sense to me, but is implicit behaviour -// in the C++ reference client, so we need it for consensus. -impl Default for Sha256dHash { - #[inline] - fn default() -> Sha256dHash { Sha256dHash([0u8; 32]) } -} - -impl Sha256dHash { - /// Create a hash by hashing some data - pub fn from_data(data: &[u8]) -> Sha256dHash { - let Sha256dHash(mut ret): Sha256dHash = Default::default(); - let mut sha2 = Sha256::new(); - sha2.input(data); - sha2.result(&mut ret); - sha2.reset(); - sha2.input(&ret); - sha2.result(&mut ret); - Sha256dHash(ret) - } - - /// Converts a hash to a little-endian Uint256 - #[inline] - pub fn into_le(self) -> Uint256 { - let Sha256dHash(data) = self; - let mut ret: [u64; 4] = unsafe { mem::transmute(data) }; - for x in (&mut ret).iter_mut() { *x = x.to_le(); } - Uint256(ret) - } - - /// Converts a hash to a big-endian Uint256 - #[inline] - pub fn into_be(self) -> Uint256 { - let Sha256dHash(mut data) = self; - data.reverse(); - let mut ret: [u64; 4] = unsafe { mem::transmute(data) }; - for x in (&mut ret).iter_mut() { *x = x.to_be(); } - Uint256(ret) - } - - /// Converts a hash to a Hash32 by truncation - #[inline] - pub fn into_hash32(self) -> Hash32 { - let Sha256dHash(data) = self; - unsafe { mem::transmute([data[0], data[8], data[16], data[24]]) } - } - - /// Converts a hash to a Hash48 by truncation - #[inline] - pub fn into_hash48(self) -> Hash48 { - let Sha256dHash(data) = self; - unsafe { mem::transmute([data[0], data[6], data[12], data[18], data[24], data[30]]) } - } - - // Human-readable hex output - - /// Decodes a big-endian (i.e. reversed vs sha256sum output) hex string as a Sha256dHash - #[inline] - pub fn from_hex(s: &str) -> Result { - if s.len() != 64 { - return Err(HexError::BadLength(s.len())); - } - - let bytes = s.as_bytes(); - let mut ret = [0; 32]; - for i in 0..32 { - let hi = match bytes[2*i] { - b @ b'0'...b'9' => (b - b'0') as u8, - b @ b'a'...b'f' => (b - b'a' + 10) as u8, - b @ b'A'...b'F' => (b - b'A' + 10) as u8, - b => return Err(HexError::BadCharacter(b as char)) - }; - let lo = match bytes[2*i + 1] { - b @ b'0'...b'9' => (b - b'0') as u8, - b @ b'a'...b'f' => (b - b'a' + 10) as u8, - b @ b'A'...b'F' => (b - b'A' + 10) as u8, - b => return Err(HexError::BadCharacter(b as char)) - }; - ret[31 - i] = hi * 0x10 + lo; - } - Ok(Sha256dHash(ret)) - } - - /// Converts a hash to a Hash64 by truncation - #[inline] - pub fn into_hash64(self) -> Hash64 { - let Sha256dHash(data) = self; - unsafe { mem::transmute([data[0], data[4], data[8], data[12], - data[16], data[20], data[24], data[28]]) } - } - - /// Human-readable hex output - pub fn le_hex_string(&self) -> String { - let &Sha256dHash(data) = self; - let mut ret = String::with_capacity(64); - for item in data.iter().take(32) { - ret.push(from_digit((*item / 0x10) as u32, 16).unwrap()); - ret.push(from_digit((*item & 0x0f) as u32, 16).unwrap()); - } - ret - } - - /// Human-readable hex output - pub fn be_hex_string(&self) -> String { - let &Sha256dHash(data) = self; - let mut ret = String::with_capacity(64); - for i in (0..32).rev() { - ret.push(from_digit((data[i] / 0x10) as u32, 16).unwrap()); - ret.push(from_digit((data[i] & 0x0f) as u32, 16).unwrap()); - } - ret - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for Sha256dHash { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - use std::fmt::{self, Formatter}; - - struct Visitor; - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = Sha256dHash; - - fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { - formatter.write_str("a SHA256d hash") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - Sha256dHash::from_hex(v).map_err(E::custom) - } - - fn visit_borrowed_str(self, v: &'de str) -> Result - where - E: serde::de::Error, - { - self.visit_str(v) - } - - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - self.visit_str(&v) - } - } - - deserializer.deserialize_str(Visitor) - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Sha256dHash { - /// Serialize a `Sha256dHash`. - /// - /// Note that this outputs hashes as big endian hex numbers, so this should be - /// used only for user-facing stuff. Internal and network serialization is - /// little-endian and should be done using the consensus - /// [`Encodable`][1] interface. - /// - /// [1]: ../../network/encodable/trait.Encodable.html - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - use std::{char, str}; - - let mut string = [0; 64]; - for i in 0..32 { - string[2 * i] = char::from_digit((self.0[31 - i] / 0x10) as u32, 16).unwrap() as u8; - string[2 * i + 1] = char::from_digit((self.0[31 - i] & 0x0f) as u32, 16).unwrap() as u8; - } - - let hex_str = unsafe { str::from_utf8_unchecked(&string) }; - serializer.serialize_str(hex_str) - } -} - -// Debug encodings -impl fmt::Debug for Sha256dHash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::LowerHex::fmt(self, f) - } -} - -impl fmt::Debug for Hash160 { - /// Output the raw hash160 hash, not reversing it (nothing reverses the output of ripemd160 in Bitcoin) - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &Hash160(data) = self; - for ch in data.iter() { - write!(f, "{:02x}", ch)?; - } - Ok(()) - } -} - -// Consensus encoding (no reversing) -impl_newtype_consensus_encoding!(Hash32); -impl_newtype_consensus_encoding!(Hash48); -impl_newtype_consensus_encoding!(Hash64); -impl_newtype_consensus_encoding!(Sha256dHash); - -// User RPC/display encoding (reversed) -impl fmt::Display for Sha256dHash { - /// Output the sha256d hash in reverse, copying Bitcoin Core's behaviour - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) } -} - -impl fmt::LowerHex for Sha256dHash { - /// Output the sha256d hash in reverse, copying Bitcoin Core's behaviour - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &Sha256dHash(data) = self; - for ch in data.iter().rev() { - write!(f, "{:02x}", ch)?; - } - Ok(()) - } -} - -impl fmt::UpperHex for Sha256dHash { - /// Output the sha256d hash in reverse, copying Bitcoin Core's behaviour - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &Sha256dHash(data) = self; - for ch in data.iter().rev() { - write!(f, "{:02X}", ch)?; - } - Ok(()) - } -} - -impl FromStr for Sha256dHash { - type Err = HexError; - - fn from_str(s: &str) -> Result::Err> { - Sha256dHash::from_hex(s) - } -} +use consensus::encode::Encodable; /// Any collection of objects for which a merkle root makes sense to calculate pub trait MerkleRoot { @@ -433,122 +68,3 @@ pub trait BitcoinHash { /// Produces a Sha256dHash which can be used to refer to the object fn bitcoin_hash(&self) -> sha256d::Hash; } - -#[cfg(test)] -mod tests { - #[cfg(all(feature = "serde", feature = "strason"))] - use strason::Json; - - use consensus::encode::{Encodable, VarInt}; - use consensus::encode::{serialize, deserialize}; - use util::uint::{Uint128, Uint256}; - use super::*; - - #[test] - fn test_sha256d() { - // nb the 5df6... output is the one you get from sha256sum. this is the - // "little-endian" hex string since it matches the in-memory representation - // of a Uint256 (which is little-endian) after transmutation - assert_eq!(Sha256dHash::from_data(&[]).le_hex_string(), - "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456"); - assert_eq!(Sha256dHash::from_data(&[]).be_hex_string(), - "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d"); - - assert_eq!(format!("{}", Sha256dHash::from_data(&[])), - "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d"); - assert_eq!(format!("{:?}", Sha256dHash::from_data(&[])), - "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d"); - assert_eq!(format!("{:x}", Sha256dHash::from_data(&[])), - "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d"); - assert_eq!(format!("{:X}", Sha256dHash::from_data(&[])), - "56944C5D3F98413EF45CF54545538103CC9F298E0575820AD3591376E2E0F65D"); - } - - #[test] - fn sha256d_from_str_parses_from_human_readable_hex() { - - let human_readable_hex_tx_id = "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d"; - - let from_hex = Sha256dHash::from_hex(human_readable_hex_tx_id).unwrap(); - let from_str = human_readable_hex_tx_id.parse().unwrap(); - - assert_eq!(from_hex, from_str) - } - - #[test] - fn test_sha256d_data() { - assert_eq!( - Sha256dHash::from_data(&[]).as_bytes(), - &[ - 0x5d, 0xf6, 0xe0, 0xe2, 0x76, 0x13, 0x59, 0xd3, 0x0a, 0x82, 0x75, 0x05, 0x8e, 0x29, - 0x9f, 0xcc, 0x03, 0x81, 0x53, 0x45, 0x45, 0xf5, 0x5c, 0xf4, 0x3e, 0x41, 0x98, 0x3f, - 0x5d, 0x4c, 0x94, 0x56, - ] - ); - } - - #[test] - fn sha256d_encoder() { - let test = vec![true, false, true, true, false]; - let mut enc = Sha256dEncoder::new(); - assert!(test.consensus_encode(&mut enc).is_ok()); - assert_eq!(enc.into_hash(), Sha256dHash::from_data(&serialize(&test))); - - macro_rules! array_encode_test ( - ($ty:ty) => ({ - // try serializing the whole array - let test: [$ty; 1000] = [1; 1000]; - let mut enc = Sha256dEncoder::new(); - assert!((&test[..]).consensus_encode(&mut enc).is_ok()); - assert_eq!(enc.into_hash(), Sha256dHash::from_data(&serialize(&test[..]))); - - // try doing it just one object at a time - let mut enc = Sha256dEncoder::new(); - assert!(VarInt(test.len() as u64).consensus_encode(&mut enc).is_ok()); - for obj in &test[..] { - assert!(obj.consensus_encode(&mut enc).is_ok()); - } - assert_eq!(enc.into_hash(), Sha256dHash::from_data(&serialize(&test[..]))); - }) - ); - - array_encode_test!(u64); - array_encode_test!(u32); - array_encode_test!(u16); - array_encode_test!(u8); - array_encode_test!(i64); - array_encode_test!(i32); - array_encode_test!(i16); - array_encode_test!(i8); - } - - #[test] - fn test_consenus_encode_roundtrip() { - let hash = Sha256dHash::from_data(&[]); - let serial = serialize(&hash); - let deserial = deserialize(&serial).unwrap(); - assert_eq!(hash, deserial); - } - - #[test] - #[cfg(all(feature = "serde", feature = "strason"))] - fn test_hash_encode_decode() { - let hash = Sha256dHash::from_data(&[]); - let encoded = Json::from_serialize(&hash).unwrap(); - assert_eq!(encoded.to_bytes(), - "\"56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d\"".as_bytes()); - let decoded = encoded.into_deserialize().unwrap(); - assert_eq!(hash, decoded); - } - - #[test] - fn test_sighash_single_vec() { - let one = Sha256dHash([1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0]); - assert_eq!(Some(one.into_le()), Uint256::from_u64(1)); - assert_eq!(Some(one.into_le().low_128()), Uint128::from_u64(1)); - } -} - From 96f9c62b0ec168572134703211d95a36cb5d9575 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 16:01:26 -0500 Subject: [PATCH 5/7] Remove unused internal macro --- src/internal_macros.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index d4f39f6e..afa6b332 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -38,25 +38,6 @@ macro_rules! impl_consensus_encoding { ); } -macro_rules! impl_newtype_consensus_encoding { - ($thing:ident) => ( - impl ::consensus::encode::Encodable for $thing { - #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { - let &$thing(ref data) = self; - data.consensus_encode(s) - } - } - - impl ::consensus::encode::Decodable for $thing { - #[inline] - fn consensus_decode(d: &mut D) -> Result<$thing, ::consensus::encode::Error> { - Ok($thing(Decodable::consensus_decode(d)?)) - } - } - ); -} - macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:expr) => { impl $thing { From 1bbeda87ebdb101aad881adf69e975c078d9a02a Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 16:03:34 -0500 Subject: [PATCH 6/7] Remove fuzz_util module Not needed anymore as the bitcoin_hashes crate handles this. --- src/fuzz_util/mod.rs | 4 --- src/fuzz_util/sha2.rs | 63 ------------------------------------------- src/lib.rs | 3 --- 3 files changed, 70 deletions(-) delete mode 100644 src/fuzz_util/mod.rs delete mode 100644 src/fuzz_util/sha2.rs diff --git a/src/fuzz_util/mod.rs b/src/fuzz_util/mod.rs deleted file mode 100644 index bbf67d3d..00000000 --- a/src/fuzz_util/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! This module contains all mocks that are used for fuzz testing. Never use anything from this -//! module in production. - -pub mod sha2; \ No newline at end of file diff --git a/src/fuzz_util/sha2.rs b/src/fuzz_util/sha2.rs deleted file mode 100644 index 40b4e5b4..00000000 --- a/src/fuzz_util/sha2.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! fuzztarget-only Sha2 context with a dummy Sha256 and Sha512 hashers. - -use crypto::digest::Digest; - -#[derive(Clone, Copy)] -/// Dummy Sha256 that hashes the input, but only returns the first byte of output, masking the -/// rest to 0s. -pub struct Sha256 { - state: u8, -} - -impl Sha256 { - /// Constructs a new dummy Sha256 context - pub fn new() -> Sha256 { - Sha256 { - state: 0, - } - } -} - -impl Digest for Sha256 { - fn result(&mut self, data: &mut [u8]) { - data[0] = self.state; - for i in 1..32 { - data[i] = 0; - } - } - - fn input(&mut self, data: &[u8]) { for i in data { self.state ^= i; } } - fn reset(&mut self) { self.state = 0; } - fn output_bits(&self) -> usize { 256 } - fn block_size(&self) -> usize { 64 } -} - -#[derive(Clone, Copy)] -/// Dummy Sha512 that hashes the input, but only returns the first byte of output, masking the -/// rest to 0s. -pub struct Sha512 { - state: u8, -} - -impl Sha512 { - /// Constructs a new dummy Sha512 context - pub fn new() -> Sha512 { - Sha512 { - state: 0xff, - } - } -} - -impl Digest for Sha512 { - fn result(&mut self, data: &mut [u8]) { - data[0] = self.state; - for i in 1..64 { - data[i] = 0; - } - } - - fn input(&mut self, data: &[u8]) { for i in data { self.state ^= i; } } - fn reset(&mut self) { self.state = 0xff; } - fn output_bits(&self) -> usize { 512 } - fn block_size(&self) -> usize { 128 } -} diff --git a/src/lib.rs b/src/lib.rs index 9f187492..199dc2f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,3 @@ pub use util::hash::BitcoinHash; pub use util::privkey::Privkey; pub use util::decimal::Decimal; pub use util::decimal::UDecimal; - -#[cfg(feature = "fuzztarget")] -pub mod fuzz_util; From ca72a04dd41faf0c4d5ae4d5dcab853b98442171 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 16 Jan 2019 16:04:33 -0500 Subject: [PATCH 7/7] Remove rust-crypto dependency We no longer need rust-crypto after integrating bitcoin_hashes. --- Cargo.toml | 1 - src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eae14d32..92c78923 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ use-serde = ["serde", "bitcoin_hashes/serde"] bitcoin-bech32 = "0.8.0" byteorder = "1.2" rand = "0.3" -rust-crypto = "0.2" bitcoin_hashes = "0.3" bitcoinconsensus = { version = "0.16", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 199dc2f2..a4277e93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,6 @@ extern crate bitcoin_bech32; extern crate bitcoin_hashes; extern crate byteorder; -extern crate crypto; extern crate hex; extern crate rand; extern crate secp256k1;