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 {
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
pub fn genesis_block(network: Network) -> Block {
let txdata = vec![bitcoin_genesis_tx()];
let merkle_root = txdata[0].txid().into();
match network {
Network::Bitcoin => {
let txdata = vec![bitcoin_genesis_tx()];
Block {
header: BlockHeader {
version: 1,
prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(),
merkle_root,
time: 1231006505,
bits: 0x1d00ffff,
nonce: 2083236893
@ -112,12 +113,11 @@ pub fn genesis_block(network: Network) -> Block {
}
}
Network::Testnet => {
let txdata = vec![bitcoin_genesis_tx()];
Block {
header: BlockHeader {
version: 1,
prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(),
merkle_root,
time: 1296688602,
bits: 0x1d00ffff,
nonce: 414098458
@ -126,12 +126,11 @@ pub fn genesis_block(network: Network) -> Block {
}
}
Network::Regtest => {
let txdata = vec![bitcoin_genesis_tx()];
Block {
header: BlockHeader {
version: 1,
prev_blockhash: Default::default(),
merkle_root: txdata[0].txid(),
merkle_root,
time: 1296688602,
bits: 0x207fffff,
nonce: 2

View File

@ -34,13 +34,14 @@ use util::hash::BitcoinHash;
#[cfg(feature="bitcoinconsensus")] use blockdata::script;
use blockdata::script::Script;
use consensus::{encode, serialize, Decodable, Encodable};
use hash_types::*;
use VarInt;
/// A reference to a transaction output
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct OutPoint {
/// The referenced transaction's txid
pub txid: sha256d::Hash,
pub txid: Txid,
/// The index of the referenced output in its transaction's vout
pub vout: u32,
}
@ -49,7 +50,7 @@ serde_struct_human_string_impl!(OutPoint, "an OutPoint", txid, vout);
impl OutPoint {
/// Create a new [OutPoint].
#[inline]
pub fn new(txid: sha256d::Hash, vout: u32) -> OutPoint {
pub fn new(txid: Txid, vout: u32) -> OutPoint {
OutPoint {
txid: txid,
vout: vout,
@ -175,7 +176,7 @@ impl ::std::str::FromStr for OutPoint {
return Err(ParseOutPointError::Format);
}
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..])?,
})
}
@ -293,13 +294,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) -> sha256d::Hash {
pub fn txid(&self) -> Txid {
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();
sha256d::Hash::from_engine(enc)
Txid::from_engine(enc)
}
/// 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::hex::FromHex;
use hash_types::*;
#[test]
fn test_outpoint() {
assert_eq!(OutPoint::from_str("i don't care"),
@ -645,20 +648,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(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"),
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"),
Err(ParseOutPointError::Vout(u32::from_str("lol").unwrap_err())));
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"),
Ok(OutPoint{
txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
vout: 42,
}));
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"),
Ok(OutPoint{
txid: sha256d::Hash::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
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)]
// 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 bech32;
@ -77,7 +77,10 @@ pub mod network;
pub mod blockdata;
pub mod util;
pub mod consensus;
#[allow(unused_imports)]
pub mod hash_types;
pub use hash_types::*;
pub use blockdata::block::Block;
pub use blockdata::block::BlockHeader;
pub use blockdata::script::Script;

View File

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