Moving from BitcoinHash to Wtxid for Transactions

This commit is contained in:
Dr Maxim Orlovsky 2019-12-18 12:00:18 +01:00
parent f5a8087105
commit 0abe15b1f6
6 changed files with 32 additions and 26 deletions

View File

@ -24,7 +24,7 @@ use util;
use util::Error::{BlockBadTarget, BlockBadProofOfWork};
use util::hash::{BitcoinHash, MerkleRooted, bitcoin_merkle_root};
use hashes::{Hash, sha256d, HashEngine};
use hash_types::{Txid, BlockHash, TxMerkleRoot, WitnessMerkleRoot, WitnessCommitment};
use hash_types::{Txid, Wtxid, BlockHash, TxMerkleRoot, WitnessMerkleRoot, WitnessCommitment};
use util::uint::Uint256;
use consensus::encode::Encodable;
use network::constants::Network;
@ -103,8 +103,8 @@ impl Block {
/// Merkle root of transactions hashed for witness
pub fn witness_root(&self) -> WitnessMerkleRoot {
let mut txhashes = vec!(Txid::default());
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.bitcoin_hash()));
let mut txhashes = vec!(Wtxid::default());
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.wtxid()));
let hash_value: sha256d::Hash = bitcoin_merkle_root(txhashes).into();
hash_value.into()
}
@ -112,7 +112,7 @@ impl Block {
impl MerkleRooted for Block {
fn merkle_root(&self) -> TxMerkleRoot {
bitcoin_merkle_root(self.txdata.iter().map(|obj| obj.txid().into()).collect())
bitcoin_merkle_root::<Txid>(self.txdata.iter().map(|obj| obj.txid().into()).collect())
}
}

View File

@ -171,7 +171,7 @@ mod test {
assert_eq!(gen.output[0].value, 50 * COIN_VALUE);
assert_eq!(gen.lock_time, 0);
assert_eq!(format!("{:x}", gen.bitcoin_hash()),
assert_eq!(format!("{:x}", gen.wtxid()),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
}

View File

@ -30,7 +30,6 @@ use hashes::{self, Hash, sha256d};
use hashes::hex::FromHex;
use util::endian;
use util::hash::BitcoinHash;
#[cfg(feature="bitcoinconsensus")] use blockdata::script;
use blockdata::script::Script;
use consensus::{encode, serialize, Decodable, Encodable};
@ -287,12 +286,12 @@ impl Transaction {
input: self.input.iter().map(|txin| TxIn { script_sig: Script::new(), witness: vec![], .. *txin }).collect(),
output: self.output.clone(),
};
cloned_tx.bitcoin_hash().into()
cloned_tx.txid().into()
}
/// Computes the txid. For non-segwit transactions this will be identical
/// to the output of `BitcoinHash::bitcoin_hash()`, but for segwit transactions,
/// this will give the correct txid (not including witnesses) while `bitcoin_hash`
/// to the output of `wtxid()`, but for segwit transactions,
/// this will give the correct txid (not including witnesses) while `wtxid`
/// will also hash witnesses.
pub fn txid(&self) -> Txid {
let mut enc = Txid::engine();
@ -303,6 +302,15 @@ impl Transaction {
Txid::from_engine(enc)
}
/// Computes SegWit-version of the transaction id (wtxid). For transaction with the witness
/// data this hash includes witness, for pre-witness transaction it is equal to the normal
/// value returned by txid() function.
pub fn wtxid(&self) -> Wtxid {
let mut enc = Wtxid::engine();
self.consensus_encode(&mut enc).unwrap();
Wtxid::from_engine(enc)
}
/// Computes a signature hash for a given input index with a given sighash flag.
/// To actually produce a scriptSig, this hash needs to be run through an
/// ECDSA signer, the SigHashType appended to the resulting sig, and a
@ -438,14 +446,6 @@ impl Transaction {
}
}
impl BitcoinHash<Txid> for Transaction {
fn bitcoin_hash(&self) -> Txid {
let mut enc = Txid::engine();
self.consensus_encode(&mut enc).unwrap();
Txid::from_engine(enc)
}
}
impl_consensus_encoding!(TxOut, value, script_pubkey);
impl Encodable for OutPoint {
@ -626,7 +626,6 @@ mod tests {
use blockdata::script::Script;
use consensus::encode::serialize;
use consensus::encode::deserialize;
use util::hash::BitcoinHash;
use hashes::Hash;
use hashes::hex::FromHex;
@ -712,7 +711,9 @@ mod tests {
assert_eq!(realtx.output.len(), 1);
assert_eq!(realtx.lock_time, 0);
assert_eq!(format!("{:x}", realtx.bitcoin_hash()),
assert_eq!(format!("{:x}", realtx.txid()),
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
assert_eq!(format!("{:x}", realtx.wtxid()),
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
assert_eq!(realtx.get_weight(), 193*4);
}
@ -781,7 +782,7 @@ mod tests {
).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap();
assert_eq!(format!("{:x}", tx.bitcoin_hash()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4");
assert_eq!(format!("{:x}", tx.wtxid()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4");
assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec");
assert_eq!(tx.get_weight(), 2718);
@ -796,7 +797,7 @@ mod tests {
).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap();
assert_eq!(format!("{:x}", tx.bitcoin_hash()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
assert_eq!(format!("{:x}", tx.wtxid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
}

View File

@ -66,3 +66,9 @@ impl_hashencode!(TxMerkleRoot);
impl_hashencode!(TxMerkleBranch);
impl_hashencode!(WitnessMerkleRoot);
impl_hashencode!(FilterHash);
/// Generic trait for functions which may either take a Txid type of Wtxid type as an imput.
/// For instance, used for Merklization procedure
pub trait TxidType: Hash<Inner = [u8; 32]> + Encodable + Decodable { }
impl TxidType for Txid { }
impl TxidType for Wtxid { }

View File

@ -19,9 +19,8 @@ use std::cmp::min;
use std::default::Default;
use hashes::Hash;
use hash_types::{Txid, TxMerkleRoot};
use hash_types::{Txid, TxidType, TxMerkleRoot};
use consensus::encode::Encodable;
/// Any collection of objects for which a merkle root makes sense to calculate
pub trait MerkleRooted {
@ -31,7 +30,7 @@ pub trait MerkleRooted {
}
/// Calculates the merkle root of a list of txids hashes directly
pub fn bitcoin_merkle_root(data: Vec<Txid>) -> TxMerkleRoot {
pub fn bitcoin_merkle_root<T: TxidType>(data: Vec<T>) -> TxMerkleRoot {
// Base case
if data.len() < 1 {
return Default::default();

View File

@ -61,9 +61,9 @@ use std::io;
use hashes::Hash;
use hash_types::{Txid, TxMerkleRoot, TxMerkleBranch};
use blockdata::transaction::Transaction;
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
use consensus::encode::{self, Decodable, Encodable};
use util::hash::BitcoinHash;
use util::merkleblock::MerkleBlockError::*;
use {Block, BlockHeader};
@ -445,7 +445,7 @@ impl MerkleBlock {
let mut matches: Vec<bool> = Vec::with_capacity(block.txdata.len());
let mut hashes: Vec<Txid> = Vec::with_capacity(block.txdata.len());
for hash in block.txdata.iter().map(BitcoinHash::bitcoin_hash) {
for hash in block.txdata.iter().map(Transaction::txid) {
matches.push(match_txids.contains(&hash));
hashes.push(hash);
}