Convert codebase from util::hash to bitcoin_hashes

Also replace unsafe transmute with call to read_u64_into
This commit is contained in:
Carl Dong 2019-01-16 15:45:31 -05:00
parent 45aa709467
commit 99f63a8ca4
13 changed files with 162 additions and 204 deletions

View File

@ -20,9 +20,11 @@
//! these blocks and the blockchain. //! these blocks and the blockchain.
//! //!
use bitcoin_hashes::{sha256d, Hash};
use util; use util;
use util::Error::{SpvBadTarget, SpvBadProofOfWork}; use util::Error::{SpvBadTarget, SpvBadProofOfWork};
use util::hash::{BitcoinHash, Sha256dHash}; use util::hash::BitcoinHash;
use util::uint::Uint256; use util::uint::Uint256;
use consensus::encode::VarInt; use consensus::encode::VarInt;
use network::constants::Network; use network::constants::Network;
@ -36,9 +38,9 @@ pub struct BlockHeader {
/// The protocol version. Should always be 1. /// The protocol version. Should always be 1.
pub version: u32, pub version: u32,
/// Reference to the previous block in the chain /// 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 /// 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 /// The timestamp of the block, as claimed by the miner
pub time: u32, pub time: u32,
/// The target value below which the blockhash must lie, encoded as a /// 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 /// is correct, but does not verify that the transactions are valid or encoded
/// correctly. /// correctly.
pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> { pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> {
use byteorder::{ByteOrder, LittleEndian};
let target = &self.target(); let target = &self.target();
if target != required_target { if target != required_target {
return Err(SpvBadTarget); 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) } if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
} }
@ -141,14 +148,14 @@ impl BlockHeader {
} }
impl BitcoinHash for BlockHeader { impl BitcoinHash for BlockHeader {
fn bitcoin_hash(&self) -> Sha256dHash { fn bitcoin_hash(&self) -> sha256d::Hash {
use consensus::encode::serialize; use consensus::encode::serialize;
Sha256dHash::from_data(&serialize(self)) sha256d::Hash::hash(&serialize(self))
} }
} }
impl BitcoinHash for Block { impl BitcoinHash for Block {
fn bitcoin_hash(&self) -> Sha256dHash { fn bitcoin_hash(&self) -> sha256d::Hash {
self.header.bitcoin_hash() self.header.bitcoin_hash()
} }
} }

View File

@ -166,7 +166,7 @@ mod test {
assert_eq!(gen.output[0].value, 50 * COIN_VALUE); assert_eq!(gen.output[0].value, 50 * COIN_VALUE);
assert_eq!(gen.lock_time, 0); assert_eq!(gen.lock_time, 0);
assert_eq!(gen.bitcoin_hash().be_hex_string(), assert_eq!(format!("{:x}", gen.bitcoin_hash()),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
} }
@ -176,12 +176,12 @@ mod test {
assert_eq!(gen.header.version, 1); assert_eq!(gen.header.version, 1);
assert_eq!(gen.header.prev_blockhash, Default::default()); 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()); "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
assert_eq!(gen.header.time, 1231006505); assert_eq!(gen.header.time, 1231006505);
assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.bits, 0x1d00ffff);
assert_eq!(gen.header.nonce, 2083236893); 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()); "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f".to_string());
} }
@ -190,12 +190,12 @@ mod test {
let gen = genesis_block(Network::Testnet); let gen = genesis_block(Network::Testnet);
assert_eq!(gen.header.version, 1); assert_eq!(gen.header.version, 1);
assert_eq!(gen.header.prev_blockhash, Default::default()); 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()); "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
assert_eq!(gen.header.time, 1296688602); assert_eq!(gen.header.time, 1296688602);
assert_eq!(gen.header.bits, 0x1d00ffff); assert_eq!(gen.header.bits, 0x1d00ffff);
assert_eq!(gen.header.nonce, 414098458); 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()); "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string());
} }
} }

View File

@ -27,19 +27,15 @@
use std::default::Default; use std::default::Default;
use std::{error, fmt}; use std::{error, fmt};
use crypto::digest::Digest;
#[cfg(feature = "serde")] use serde; #[cfg(feature = "serde")] use serde;
use blockdata::opcodes; use blockdata::opcodes;
use consensus::encode::{Decodable, Encodable}; use consensus::encode::{Decodable, Encodable};
use consensus::encode::{self, Decoder, Encoder}; 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 bitcoinconsensus;
#[cfg(feature="bitcoinconsensus")] use std::convert; #[cfg(feature="bitcoinconsensus")] use std::convert;
#[cfg(feature="bitcoinconsensus")] use util::hash::Sha256dHash; #[cfg(feature="bitcoinconsensus")] use bitcoin_hashes::sha256d;
#[cfg(feature="fuzztarget")] use fuzz_util::sha2::Sha256;
#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256;
#[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)] #[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
/// A Bitcoin script /// A Bitcoin script
@ -163,7 +159,7 @@ pub enum Error {
BitcoinConsensus(bitcoinconsensus::Error), BitcoinConsensus(bitcoinconsensus::Error),
#[cfg(feature="bitcoinconsensus")] #[cfg(feature="bitcoinconsensus")]
/// Can not find the spent transaction /// Can not find the spent transaction
UnknownSpentTransaction(Sha256dHash), UnknownSpentTransaction(sha256d::Hash),
#[cfg(feature="bitcoinconsensus")] #[cfg(feature="bitcoinconsensus")]
/// The spent transaction does not have the referred output /// The spent transaction does not have the referred output
WrongSpentOutputIndex(usize), WrongSpentOutputIndex(usize),
@ -305,7 +301,7 @@ impl Script {
/// Compute the P2SH output corresponding to this redeem script /// Compute the P2SH output corresponding to this redeem script
pub fn to_p2sh(&self) -> Script { pub fn to_p2sh(&self) -> Script {
Builder::new().push_opcode(opcodes::all::OP_HASH160) 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) .push_opcode(opcodes::all::OP_EQUAL)
.into_script() .into_script()
} }
@ -313,12 +309,8 @@ impl Script {
/// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem /// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem
/// script") /// script")
pub fn to_v0_p2wsh(&self) -> 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) Builder::new().push_int(0)
.push_slice(&tmp) .push_slice(&sha256::Hash::hash(&self.0)[..])
.into_script() .into_script()
} }

View File

@ -28,7 +28,10 @@ use std::default::Default;
use std::fmt; use std::fmt;
#[cfg(feature="bitcoinconsensus")] use std::collections::HashMap; #[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; #[cfg(feature="bitcoinconsensus")] use blockdata::script;
use blockdata::script::Script; use blockdata::script::Script;
use consensus::encode::{self, serialize, Encoder, Decoder}; 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)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct OutPoint { pub struct OutPoint {
/// The referenced transaction's txid /// The referenced transaction's txid
pub txid: Sha256dHash, pub txid: sha256d::Hash,
/// The index of the referenced output in its transaction's vout /// The index of the referenced output in its transaction's vout
pub vout: u32, pub vout: u32,
} }
@ -93,7 +96,7 @@ impl fmt::Display for OutPoint {
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum ParseOutPointError { pub enum ParseOutPointError {
/// Error in TXID part. /// Error in TXID part.
Txid(HexError), Txid(bitcoin_hashes::Error),
/// Error in vout part. /// Error in vout part.
Vout(::std::num::ParseIntError), Vout(::std::num::ParseIntError),
/// Error in general format. /// Error in general format.
@ -164,7 +167,7 @@ impl ::std::str::FromStr for OutPoint {
return Err(ParseOutPointError::Format); return Err(ParseOutPointError::Format);
} }
Ok(OutPoint { 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..])?, vout: parse_vout(&s[colon+1..])?,
}) })
} }
@ -257,7 +260,7 @@ impl Transaction {
/// Computes a "normalized TXID" which does not include any signatures. /// Computes a "normalized TXID" which does not include any signatures.
/// This gives a way to identify a transaction that is ``the same'' as /// This gives a way to identify a transaction that is ``the same'' as
/// another in the sense of having same inputs and outputs. /// 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 { let cloned_tx = Transaction {
version: self.version, version: self.version,
lock_time: self.lock_time, lock_time: self.lock_time,
@ -271,15 +274,13 @@ impl Transaction {
/// to the output of `BitcoinHash::bitcoin_hash()`, but for segwit transactions, /// to the output of `BitcoinHash::bitcoin_hash()`, but for segwit transactions,
/// this will give the correct txid (not including witnesses) while `bitcoin_hash` /// this will give the correct txid (not including witnesses) while `bitcoin_hash`
/// will also hash witnesses. /// will also hash witnesses.
pub fn txid(&self) -> Sha256dHash { pub fn txid(&self) -> sha256d::Hash {
use util::hash::Sha256dEncoder; let mut enc = sha256d::Hash::engine();
let mut enc = Sha256dEncoder::new();
self.version.consensus_encode(&mut enc).unwrap(); self.version.consensus_encode(&mut enc).unwrap();
self.input.consensus_encode(&mut enc).unwrap(); self.input.consensus_encode(&mut enc).unwrap();
self.output.consensus_encode(&mut enc).unwrap(); self.output.consensus_encode(&mut enc).unwrap();
self.lock_time.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. /// Computes a signature hash for a given input index with a given sighash flag.
@ -295,17 +296,17 @@ impl Transaction {
/// # Panics /// # Panics
/// Panics if `input_index` is greater than or equal to `self.input.len()` /// 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 assert!(input_index < self.input.len()); // Panic on OOB
let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_u32).split_anyonecanpay_flag(); let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_u32).split_anyonecanpay_flag();
// Special-case sighash_single bug because this is easy enough. // Special-case sighash_single bug because this is easy enough.
if sighash == SigHashType::Single && input_index >= self.output.len() { if sighash == SigHashType::Single && input_index >= self.output.len() {
return Sha256dHash::from(&[1, 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, 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 // Build tx to sign
@ -350,7 +351,7 @@ impl Transaction {
// hash the result // hash the result
let mut raw_vec = serialize(&tx); let mut raw_vec = serialize(&tx);
raw_vec.write_u32::<LittleEndian>(sighash_u32).unwrap(); raw_vec.write_u32::<LittleEndian>(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 /// Gets the "weight" of this transaction, as defined by BIP141. For transactions with an empty
@ -397,7 +398,7 @@ impl Transaction {
#[cfg(feature="bitcoinconsensus")] #[cfg(feature="bitcoinconsensus")]
/// Verify that this transaction is able to spend some outputs of spent transactions /// Verify that this transaction is able to spend some outputs of spent transactions
pub fn verify(&self, spent: &HashMap<Sha256dHash, Transaction>) -> Result<(), script::Error> { pub fn verify(&self, spent: &HashMap<sha256d::Hash, Transaction>) -> Result<(), script::Error> {
let tx = serialize(&*self); let tx = serialize(&*self);
for (idx, input) in self.input.iter().enumerate() { for (idx, input) in self.input.iter().enumerate() {
if let Some(ref s) = spent.get(&input.previous_output.txid) { if let Some(ref s) = spent.get(&input.previous_output.txid) {
@ -420,12 +421,10 @@ impl Transaction {
} }
impl BitcoinHash for Transaction { impl BitcoinHash for Transaction {
fn bitcoin_hash(&self) -> Sha256dHash { fn bitcoin_hash(&self) -> sha256d::Hash {
use util::hash::Sha256dEncoder; let mut enc = sha256d::Hash::engine();
let mut enc = Sha256dEncoder::new();
self.consensus_encode(&mut enc).unwrap(); 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 blockdata::script::Script;
use consensus::encode::serialize; use consensus::encode::serialize;
use consensus::encode::deserialize; use consensus::encode::deserialize;
use util::hash::{BitcoinHash, Sha256dHash}; use util::hash::BitcoinHash;
use util::misc::hex_bytes; use util::misc::hex_bytes;
use bitcoin_hashes::{sha256d, Hash};
use bitcoin_hashes::hex::FromHex;
#[test] #[test]
fn test_outpoint() { fn test_outpoint() {
assert_eq!(OutPoint::from_str("i don't care"), assert_eq!(OutPoint::from_str("i don't care"),
@ -617,20 +619,20 @@ mod tests {
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"), assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"),
Err(ParseOutPointError::VoutNotCanonical)); Err(ParseOutPointError::VoutNotCanonical));
assert_eq!(OutPoint::from_str("i don't care:1"), 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"), 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"), assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"),
Err(ParseOutPointError::Vout(u32::from_str("lol").unwrap_err()))); Err(ParseOutPointError::Vout(u32::from_str("lol").unwrap_err())));
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"), assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"),
Ok(OutPoint{ Ok(OutPoint{
txid: Sha256dHash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
vout: 42, vout: 42,
})); }));
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"), assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"),
Ok(OutPoint{ Ok(OutPoint{
txid: Sha256dHash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
vout: 0, vout: 0,
})); }));
} }
@ -665,13 +667,13 @@ mod tests {
assert_eq!(realtx.input.len(), 1); assert_eq!(realtx.input.len(), 1);
// In particular this one is easy to get backward -- in bitcoin hashes are encoded // 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. // 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()); "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string());
assert_eq!(realtx.input[0].previous_output.vout, 1); assert_eq!(realtx.input[0].previous_output.vout, 1);
assert_eq!(realtx.output.len(), 1); assert_eq!(realtx.output.len(), 1);
assert_eq!(realtx.lock_time, 0); assert_eq!(realtx.lock_time, 0);
assert_eq!(realtx.bitcoin_hash().be_hex_string(), assert_eq!(format!("{:x}", realtx.bitcoin_hash()),
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
assert_eq!(realtx.get_weight(), 193*4); assert_eq!(realtx.get_weight(), 193*4);
} }
@ -696,7 +698,7 @@ mod tests {
let mut tx: Transaction = deserialize(&hex_tx).unwrap(); let mut tx: Transaction = deserialize(&hex_tx).unwrap();
let old_ntxid = tx.ntxid(); 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 // changing sigs does not affect it
tx.input[0].script_sig = Script::new(); tx.input[0].script_sig = Script::new();
assert_eq!(old_ntxid, tx.ntxid()); assert_eq!(old_ntxid, tx.ntxid());
@ -740,8 +742,8 @@ mod tests {
).unwrap(); ).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap();
assert_eq!(tx.bitcoin_hash().be_hex_string(), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); assert_eq!(format!("{:x}", tx.bitcoin_hash()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4");
assert_eq!(tx.txid().be_hex_string(), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec");
assert_eq!(tx.get_weight(), 2718); assert_eq!(tx.get_weight(), 2718);
// non-segwit tx from my mempool // non-segwit tx from my mempool
@ -755,8 +757,8 @@ mod tests {
).unwrap(); ).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap();
assert_eq!(tx.bitcoin_hash().be_hex_string(), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); assert_eq!(format!("{:x}", tx.bitcoin_hash()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
assert_eq!(tx.txid().be_hex_string(), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
} }
#[test] #[test]
@ -775,7 +777,7 @@ mod tests {
let script = Script::from(hex_bytes(script).unwrap()); let script = Script::from(hex_bytes(script).unwrap());
let mut raw_expected = hex_bytes(expected_result).unwrap(); let mut raw_expected = hex_bytes(expected_result).unwrap();
raw_expected.reverse(); 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); let actual_result = tx.signature_hash(input_index, &script, hash_type as u32);
assert_eq!(actual_result, expected_result); assert_eq!(actual_result, expected_result);

View File

@ -33,8 +33,6 @@ use std::collections::HashMap;
use std::hash::Hash; use std::hash::Hash;
use std::{mem, u32}; use std::{mem, u32};
use util::hash::Sha256dHash;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::io; use std::io;
@ -566,7 +564,7 @@ impl<D: Decoder, T:Decodable<D>> Decodable<D> for Option<T> {
/// Do a double-SHA256 on some data and return the first 4 bytes /// Do a double-SHA256 on some data and return the first 4 bytes
fn sha2_checksum(data: &[u8]) -> [u8; 4] { fn sha2_checksum(data: &[u8]) -> [u8; 4] {
let checksum = Sha256dHash::from_data(data); let checksum = <sha256d::Hash as HashTrait>::hash(data);
[checksum[0], checksum[1], checksum[2], checksum[3]] [checksum[0], checksum[1], checksum[2], checksum[3]]
} }

View File

@ -299,7 +299,7 @@ macro_rules! display_from_debug {
macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from(::hex::decode($s).unwrap()))); macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from(::hex::decode($s).unwrap())));
#[cfg(test)] #[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 { macro_rules! serde_struct_impl {
($name:ident, $($fe:ident),*) => ( ($name:ident, $($fe:ident),*) => (

View File

@ -21,7 +21,7 @@
use network::constants; use network::constants;
use consensus::encode::{Decodable, Encodable}; use consensus::encode::{Decodable, Encodable};
use consensus::encode::{self, Decoder, Encoder}; use consensus::encode::{self, Decoder, Encoder};
use util::hash::Sha256dHash; use bitcoin_hashes::sha256d;
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
/// The type of an inventory object /// The type of an inventory object
@ -48,9 +48,9 @@ pub struct GetBlocksMessage {
/// Locator hashes --- ordered newest to oldest. The remote peer will /// Locator hashes --- ordered newest to oldest. The remote peer will
/// reply with its longest known chain, starting from a locator hash /// reply with its longest known chain, starting from a locator hash
/// if possible and block 1 otherwise. /// if possible and block 1 otherwise.
pub locator_hashes: Vec<Sha256dHash>, pub locator_hashes: Vec<sha256d::Hash>,
/// References the block to stop at, or zero to just fetch the maximum 500 blocks /// 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 /// The `getheaders` message
@ -61,9 +61,9 @@ pub struct GetHeadersMessage {
/// Locator hashes --- ordered newest to oldest. The remote peer will /// Locator hashes --- ordered newest to oldest. The remote peer will
/// reply with its longest known chain, starting from a locator hash /// reply with its longest known chain, starting from a locator hash
/// if possible and block 1 otherwise. /// if possible and block 1 otherwise.
pub locator_hashes: Vec<Sha256dHash>, pub locator_hashes: Vec<sha256d::Hash>,
/// References the header to stop at, or zero to just fetch the maximum 2000 headers /// 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 /// An inventory object --- a reference to a Bitcoin object
@ -72,12 +72,12 @@ pub struct Inventory {
/// The type of object that is referenced /// The type of object that is referenced
pub inv_type: InvType, pub inv_type: InvType,
/// The object's hash /// The object's hash
pub hash: Sha256dHash pub hash: sha256d::Hash
} }
impl GetBlocksMessage { impl GetBlocksMessage {
/// Construct a new `getblocks` message /// Construct a new `getblocks` message
pub fn new(locator_hashes: Vec<Sha256dHash>, stop_hash: Sha256dHash) -> GetBlocksMessage { pub fn new(locator_hashes: Vec<sha256d::Hash>, stop_hash: sha256d::Hash) -> GetBlocksMessage {
GetBlocksMessage { GetBlocksMessage {
version: constants::PROTOCOL_VERSION, version: constants::PROTOCOL_VERSION,
locator_hashes: locator_hashes.clone(), locator_hashes: locator_hashes.clone(),
@ -90,7 +90,7 @@ impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash);
impl GetHeadersMessage { impl GetHeadersMessage {
/// Construct a new `getheaders` message /// Construct a new `getheaders` message
pub fn new(locator_hashes: Vec<Sha256dHash>, stop_hash: Sha256dHash) -> GetHeadersMessage { pub fn new(locator_hashes: Vec<sha256d::Hash>, stop_hash: sha256d::Hash) -> GetHeadersMessage {
GetHeadersMessage { GetHeadersMessage {
version: constants::PROTOCOL_VERSION, version: constants::PROTOCOL_VERSION,
locator_hashes: locator_hashes, locator_hashes: locator_hashes,

View File

@ -51,6 +51,7 @@ use std::fmt::{self, Display, Formatter};
use std::str::FromStr; use std::str::FromStr;
use bitcoin_bech32::{self, WitnessProgram, u5}; use bitcoin_bech32::{self, WitnessProgram, u5};
use bitcoin_hashes::{hash160, Hash};
use secp256k1::key::PublicKey; use secp256k1::key::PublicKey;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -60,7 +61,6 @@ use blockdata::opcodes;
use blockdata::script; use blockdata::script;
use network::constants::Network; use network::constants::Network;
use consensus::encode; use consensus::encode;
use util::hash::Hash160;
use util::base58; use util::base58;
/// The method used to produce an address /// The method used to produce an address
@ -69,9 +69,9 @@ pub enum Payload {
/// pay-to-pubkey /// pay-to-pubkey
Pubkey(PublicKey), Pubkey(PublicKey),
/// pay-to-pkhash address /// pay-to-pkhash address
PubkeyHash(Hash160), PubkeyHash(hash160::Hash),
/// P2SH address /// P2SH address
ScriptHash(Hash160), ScriptHash(hash160::Hash),
/// Segwit address /// Segwit address
WitnessProgram(WitnessProgram), WitnessProgram(WitnessProgram),
} }
@ -92,7 +92,7 @@ impl Address {
pub fn p2pkh(pk: &PublicKey, network: Network) -> Address { pub fn p2pkh(pk: &PublicKey, network: Network) -> Address {
Address { Address {
network: network, 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 { pub fn p2upkh(pk: &PublicKey, network: Network) -> Address {
Address { Address {
network: network, 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 { pub fn p2sh(script: &script::Script, network: Network) -> Address {
Address { Address {
network: network, 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( payload: Payload::WitnessProgram(
// unwrap is safe as witness program is known to be correct as above // unwrap is safe as witness program is known to be correct as above
WitnessProgram::new(u5::try_from_u8(0).expect("0<32"), 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()) Address::bech_network(network)).unwrap())
} }
} }
@ -146,24 +146,19 @@ impl Address {
pub fn p2shwpkh (pk: &PublicKey, network: Network) -> Address { pub fn p2shwpkh (pk: &PublicKey, network: Network) -> Address {
let builder = script::Builder::new() let builder = script::Builder::new()
.push_int(0) .push_int(0)
.push_slice(&Hash160::from_data(&pk.serialize()[..])[..]); .push_slice(&hash160::Hash::hash(&pk.serialize()[..])[..]);
Address { Address {
network: network, network: network,
payload: Payload::ScriptHash( 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 /// Create a witness pay to script hash address
pub fn p2wsh (script: &script::Script, network: Network) -> Address { pub fn p2wsh (script: &script::Script, network: Network) -> Address {
use crypto::sha2::Sha256; use bitcoin_hashes::sha256;
use crypto::digest::Digest; use bitcoin_hashes::Hash;
let mut digest = Sha256::new();
digest.input(script.as_bytes());
let mut d = [0u8; 32];
digest.result(&mut d);
Address { Address {
network: network, network: network,
@ -171,7 +166,7 @@ impl Address {
// unwrap is safe as witness program is known to be correct as above // unwrap is safe as witness program is known to be correct as above
WitnessProgram::new( WitnessProgram::new(
u5::try_from_u8(0).expect("0<32"), u5::try_from_u8(0).expect("0<32"),
d.to_vec(), sha256::Hash::hash(&script[..])[..].to_vec(),
Address::bech_network(network) Address::bech_network(network)
).unwrap() ).unwrap()
) )
@ -181,18 +176,17 @@ impl Address {
/// Create a pay to script address that embeds a witness pay to script hash 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 /// This is a segwit address type that looks familiar (as p2sh) to legacy clients
pub fn p2shwsh (script: &script::Script, network: Network) -> Address { pub fn p2shwsh (script: &script::Script, network: Network) -> Address {
use crypto::sha2::Sha256; use bitcoin_hashes::sha256;
use crypto::digest::Digest; use bitcoin_hashes::Hash;
use bitcoin_hashes::hash160;
let mut digest = Sha256::new(); let ws = script::Builder::new().push_int(0)
digest.input(script.as_bytes()); .push_slice(&sha256::Hash::hash(&script[..])[..])
let mut d = [0u8; 32]; .into_script();
digest.result(&mut d);
let ws = script::Builder::new().push_int(0).push_slice(&d).into_script();
Address { Address {
network: network, 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 { match self.payload {
// note: serialization for pay-to-pk is defined, but is irreversible // note: serialization for pay-to-pk is defined, but is irreversible
Payload::Pubkey(ref pk) => { 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]; let mut prefixed = [0; 21];
prefixed[0] = match self.network { prefixed[0] = match self.network {
Network::Bitcoin => 0, Network::Bitcoin => 0,
@ -315,19 +309,19 @@ impl FromStr for Address {
let (network, payload) = match data[0] { let (network, payload) = match data[0] {
0 => ( 0 => (
Network::Bitcoin, Network::Bitcoin,
Payload::PubkeyHash(Hash160::from(&data[1..])) Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap())
), ),
5 => ( 5 => (
Network::Bitcoin, Network::Bitcoin,
Payload::ScriptHash(Hash160::from(&data[1..])) Payload::ScriptHash(hash160::Hash::from_slice(&data[1..]).unwrap())
), ),
111 => ( 111 => (
Network::Testnet, Network::Testnet,
Payload::PubkeyHash(Hash160::from(&data[1..])) Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap())
), ),
196 => ( 196 => (
Network::Testnet, 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]))) x => return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![x])))
}; };
@ -403,24 +397,25 @@ mod tests {
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString; use std::string::ToString;
use bitcoin_hashes::{hash160, Hash};
use secp256k1::key::PublicKey; use secp256k1::key::PublicKey;
use hex::decode as hex_decode; use hex::decode as hex_decode;
use blockdata::script::Script; use blockdata::script::Script;
use network::constants::Network::{Bitcoin, Testnet, Regtest}; use network::constants::Network::{Bitcoin, Testnet, Regtest};
use util::hash::Hash160;
use super::*; use super::*;
macro_rules! hex (($hex:expr) => (hex_decode($hex).unwrap())); macro_rules! hex (($hex:expr) => (hex_decode($hex).unwrap()));
macro_rules! hex_key (($hex:expr) => (PublicKey::from_slice(&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_script (($hex:expr) => (Script::from(hex!($hex))));
macro_rules! hex_hash160 (($hex:expr) => (hash160::Hash::from_slice(&hex!($hex)).unwrap()));
#[test] #[test]
fn test_p2pkh_address_58() { fn test_p2pkh_address_58() {
let addr = Address { let addr = Address {
network: Bitcoin, network: Bitcoin,
payload: Payload::PubkeyHash( payload: Payload::PubkeyHash(
Hash160::from(&hex_decode("162c5ea71c0b23f5b9022ef047c4a86470a5b070").unwrap()[..]) hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")
) )
}; };
@ -453,7 +448,7 @@ mod tests {
let addr = Address { let addr = Address {
network: Bitcoin, network: Bitcoin,
payload: Payload::ScriptHash( payload: Payload::ScriptHash(
Hash160::from(&hex_decode("162c5ea71c0b23f5b9022ef047c4a86470a5b070").unwrap()[..]) hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")
) )
}; };

View File

@ -17,7 +17,8 @@
use std::{error, fmt, str, slice, iter}; use std::{error, fmt, str, slice, iter};
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use util::hash::Sha256dHash;
use bitcoin_hashes::{sha256d, Hash};
/// An error that might occur during base58 decoding /// An error that might occur during base58 decoding
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
@ -161,7 +162,7 @@ pub fn from_check(data: &str) -> Result<Vec<u8>, Error> {
return Err(Error::TooShort(ret.len())); return Err(Error::TooShort(ret.len()));
} }
let ck_start = ret.len() - 4; 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)]); let actual = LittleEndian::read_u32(&ret[ck_start..(ck_start + 4)]);
if expected != actual { if expected != actual {
return Err(Error::BadChecksum(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 /// 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.) /// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.)
pub fn check_encode_slice(data: &[u8]) -> String { pub fn check_encode_slice(data: &[u8]) -> String {
let checksum = Sha256dHash::from_data(&data); let checksum = sha256d::Hash::hash(&data);
encode_iter( encode_iter(
data.iter() data.iter()
.cloned() .cloned()
@ -241,7 +242,7 @@ pub fn check_encode_slice(data: &[u8]) -> String {
/// Obtain a string with the base58check encoding of a slice /// 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.) /// (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 { 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() let iter = data.iter()
.cloned() .cloned()
.chain(checksum[0..4].iter().cloned()); .chain(checksum[0..4].iter().cloned());

View File

@ -19,10 +19,11 @@
//! signatures, which are placed in the scriptSig. //! signatures, which are placed in the scriptSig.
//! //!
use bitcoin_hashes::{sha256d, Hash};
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::transaction::{Transaction, TxIn}; use blockdata::transaction::{Transaction, TxIn};
use consensus::encode::Encodable; use consensus::encode::Encodable;
use util::hash::{Sha256dHash, Sha256dEncoder};
/// Parts of a sighash which are common across inputs or signatures, and which are /// 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 /// sufficient (in conjunction with a private key) to sign the transaction
@ -31,11 +32,11 @@ pub struct SighashComponents {
tx_version: u32, tx_version: u32,
tx_locktime: u32, tx_locktime: u32,
/// Hash of all the previous outputs /// Hash of all the previous outputs
pub hash_prevouts: Sha256dHash, pub hash_prevouts: sha256d::Hash,
/// Hash of all the input sequence nos /// Hash of all the input sequence nos
pub hash_sequence: Sha256dHash, pub hash_sequence: sha256d::Hash,
/// Hash of all the outputs in this transaction /// Hash of all the outputs in this transaction
pub hash_outputs: Sha256dHash, pub hash_outputs: sha256d::Hash,
} }
impl SighashComponents { impl SighashComponents {
@ -45,27 +46,27 @@ impl SighashComponents {
/// script_sig and witnesses. /// script_sig and witnesses.
pub fn new(tx: &Transaction) -> SighashComponents { pub fn new(tx: &Transaction) -> SighashComponents {
let hash_prevouts = { let hash_prevouts = {
let mut enc = Sha256dEncoder::new(); let mut enc = sha256d::Hash::engine();
for txin in &tx.input { for txin in &tx.input {
txin.previous_output.consensus_encode(&mut enc).unwrap(); txin.previous_output.consensus_encode(&mut enc).unwrap();
} }
enc.into_hash() sha256d::Hash::from_engine(enc)
}; };
let hash_sequence = { let hash_sequence = {
let mut enc = Sha256dEncoder::new(); let mut enc = sha256d::Hash::engine();
for txin in &tx.input { for txin in &tx.input {
txin.sequence.consensus_encode(&mut enc).unwrap(); txin.sequence.consensus_encode(&mut enc).unwrap();
} }
enc.into_hash() sha256d::Hash::from_engine(enc)
}; };
let hash_outputs = { let hash_outputs = {
let mut enc = Sha256dEncoder::new(); let mut enc = sha256d::Hash::engine();
for txout in &tx.output { for txout in &tx.output {
txout.consensus_encode(&mut enc).unwrap(); txout.consensus_encode(&mut enc).unwrap();
} }
enc.into_hash() sha256d::Hash::from_engine(enc)
}; };
SighashComponents { SighashComponents {
@ -79,8 +80,8 @@ impl SighashComponents {
/// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given /// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given
/// input. /// input.
pub fn sighash_all(&self, txin: &TxIn, witness_script: &Script, value: u64) -> Sha256dHash { pub fn sighash_all(&self, txin: &TxIn, witness_script: &Script, value: u64) -> sha256d::Hash {
let mut enc = Sha256dEncoder::new(); let mut enc = sha256d::Hash::engine();
self.tx_version.consensus_encode(&mut enc).unwrap(); self.tx_version.consensus_encode(&mut enc).unwrap();
self.hash_prevouts.consensus_encode(&mut enc).unwrap(); self.hash_prevouts.consensus_encode(&mut enc).unwrap();
self.hash_sequence.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.hash_outputs.consensus_encode(&mut enc).unwrap();
self.tx_locktime.consensus_encode(&mut enc).unwrap(); self.tx_locktime.consensus_encode(&mut enc).unwrap();
1u32.consensus_encode(&mut enc).unwrap(); // hashtype 1u32.consensus_encode(&mut enc).unwrap(); // hashtype
enc.into_hash() sha256d::Hash::from_engine(enc)
} }
} }

View File

@ -23,19 +23,13 @@ use std::str::FromStr;
#[cfg(feature = "serde")] use serde; #[cfg(feature = "serde")] use serde;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use crypto::digest::Digest; use bitcoin_hashes::{hash160, sha512, Hash, HashEngine, Hmac, HmacEngine};
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::ripemd160::Ripemd160;
use secp256k1::key::{PublicKey, SecretKey}; use secp256k1::key::{PublicKey, SecretKey};
use secp256k1::{self, Secp256k1}; use secp256k1::{self, Secp256k1};
use network::constants::Network; use network::constants::Network;
use util::base58; use util::base58;
#[cfg(feature="fuzztarget")] use fuzz_util::sha2::{Sha256, Sha512};
#[cfg(not(feature="fuzztarget"))] use crypto::sha2::{Sha256, Sha512};
/// A chain code /// A chain code
pub struct ChainCode([u8; 32]); pub struct ChainCode([u8; 32]);
impl_array_newtype!(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_array_newtype_encodable!(Fingerprint, u8, 4);
impl Default for Fingerprint { impl Default for Fingerprint {
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) } fn default() -> Fingerprint { Fingerprint([0; 4]) }
} }
/// Extended private key /// Extended private key
@ -237,18 +231,17 @@ impl From<secp256k1::Error> for Error {
impl ExtendedPrivKey { impl ExtendedPrivKey {
/// Construct a new master key from a seed value /// Construct a new master key from a seed value
pub fn new_master(network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> { pub fn new_master(network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
let mut result = [0; 64]; let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(b"Bitcoin seed");
let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed"); hmac_engine.input(seed);
hmac.input(seed); let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
hmac.raw_result(&mut result);
Ok(ExtendedPrivKey { Ok(ExtendedPrivKey {
network: network, network: network,
depth: 0, depth: 0,
parent_fingerprint: Default::default(), parent_fingerprint: Default::default(),
child_number: ChildNumber::from_normal_idx(0), child_number: ChildNumber::from_normal_idx(0),
secret_key: SecretKey::from_slice(&result[..32]).map_err(Error::Ecdsa)?, secret_key: SecretKey::from_slice(&hmac_result[..32]).map_err(Error::Ecdsa)?,
chain_code: ChainCode::from(&result[32..]) chain_code: ChainCode::from(&hmac_result[32..]),
}) })
} }
@ -267,25 +260,24 @@ impl ExtendedPrivKey {
/// Private->Private child key derivation /// Private->Private child key derivation
pub fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<ExtendedPrivKey, Error> { pub fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<ExtendedPrivKey, Error> {
let mut result = [0; 64]; let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]);
let mut be_n = [0; 4]; let mut be_n = [0; 4];
match i { match i {
ChildNumber::Normal {..} => { ChildNumber::Normal {..} => {
// Non-hardened key: compute public data and use that // 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 {..} => { ChildNumber::Hardened {..} => {
// Hardened key: use only secret data to prevent public derivation // Hardened key: use only secret data to prevent public derivation
hmac.input(&[0u8]); hmac_engine.input(&[0u8]);
hmac.input(&self.secret_key[..]); hmac_engine.input(&self.secret_key[..]);
} }
} }
BigEndian::write_u32(&mut be_n, u32::from(i)); BigEndian::write_u32(&mut be_n, u32::from(i));
hmac.input(&be_n); hmac_engine.input(&be_n);
hmac.raw_result(&mut result); let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
let mut sk = SecretKey::from_slice(&result[..32]).map_err(Error::Ecdsa)?; let mut sk = SecretKey::from_slice(&hmac_result[..32]).map_err(Error::Ecdsa)?;
sk.add_assign(&self.secret_key[..]).map_err(Error::Ecdsa)?; sk.add_assign(&self.secret_key[..]).map_err(Error::Ecdsa)?;
Ok(ExtendedPrivKey { Ok(ExtendedPrivKey {
@ -294,26 +286,13 @@ impl ExtendedPrivKey {
parent_fingerprint: self.fingerprint(secp), parent_fingerprint: self.fingerprint(secp),
child_number: i, child_number: i,
secret_key: sk, secret_key: sk,
chain_code: ChainCode::from(&result[32..]) chain_code: ChainCode::from(&hmac_result[32..])
}) })
} }
/// Returns the HASH160 of the chaincode /// Returns the HASH160 of the chaincode
pub fn identifier<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> [u8; 20] { pub fn identifier<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> hash160::Hash {
let mut sha2_res = [0; 32]; ExtendedPubKey::from_private(secp, self).identifier()
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
} }
/// Returns the first four bytes of the identifier /// Returns the first four bytes of the identifier
@ -355,17 +334,16 @@ impl ExtendedPubKey {
Err(Error::CannotDeriveFromHardenedKey) Err(Error::CannotDeriveFromHardenedKey)
} }
ChildNumber::Normal { index: n } => { ChildNumber::Normal { index: n } => {
let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]); let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
hmac.input(&self.public_key.serialize()[..]); hmac_engine.input(&self.public_key.serialize()[..]);
let mut be_n = [0; 4]; let mut be_n = [0; 4];
BigEndian::write_u32(&mut be_n, n); BigEndian::write_u32(&mut be_n, n);
hmac.input(&be_n); hmac_engine.input(&be_n);
let mut result = [0; 64]; let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
hmac.raw_result(&mut result);
let secret_key = SecretKey::from_slice(&result[..32])?; let secret_key = SecretKey::from_slice(&hmac_result[..32])?;
let chain_code = ChainCode::from(&result[32..]); let chain_code = ChainCode::from(&hmac_result[32..]);
Ok((secret_key, chain_code)) Ok((secret_key, chain_code))
} }
} }
@ -392,19 +370,8 @@ impl ExtendedPubKey {
} }
/// Returns the HASH160 of the chaincode /// Returns the HASH160 of the chaincode
pub fn identifier(&self) -> [u8; 20] { pub fn identifier(&self) -> hash160::Hash {
let mut sha2_res = [0; 32]; hash160::Hash::hash(&self.public_key.serialize())
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
} }
/// Returns the first four bytes of the identifier /// Returns the first four bytes of the identifier

View File

@ -20,17 +20,13 @@
use secp256k1::{self, Secp256k1}; use secp256k1::{self, Secp256k1};
use secp256k1::key::{PublicKey, SecretKey}; use secp256k1::key::{PublicKey, SecretKey};
use bitcoin_hashes::{hash160, sha256, Hash, HashEngine, Hmac, HmacEngine};
use blockdata::{opcodes, script}; use blockdata::{opcodes, script};
use crypto::hmac;
use crypto::mac::Mac;
use std::{error, fmt}; use std::{error, fmt};
use network::constants::Network; use network::constants::Network;
use util::{address, hash}; use util::address;
#[cfg(feature="fuzztarget")] use fuzz_util::sha2;
#[cfg(not(feature="fuzztarget"))] use crypto::sha2;
/// Encoding of "pubkey here" in script; from Bitcoin Core `src/script/script.h` /// Encoding of "pubkey here" in script; from Bitcoin Core `src/script/script.h`
static PUBKEY: u8 = 0xFE; static PUBKEY: u8 = 0xFE;
@ -173,11 +169,10 @@ impl<'a> From<&'a [u8]> for Template {
pub fn tweak_keys<C: secp256k1::Verification>(secp: &Secp256k1<C>, keys: &[PublicKey], contract: &[u8]) -> Result<Vec<PublicKey>, Error> { pub fn tweak_keys<C: secp256k1::Verification>(secp: &Secp256k1<C>, keys: &[PublicKey], contract: &[u8]) -> Result<Vec<PublicKey>, Error> {
let mut ret = Vec::with_capacity(keys.len()); let mut ret = Vec::with_capacity(keys.len());
for mut key in keys.iter().cloned() { for mut key in keys.iter().cloned() {
let mut hmac_raw = [0; 32]; let mut hmac_engine: HmacEngine<sha256::Hash> = HmacEngine::new(&key.serialize());
let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &key.serialize()); hmac_engine.input(contract);
hmac.input(contract); let hmac_result: Hmac<sha256::Hash> = Hmac::from_engine(hmac_engine);
hmac.raw_result(&mut hmac_raw); let hmac_sk = SecretKey::from_slice(&hmac_result[..]).map_err(Error::BadTweak)?;
let hmac_sk = SecretKey::from_slice(&hmac_raw).map_err(Error::BadTweak)?;
key.add_exp_assign(secp, &hmac_sk[..]).map_err(Error::Secp)?; key.add_exp_assign(secp, &hmac_sk[..]).map_err(Error::Secp)?;
ret.push(key); ret.push(key);
} }
@ -186,11 +181,10 @@ pub fn tweak_keys<C: secp256k1::Verification>(secp: &Secp256k1<C>, keys: &[Publi
/// Compute a tweak from some given data for the given public key /// Compute a tweak from some given data for the given public key
pub fn compute_tweak(pk: &PublicKey, contract: &[u8]) -> Result<SecretKey, Error> { pub fn compute_tweak(pk: &PublicKey, contract: &[u8]) -> Result<SecretKey, Error> {
let mut hmac_raw = [0; 32]; let mut hmac_engine: HmacEngine<sha256::Hash> = HmacEngine::new(&pk.serialize());
let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &pk.serialize()); hmac_engine.input(contract);
hmac.input(contract); let hmac_result: Hmac<sha256::Hash> = Hmac::from_engine(hmac_engine);
hmac.raw_result(&mut hmac_raw); SecretKey::from_slice(&hmac_result[..]).map_err(Error::BadTweak)
SecretKey::from_slice(&hmac_raw).map_err(Error::BadTweak)
} }
/// Tweak a secret key using some arbitrary data (calls `compute_tweak` internally) /// Tweak a secret key using some arbitrary data (calls `compute_tweak` internally)
@ -218,7 +212,7 @@ pub fn create_address<C: secp256k1::Verification>(secp: &Secp256k1<C>,
Ok(address::Address { Ok(address::Address {
network: network, network: network,
payload: address::Payload::ScriptHash( payload: address::Payload::ScriptHash(
hash::Hash160::from_data(&script[..]) hash160::Hash::hash(&script[..])
) )
}) })
} }

View File

@ -26,6 +26,7 @@ use std::mem;
use crypto::digest::Digest; use crypto::digest::Digest;
use crypto::ripemd160::Ripemd160; use crypto::ripemd160::Ripemd160;
use bitcoin_hashes::{sha256d, Hash};
use consensus::encode::{Encodable, Decodable}; use consensus::encode::{Encodable, Decodable};
use util::uint::Uint256; use util::uint::Uint256;
@ -390,11 +391,11 @@ impl FromStr for Sha256dHash {
pub trait MerkleRoot { pub trait MerkleRoot {
/// Construct a merkle tree from a collection, with elements ordered as /// Construct a merkle tree from a collection, with elements ordered as
/// they were in the original collection, and return the merkle root. /// 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 /// Calculates the merkle root of a list of txids hashes directly
pub fn bitcoin_merkle_root(data: Vec<Sha256dHash>) -> Sha256dHash { pub fn bitcoin_merkle_root(data: Vec<sha256d::Hash>) -> sha256d::Hash {
// Base case // Base case
if data.len() < 1 { if data.len() < 1 {
return Default::default(); return Default::default();
@ -407,22 +408,22 @@ pub fn bitcoin_merkle_root(data: Vec<Sha256dHash>) -> Sha256dHash {
for idx in 0..((data.len() + 1) / 2) { for idx in 0..((data.len() + 1) / 2) {
let idx1 = 2 * idx; let idx1 = 2 * idx;
let idx2 = min(idx1 + 1, data.len() - 1); 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[idx1].consensus_encode(&mut encoder).unwrap();
data[idx2].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) bitcoin_merkle_root(next)
} }
impl<'a, T: BitcoinHash> MerkleRoot for &'a [T] { 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()) bitcoin_merkle_root(self.iter().map(|obj| obj.bitcoin_hash()).collect())
} }
} }
impl <T: BitcoinHash> MerkleRoot for Vec<T> { impl <T: BitcoinHash> MerkleRoot for Vec<T> {
fn merkle_root(&self) -> Sha256dHash { fn merkle_root(&self) -> sha256d::Hash {
(&self[..]).merkle_root() (&self[..]).merkle_root()
} }
} }
@ -430,7 +431,7 @@ impl <T: BitcoinHash> MerkleRoot for Vec<T> {
/// Objects which are referred to by hash /// Objects which are referred to by hash
pub trait BitcoinHash { pub trait BitcoinHash {
/// Produces a Sha256dHash which can be used to refer to the object /// 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)] #[cfg(test)]