New HashTypes defined according to #284 (WIP), Txid is completed

This commit is contained in:
Dr Maxim Orlovsky 2019-12-09 23:37:52 +01:00
parent e2caebc42e
commit ec92a05682
6 changed files with 80 additions and 24 deletions

View File

@ -112,7 +112,7 @@ impl Block {
impl MerkleRoot for Block { impl MerkleRoot for Block {
fn merkle_root(&self) -> sha256d::Hash { fn merkle_root(&self) -> sha256d::Hash {
bitcoin_merkle_root(self.txdata.iter().map(|obj| obj.txid()).collect()) bitcoin_merkle_root(self.txdata.iter().map(|obj| obj.txid().into()).collect())
} }
} }

View File

@ -96,14 +96,15 @@ fn bitcoin_genesis_tx() -> Transaction {
/// Constructs and returns the genesis block /// Constructs and returns the genesis block
pub fn genesis_block(network: Network) -> Block { pub fn genesis_block(network: Network) -> Block {
let txdata = vec![bitcoin_genesis_tx()];
let merkle_root = txdata[0].txid().into();
match network { match network {
Network::Bitcoin => { Network::Bitcoin => {
let txdata = vec![bitcoin_genesis_tx()];
Block { Block {
header: BlockHeader { header: BlockHeader {
version: 1, version: 1,
prev_blockhash: Default::default(), prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(), merkle_root,
time: 1231006505, time: 1231006505,
bits: 0x1d00ffff, bits: 0x1d00ffff,
nonce: 2083236893 nonce: 2083236893
@ -112,12 +113,11 @@ pub fn genesis_block(network: Network) -> Block {
} }
} }
Network::Testnet => { Network::Testnet => {
let txdata = vec![bitcoin_genesis_tx()];
Block { Block {
header: BlockHeader { header: BlockHeader {
version: 1, version: 1,
prev_blockhash: Default::default(), prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(), merkle_root,
time: 1296688602, time: 1296688602,
bits: 0x1d00ffff, bits: 0x1d00ffff,
nonce: 414098458 nonce: 414098458
@ -126,12 +126,11 @@ pub fn genesis_block(network: Network) -> Block {
} }
} }
Network::Regtest => { Network::Regtest => {
let txdata = vec![bitcoin_genesis_tx()];
Block { Block {
header: BlockHeader { header: BlockHeader {
version: 1, version: 1,
prev_blockhash: Default::default(), prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(), merkle_root,
time: 1296688602, time: 1296688602,
bits: 0x207fffff, bits: 0x207fffff,
nonce: 2 nonce: 2

View File

@ -34,13 +34,14 @@ 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, serialize, Decodable, Encodable}; use consensus::{encode, serialize, Decodable, Encodable};
use hash_types::*;
use VarInt; use VarInt;
/// A reference to a transaction output /// A reference to a transaction output
#[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: sha256d::Hash, pub txid: Txid,
/// 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,
} }
@ -49,7 +50,7 @@ serde_struct_human_string_impl!(OutPoint, "an OutPoint", txid, vout);
impl OutPoint { impl OutPoint {
/// Create a new [OutPoint]. /// Create a new [OutPoint].
#[inline] #[inline]
pub fn new(txid: sha256d::Hash, vout: u32) -> OutPoint { pub fn new(txid: Txid, vout: u32) -> OutPoint {
OutPoint { OutPoint {
txid: txid, txid: txid,
vout: vout, vout: vout,
@ -175,7 +176,7 @@ impl ::std::str::FromStr for OutPoint {
return Err(ParseOutPointError::Format); return Err(ParseOutPointError::Format);
} }
Ok(OutPoint { Ok(OutPoint {
txid: sha256d::Hash::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?, txid: Txid::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?,
vout: parse_vout(&s[colon+1..])?, vout: parse_vout(&s[colon+1..])?,
}) })
} }
@ -293,13 +294,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) -> sha256d::Hash { pub fn txid(&self) -> Txid {
let mut enc = sha256d::Hash::engine(); let mut enc = sha256d::Hash::engine();
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();
sha256d::Hash::from_engine(enc) Txid::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.
@ -630,6 +631,8 @@ mod tests {
use hashes::{sha256d, Hash}; use hashes::{sha256d, Hash};
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hash_types::*;
#[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"),
@ -645,20 +648,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(sha256d::Hash::from_hex("i don't care").unwrap_err()))); Err(ParseOutPointError::Txid(Txid::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(sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X").unwrap_err()))); Err(ParseOutPointError::Txid(Txid::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: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), txid: Txid::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: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
vout: 0, vout: 0,
})); }));
} }

51
src/hash_types.rs Normal file
View File

@ -0,0 +1,51 @@
// Rust Bitcoin Library
// Written in 2014 by
// Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! File defines types for hashes used throughout the library. These types are needed in order
//! to avoid mixing data of the same hash format (like SHA256d) but of different meaning
//! (transaction id, block hash etc).
use std::io;
use consensus::encode::{Encodable, Decodable, Error};
use hashes::{sha256, sha256d, hash160, Hash};
use hashes::hex::{ToHex, FromHex};
macro_rules! impl_hashencode {
($hashtype:ident) => {
impl Encodable for $hashtype {
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, Error> {
self.0.consensus_encode(s)
}
}
impl Decodable for $hashtype {
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
let inner = <<$hashtype as Hash>::Inner>::consensus_decode(d)?;
Ok(Self::from_slice(&inner).unwrap())
}
}
}
}
hash_newtype!(Txid, sha256d::Hash, 32, doc="A bitcoin transaction hash/transaction ID.");
hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID.");
hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash.");
hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key.");
hash_newtype!(ScriptHash, hash160::Hash, 20, doc="A hash of Bitcoin Script bytecode.");
hash_newtype!(WPubkeyHash, hash160::Hash, 20, doc="SegWit version of a public key hash.");
hash_newtype!(WScriptHash, sha256::Hash, 32, doc="SegWit version of a Bitcoin Script bytecode hash.");
hash_newtype!(XpubIdentifier, hash160::Hash, 20, doc="XpubIdentifier as defined in BIP-32.");
impl_hashencode!(Txid);

View File

@ -52,7 +52,7 @@
#![allow(ellipsis_inclusive_range_patterns)] #![allow(ellipsis_inclusive_range_patterns)]
// Re-exported dependencies. // Re-exported dependencies.
pub extern crate bitcoin_hashes as hashes; #[macro_use] pub extern crate bitcoin_hashes as hashes;
pub extern crate secp256k1; pub extern crate secp256k1;
pub extern crate bech32; pub extern crate bech32;
@ -77,7 +77,10 @@ pub mod network;
pub mod blockdata; pub mod blockdata;
pub mod util; pub mod util;
pub mod consensus; pub mod consensus;
#[allow(unused_imports)]
pub mod hash_types;
pub use hash_types::*;
pub use blockdata::block::Block; pub use blockdata::block::Block;
pub use blockdata::block::BlockHeader; pub use blockdata::block::BlockHeader;
pub use blockdata::script::Script; pub use blockdata::script::Script;

View File

@ -163,7 +163,7 @@ impl Decodable for PartiallySignedTransaction {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hashes::sha256d; use hash_types::Txid;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -255,7 +255,7 @@ mod tests {
lock_time: 1257139, lock_time: 1257139,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
txid: sha256d::Hash::from_hex( txid: Txid::from_hex(
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
).unwrap(), ).unwrap(),
vout: 0, vout: 0,
@ -315,7 +315,7 @@ mod tests {
use hex::decode as hex_decode; use hex::decode as hex_decode;
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hashes::sha256d; use hash_types::Txid;
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::transaction::{SigHashType, Transaction, TxIn, TxOut, OutPoint}; use blockdata::transaction::{SigHashType, Transaction, TxIn, TxOut, OutPoint};
@ -363,7 +363,7 @@ mod tests {
lock_time: 1257139, lock_time: 1257139,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
txid: sha256d::Hash::from_hex( txid: Txid::from_hex(
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
).unwrap(), ).unwrap(),
vout: 0, vout: 0,
@ -391,7 +391,7 @@ mod tests {
lock_time: 0, lock_time: 0,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
txid: sha256d::Hash::from_hex( txid: Txid::from_hex(
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
).unwrap(), ).unwrap(),
vout: 1, vout: 1,
@ -405,7 +405,7 @@ mod tests {
}, },
TxIn { TxIn {
previous_output: OutPoint { previous_output: OutPoint {
txid: sha256d::Hash::from_hex( txid: Txid::from_hex(
"b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
).unwrap(), ).unwrap(),
vout: 1, vout: 1,
@ -548,7 +548,7 @@ mod tests {
let tx = &psbt.global.unsigned_tx; let tx = &psbt.global.unsigned_tx;
assert_eq!( assert_eq!(
tx.txid(), tx.txid(),
sha256d::Hash::from_hex( Txid::from_hex(
"75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115" "75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115"
).unwrap() ).unwrap()
); );