Moving from BitcoinHash to Wtxid for Transactions
This commit is contained in:
parent
f5a8087105
commit
0abe15b1f6
|
@ -24,7 +24,7 @@ use util;
|
||||||
use util::Error::{BlockBadTarget, BlockBadProofOfWork};
|
use util::Error::{BlockBadTarget, BlockBadProofOfWork};
|
||||||
use util::hash::{BitcoinHash, MerkleRooted, bitcoin_merkle_root};
|
use util::hash::{BitcoinHash, MerkleRooted, bitcoin_merkle_root};
|
||||||
use hashes::{Hash, sha256d, HashEngine};
|
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 util::uint::Uint256;
|
||||||
use consensus::encode::Encodable;
|
use consensus::encode::Encodable;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
@ -103,8 +103,8 @@ impl Block {
|
||||||
|
|
||||||
/// Merkle root of transactions hashed for witness
|
/// Merkle root of transactions hashed for witness
|
||||||
pub fn witness_root(&self) -> WitnessMerkleRoot {
|
pub fn witness_root(&self) -> WitnessMerkleRoot {
|
||||||
let mut txhashes = vec!(Txid::default());
|
let mut txhashes = vec!(Wtxid::default());
|
||||||
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.bitcoin_hash()));
|
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.wtxid()));
|
||||||
let hash_value: sha256d::Hash = bitcoin_merkle_root(txhashes).into();
|
let hash_value: sha256d::Hash = bitcoin_merkle_root(txhashes).into();
|
||||||
hash_value.into()
|
hash_value.into()
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ impl Block {
|
||||||
|
|
||||||
impl MerkleRooted for Block {
|
impl MerkleRooted for Block {
|
||||||
fn merkle_root(&self) -> TxMerkleRoot {
|
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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,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!(format!("{:x}", gen.bitcoin_hash()),
|
assert_eq!(format!("{:x}", gen.wtxid()),
|
||||||
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
|
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ use hashes::{self, Hash, sha256d};
|
||||||
use hashes::hex::FromHex;
|
use hashes::hex::FromHex;
|
||||||
|
|
||||||
use util::endian;
|
use util::endian;
|
||||||
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};
|
||||||
|
@ -287,12 +286,12 @@ impl Transaction {
|
||||||
input: self.input.iter().map(|txin| TxIn { script_sig: Script::new(), witness: vec![], .. *txin }).collect(),
|
input: self.input.iter().map(|txin| TxIn { script_sig: Script::new(), witness: vec![], .. *txin }).collect(),
|
||||||
output: self.output.clone(),
|
output: self.output.clone(),
|
||||||
};
|
};
|
||||||
cloned_tx.bitcoin_hash().into()
|
cloned_tx.txid().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the txid. For non-segwit transactions this will be identical
|
/// Computes the txid. For non-segwit transactions this will be identical
|
||||||
/// to the output of `BitcoinHash::bitcoin_hash()`, but for segwit transactions,
|
/// to the output of `wtxid()`, 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 `wtxid`
|
||||||
/// will also hash witnesses.
|
/// will also hash witnesses.
|
||||||
pub fn txid(&self) -> Txid {
|
pub fn txid(&self) -> Txid {
|
||||||
let mut enc = Txid::engine();
|
let mut enc = Txid::engine();
|
||||||
|
@ -303,6 +302,15 @@ impl Transaction {
|
||||||
Txid::from_engine(enc)
|
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.
|
/// 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
|
/// To actually produce a scriptSig, this hash needs to be run through an
|
||||||
/// ECDSA signer, the SigHashType appended to the resulting sig, and a
|
/// 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_consensus_encoding!(TxOut, value, script_pubkey);
|
||||||
|
|
||||||
impl Encodable for OutPoint {
|
impl Encodable for OutPoint {
|
||||||
|
@ -626,7 +626,6 @@ 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;
|
|
||||||
|
|
||||||
use hashes::Hash;
|
use hashes::Hash;
|
||||||
use hashes::hex::FromHex;
|
use hashes::hex::FromHex;
|
||||||
|
@ -712,7 +711,9 @@ mod tests {
|
||||||
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!(format!("{:x}", realtx.bitcoin_hash()),
|
assert_eq!(format!("{:x}", realtx.txid()),
|
||||||
|
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
|
||||||
|
assert_eq!(format!("{:x}", realtx.wtxid()),
|
||||||
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
|
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
|
||||||
assert_eq!(realtx.get_weight(), 193*4);
|
assert_eq!(realtx.get_weight(), 193*4);
|
||||||
}
|
}
|
||||||
|
@ -781,7 +782,7 @@ mod tests {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let tx: Transaction = deserialize(&hex_tx).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!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec");
|
||||||
assert_eq!(tx.get_weight(), 2718);
|
assert_eq!(tx.get_weight(), 2718);
|
||||||
|
|
||||||
|
@ -796,7 +797,7 @@ mod tests {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let tx: Transaction = deserialize(&hex_tx).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");
|
assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,3 +66,9 @@ impl_hashencode!(TxMerkleRoot);
|
||||||
impl_hashencode!(TxMerkleBranch);
|
impl_hashencode!(TxMerkleBranch);
|
||||||
impl_hashencode!(WitnessMerkleRoot);
|
impl_hashencode!(WitnessMerkleRoot);
|
||||||
impl_hashencode!(FilterHash);
|
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 { }
|
||||||
|
|
|
@ -19,9 +19,8 @@ use std::cmp::min;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
||||||
use hashes::Hash;
|
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
|
/// Any collection of objects for which a merkle root makes sense to calculate
|
||||||
pub trait MerkleRooted {
|
pub trait MerkleRooted {
|
||||||
|
@ -31,7 +30,7 @@ pub trait MerkleRooted {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<Txid>) -> TxMerkleRoot {
|
pub fn bitcoin_merkle_root<T: TxidType>(data: Vec<T>) -> TxMerkleRoot {
|
||||||
// Base case
|
// Base case
|
||||||
if data.len() < 1 {
|
if data.len() < 1 {
|
||||||
return Default::default();
|
return Default::default();
|
||||||
|
|
|
@ -61,9 +61,9 @@ use std::io;
|
||||||
use hashes::Hash;
|
use hashes::Hash;
|
||||||
use hash_types::{Txid, TxMerkleRoot, TxMerkleBranch};
|
use hash_types::{Txid, TxMerkleRoot, TxMerkleBranch};
|
||||||
|
|
||||||
|
use blockdata::transaction::Transaction;
|
||||||
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
||||||
use consensus::encode::{self, Decodable, Encodable};
|
use consensus::encode::{self, Decodable, Encodable};
|
||||||
use util::hash::BitcoinHash;
|
|
||||||
use util::merkleblock::MerkleBlockError::*;
|
use util::merkleblock::MerkleBlockError::*;
|
||||||
use {Block, BlockHeader};
|
use {Block, BlockHeader};
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ impl MerkleBlock {
|
||||||
let mut matches: Vec<bool> = Vec::with_capacity(block.txdata.len());
|
let mut matches: Vec<bool> = Vec::with_capacity(block.txdata.len());
|
||||||
let mut hashes: Vec<Txid> = 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));
|
matches.push(match_txids.contains(&hash));
|
||||||
hashes.push(hash);
|
hashes.push(hash);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue