Replaced all hash160, sha256 and sha256d with the new hash types throughout the code
Embedding Txid's in the doc exaples
This commit is contained in:
parent
5ef39e34fa
commit
5f4f629bb1
|
@ -26,7 +26,7 @@ use util;
|
||||||
use util::Error::{BlockBadTarget, BlockBadProofOfWork};
|
use util::Error::{BlockBadTarget, BlockBadProofOfWork};
|
||||||
use util::hash::{BitcoinHash, MerkleRoot, bitcoin_merkle_root};
|
use util::hash::{BitcoinHash, MerkleRoot, bitcoin_merkle_root};
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
use hash_types::BlockHash;
|
use hash_types::{Txid, BlockHash};
|
||||||
use consensus::encode::Encodable;
|
use consensus::encode::Encodable;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use blockdata::transaction::Transaction;
|
use blockdata::transaction::Transaction;
|
||||||
|
@ -105,7 +105,7 @@ impl Block {
|
||||||
|
|
||||||
/// Merkle root of transactions hashed for witness
|
/// Merkle root of transactions hashed for witness
|
||||||
pub fn witness_root(&self) -> sha256d::Hash {
|
pub fn witness_root(&self) -> sha256d::Hash {
|
||||||
let mut txhashes = vec!(sha256d::Hash::default());
|
let mut txhashes = vec!(Txid::default());
|
||||||
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.bitcoin_hash()));
|
txhashes.extend(self.txdata.iter().skip(1).map(|t|t.bitcoin_hash()));
|
||||||
bitcoin_merkle_root(txhashes)
|
bitcoin_merkle_root(txhashes)
|
||||||
}
|
}
|
||||||
|
@ -189,15 +189,15 @@ impl BlockHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitcoinHash for BlockHeader {
|
impl BitcoinHash<BlockHash> for BlockHeader {
|
||||||
fn bitcoin_hash(&self) -> sha256d::Hash {
|
fn bitcoin_hash(&self) -> BlockHash {
|
||||||
use consensus::encode::serialize;
|
use consensus::encode::serialize;
|
||||||
sha256d::Hash::hash(&serialize(self))
|
BlockHash::hash(&serialize(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitcoinHash for Block {
|
impl BitcoinHash<BlockHash> for Block {
|
||||||
fn bitcoin_hash(&self) -> sha256d::Hash {
|
fn bitcoin_hash(&self) -> BlockHash {
|
||||||
self.header.bitcoin_hash()
|
self.header.bitcoin_hash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,10 @@ use std::{error, fmt, io};
|
||||||
|
|
||||||
#[cfg(feature = "serde")] use serde;
|
#[cfg(feature = "serde")] use serde;
|
||||||
|
|
||||||
|
use hash_types::WScriptHash;
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use consensus::{encode, Decodable, Encodable};
|
use consensus::{encode, Decodable, Encodable};
|
||||||
use hashes::{hash160, sha256, Hash};
|
use hashes::{hash160, 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 OutPoint;
|
#[cfg(feature="bitcoinconsensus")] use OutPoint;
|
||||||
|
@ -242,7 +243,7 @@ impl Script {
|
||||||
/// script")
|
/// script")
|
||||||
pub fn to_v0_p2wsh(&self) -> Script {
|
pub fn to_v0_p2wsh(&self) -> Script {
|
||||||
Builder::new().push_int(0)
|
Builder::new().push_int(0)
|
||||||
.push_slice(&sha256::Hash::hash(&self.0)[..])
|
.push_slice(&WScriptHash::hash(&self.0)[..])
|
||||||
.into_script()
|
.into_script()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,7 @@ 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()
|
cloned_tx.bitcoin_hash().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the txid. For non-segwit transactions this will be identical
|
/// Computes the txid. For non-segwit transactions this will be identical
|
||||||
|
@ -438,11 +438,11 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitcoinHash for Transaction {
|
impl BitcoinHash<Txid> for Transaction {
|
||||||
fn bitcoin_hash(&self) -> sha256d::Hash {
|
fn bitcoin_hash(&self) -> Txid {
|
||||||
let mut enc = sha256d::Hash::engine();
|
let mut enc = sha256d::Hash::engine();
|
||||||
self.consensus_encode(&mut enc).unwrap();
|
self.consensus_encode(&mut enc).unwrap();
|
||||||
sha256d::Hash::from_engine(enc)
|
Txid::from_engine(enc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ use std::fmt::{self, Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use bech32;
|
use bech32;
|
||||||
use hashes::{hash160, sha256, Hash};
|
use hashes::{hash160, Hash};
|
||||||
|
|
||||||
use hash_types::{PubkeyHash, ScriptHash, WScriptHash};
|
use hash_types::{PubkeyHash, ScriptHash, WScriptHash};
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
|
@ -309,7 +309,7 @@ impl Address {
|
||||||
pub fn p2shwsh(script: &script::Script, network: Network) -> Address {
|
pub fn p2shwsh(script: &script::Script, network: Network) -> Address {
|
||||||
let ws = script::Builder::new()
|
let ws = script::Builder::new()
|
||||||
.push_int(0)
|
.push_int(0)
|
||||||
.push_slice(&sha256::Hash::hash(&script[..])[..])
|
.push_slice(&WScriptHash::hash(&script[..])[..])
|
||||||
.into_script();
|
.into_script();
|
||||||
|
|
||||||
Address {
|
Address {
|
||||||
|
|
|
@ -50,6 +50,7 @@ use std::error;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use hash_types::BlockHash;
|
||||||
use hashes::{Hash, sha256d, siphash24};
|
use hashes::{Hash, sha256d, siphash24};
|
||||||
|
|
||||||
use blockdata::block::Block;
|
use blockdata::block::Block;
|
||||||
|
@ -133,13 +134,13 @@ impl BlockFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// match any query pattern
|
/// match any query pattern
|
||||||
pub fn match_any(&self, block_hash: &sha256d::Hash, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
pub fn match_any(&self, block_hash: &BlockHash, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
||||||
let filter_reader = BlockFilterReader::new(block_hash);
|
let filter_reader = BlockFilterReader::new(block_hash);
|
||||||
filter_reader.match_any(&mut Cursor::new(self.content.as_slice()), query)
|
filter_reader.match_any(&mut Cursor::new(self.content.as_slice()), query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// match all query pattern
|
/// match all query pattern
|
||||||
pub fn match_all(&self, block_hash: &sha256d::Hash, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
pub fn match_all(&self, block_hash: &BlockHash, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
||||||
let filter_reader = BlockFilterReader::new(block_hash);
|
let filter_reader = BlockFilterReader::new(block_hash);
|
||||||
filter_reader.match_all(&mut Cursor::new(self.content.as_slice()), query)
|
filter_reader.match_all(&mut Cursor::new(self.content.as_slice()), query)
|
||||||
}
|
}
|
||||||
|
@ -206,7 +207,7 @@ pub struct BlockFilterReader {
|
||||||
|
|
||||||
impl BlockFilterReader {
|
impl BlockFilterReader {
|
||||||
/// Create a block filter reader
|
/// Create a block filter reader
|
||||||
pub fn new(block_hash: &sha256d::Hash) -> BlockFilterReader {
|
pub fn new(block_hash: &BlockHash) -> BlockFilterReader {
|
||||||
let block_hash_as_int = block_hash.into_inner();
|
let block_hash_as_int = block_hash.into_inner();
|
||||||
let k0 = endian::slice_to_u64_le(&block_hash_as_int[0..8]);
|
let k0 = endian::slice_to_u64_le(&block_hash_as_int[0..8]);
|
||||||
let k1 = endian::slice_to_u64_le(&block_hash_as_int[8..16]);
|
let k1 = endian::slice_to_u64_le(&block_hash_as_int[8..16]);
|
||||||
|
@ -523,6 +524,7 @@ mod test {
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use hash_types::BlockHash;
|
||||||
use hashes::hex::FromHex;
|
use hashes::hex::FromHex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -555,7 +557,7 @@ mod test {
|
||||||
|
|
||||||
let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
|
let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
|
||||||
for t in testdata.iter().skip(1) {
|
for t in testdata.iter().skip(1) {
|
||||||
let block_hash = sha256d::Hash::from_hex(&t.get(1).unwrap().as_str().unwrap()).unwrap();
|
let block_hash = BlockHash::from_hex(&t.get(1).unwrap().as_str().unwrap()).unwrap();
|
||||||
let block: Block = deserialize(hex::decode(&t.get(2).unwrap().as_str().unwrap().as_bytes()).unwrap().as_slice()).unwrap();
|
let block: Block = deserialize(hex::decode(&t.get(2).unwrap().as_str().unwrap().as_bytes()).unwrap().as_slice()).unwrap();
|
||||||
assert_eq!(block.bitcoin_hash(), block_hash);
|
assert_eq!(block.bitcoin_hash(), block_hash);
|
||||||
let scripts = t.get(3).unwrap().as_array().unwrap();
|
let scripts = t.get(3).unwrap().as_array().unwrap();
|
||||||
|
@ -583,7 +585,7 @@ mod test {
|
||||||
assert_eq!(test_filter.content, filter.content);
|
assert_eq!(test_filter.content, filter.content);
|
||||||
|
|
||||||
let block_hash = &block.header.bitcoin_hash();
|
let block_hash = &block.header.bitcoin_hash();
|
||||||
assert!(filter.match_all(&block_hash, &mut txmap.iter()
|
assert!(filter.match_all(block_hash, &mut txmap.iter()
|
||||||
.filter_map(|(_, s)| if !s.is_empty() { Some(s.as_bytes()) } else { None })).unwrap());
|
.filter_map(|(_, s)| if !s.is_empty() { Some(s.as_bytes()) } else { None })).unwrap());
|
||||||
|
|
||||||
for (_, script) in &txmap {
|
for (_, script) in &txmap {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
||||||
|
use hash_types::Txid;
|
||||||
use hashes::{sha256d, Hash};
|
use hashes::{sha256d, Hash};
|
||||||
|
|
||||||
use consensus::encode::Encodable;
|
use consensus::encode::Encodable;
|
||||||
|
@ -30,13 +31,13 @@ pub trait MerkleRoot {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<sha256d::Hash>) -> sha256d::Hash {
|
pub fn bitcoin_merkle_root(data: Vec<Txid>) -> sha256d::Hash {
|
||||||
// Base case
|
// Base case
|
||||||
if data.len() < 1 {
|
if data.len() < 1 {
|
||||||
return Default::default();
|
return Default::default();
|
||||||
}
|
}
|
||||||
if data.len() < 2 {
|
if data.len() < 2 {
|
||||||
return data[0];
|
return data[0].into();
|
||||||
}
|
}
|
||||||
// Recursion
|
// Recursion
|
||||||
let mut next = vec![];
|
let mut next = vec![];
|
||||||
|
@ -46,13 +47,13 @@ pub fn bitcoin_merkle_root(data: Vec<sha256d::Hash>) -> sha256d::Hash {
|
||||||
let mut encoder = sha256d::Hash::engine();
|
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(sha256d::Hash::from_engine(encoder));
|
next.push(Txid::from_engine(encoder));
|
||||||
}
|
}
|
||||||
bitcoin_merkle_root(next)
|
bitcoin_merkle_root(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Objects which are referred to by hash
|
/// Objects which are referred to by hash
|
||||||
pub trait BitcoinHash {
|
pub trait BitcoinHash<T: Hash> {
|
||||||
/// 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) -> sha256d::Hash;
|
fn bitcoin_hash(&self) -> T;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate bitcoin;
|
//! extern crate bitcoin;
|
||||||
//! use bitcoin::hashes::sha256d;
|
//! use bitcoin::hash_types::Txid;
|
||||||
//! use bitcoin::hashes::hex::FromHex;
|
//! use bitcoin::hashes::hex::FromHex;
|
||||||
//! use bitcoin::{Block, MerkleBlock};
|
//! use bitcoin::{Block, MerkleBlock};
|
||||||
//!
|
//!
|
||||||
|
@ -41,12 +41,12 @@
|
||||||
//! let mb: MerkleBlock = bitcoin::consensus::deserialize(&mb_bytes).unwrap();
|
//! let mb: MerkleBlock = bitcoin::consensus::deserialize(&mb_bytes).unwrap();
|
||||||
//!
|
//!
|
||||||
//! // Authenticate and extract matched transaction ids
|
//! // Authenticate and extract matched transaction ids
|
||||||
//! let mut matches: Vec<sha256d::Hash> = vec![];
|
//! let mut matches: Vec<Txid> = vec![];
|
||||||
//! let mut index: Vec<u32> = vec![];
|
//! let mut index: Vec<u32> = vec![];
|
||||||
//! assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
//! assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
||||||
//! assert_eq!(1, matches.len());
|
//! assert_eq!(1, matches.len());
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! sha256d::Hash::from_hex(
|
//! Txid::from_hex(
|
||||||
//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap(),
|
//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap(),
|
||||||
//! matches[0]
|
//! matches[0]
|
||||||
//! );
|
//! );
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use hash_types::Txid;
|
||||||
use hashes::{sha256d, Hash};
|
use hashes::{sha256d, Hash};
|
||||||
|
|
||||||
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
||||||
|
@ -133,18 +134,18 @@ impl PartialMerkleTree {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate bitcoin;
|
/// extern crate bitcoin;
|
||||||
/// use bitcoin::hashes::sha256d;
|
/// use bitcoin::hash_types::Txid;
|
||||||
/// use bitcoin::hashes::hex::FromHex;
|
/// use bitcoin::hashes::hex::FromHex;
|
||||||
/// use bitcoin::util::merkleblock::PartialMerkleTree;
|
/// use bitcoin::util::merkleblock::PartialMerkleTree;
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// // Block 80000
|
/// // Block 80000
|
||||||
/// let txids: Vec<sha256d::Hash> = [
|
/// let txids: Vec<Txid> = [
|
||||||
/// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25",
|
/// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25",
|
||||||
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2",
|
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2",
|
||||||
/// ]
|
/// ]
|
||||||
/// .iter()
|
/// .iter()
|
||||||
/// .map(|hex| sha256d::Hash::from_hex(hex).unwrap())
|
/// .map(|hex| Txid::from_hex(hex).unwrap())
|
||||||
/// .collect();
|
/// .collect();
|
||||||
///
|
///
|
||||||
/// // Select the second transaction
|
/// // Select the second transaction
|
||||||
|
@ -153,7 +154,7 @@ impl PartialMerkleTree {
|
||||||
/// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok());
|
/// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok());
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_txids(txids: &[sha256d::Hash], matches: &[bool]) -> Self {
|
pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self {
|
||||||
// We can never have zero txs in a merkle block, we always need the coinbase tx
|
// We can never have zero txs in a merkle block, we always need the coinbase tx
|
||||||
assert_ne!(txids.len(), 0);
|
assert_ne!(txids.len(), 0);
|
||||||
assert_eq!(txids.len(), matches.len());
|
assert_eq!(txids.len(), matches.len());
|
||||||
|
@ -178,7 +179,7 @@ impl PartialMerkleTree {
|
||||||
/// returns the merkle root, or error in case of failure
|
/// returns the merkle root, or error in case of failure
|
||||||
pub fn extract_matches(
|
pub fn extract_matches(
|
||||||
&self,
|
&self,
|
||||||
matches: &mut Vec<sha256d::Hash>,
|
matches: &mut Vec<Txid>,
|
||||||
indexes: &mut Vec<u32>,
|
indexes: &mut Vec<u32>,
|
||||||
) -> Result<sha256d::Hash, MerkleBlockError> {
|
) -> Result<sha256d::Hash, MerkleBlockError> {
|
||||||
matches.clear();
|
matches.clear();
|
||||||
|
@ -231,10 +232,10 @@ impl PartialMerkleTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves)
|
/// Calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves)
|
||||||
fn calc_hash(&self, height: u32, pos: u32, txids: &[sha256d::Hash]) -> sha256d::Hash {
|
fn calc_hash(&self, height: u32, pos: u32, txids: &[Txid]) -> sha256d::Hash {
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
// Hash at height 0 is the txid itself
|
// Hash at height 0 is the txid itself
|
||||||
txids[pos as usize]
|
txids[pos as usize].into()
|
||||||
} else {
|
} else {
|
||||||
// Calculate left hash
|
// Calculate left hash
|
||||||
let left = self.calc_hash(height - 1, pos * 2, txids);
|
let left = self.calc_hash(height - 1, pos * 2, txids);
|
||||||
|
@ -254,7 +255,7 @@ impl PartialMerkleTree {
|
||||||
&mut self,
|
&mut self,
|
||||||
height: u32,
|
height: u32,
|
||||||
pos: u32,
|
pos: u32,
|
||||||
txids: &[sha256d::Hash],
|
txids: &[Txid],
|
||||||
matches: &[bool],
|
matches: &[bool],
|
||||||
) {
|
) {
|
||||||
// Determine whether this node is the parent of at least one matched txid
|
// Determine whether this node is the parent of at least one matched txid
|
||||||
|
@ -270,7 +271,7 @@ impl PartialMerkleTree {
|
||||||
if height == 0 || !parent_of_match {
|
if height == 0 || !parent_of_match {
|
||||||
// If at height 0, or nothing interesting below, store hash and stop
|
// If at height 0, or nothing interesting below, store hash and stop
|
||||||
let hash = self.calc_hash(height, pos, txids);
|
let hash = self.calc_hash(height, pos, txids);
|
||||||
self.hashes.push(hash);
|
self.hashes.push(hash.into());
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, don't store any hash, but descend into the subtrees
|
// Otherwise, don't store any hash, but descend into the subtrees
|
||||||
self.traverse_and_build(height - 1, pos * 2, txids, matches);
|
self.traverse_and_build(height - 1, pos * 2, txids, matches);
|
||||||
|
@ -288,7 +289,7 @@ impl PartialMerkleTree {
|
||||||
pos: u32,
|
pos: u32,
|
||||||
bits_used: &mut u32,
|
bits_used: &mut u32,
|
||||||
hash_used: &mut u32,
|
hash_used: &mut u32,
|
||||||
matches: &mut Vec<sha256d::Hash>,
|
matches: &mut Vec<Txid>,
|
||||||
indexes: &mut Vec<u32>,
|
indexes: &mut Vec<u32>,
|
||||||
) -> Result<sha256d::Hash, MerkleBlockError> {
|
) -> Result<sha256d::Hash, MerkleBlockError> {
|
||||||
if *bits_used as usize >= self.bits.len() {
|
if *bits_used as usize >= self.bits.len() {
|
||||||
|
@ -305,7 +306,7 @@ impl PartialMerkleTree {
|
||||||
*hash_used += 1;
|
*hash_used += 1;
|
||||||
if height == 0 && parent_of_match {
|
if height == 0 && parent_of_match {
|
||||||
// in case of height 0, we have a matched txid
|
// in case of height 0, we have a matched txid
|
||||||
matches.push(hash);
|
matches.push(hash.into());
|
||||||
indexes.push(pos);
|
indexes.push(pos);
|
||||||
}
|
}
|
||||||
Ok(hash)
|
Ok(hash)
|
||||||
|
@ -407,7 +408,7 @@ impl MerkleBlock {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate bitcoin;
|
/// extern crate bitcoin;
|
||||||
/// use bitcoin::hashes::sha256d;
|
/// use bitcoin::hash_types::Txid;
|
||||||
/// use bitcoin::hashes::hex::FromHex;
|
/// use bitcoin::hashes::hex::FromHex;
|
||||||
/// use bitcoin::{Block, MerkleBlock};
|
/// use bitcoin::{Block, MerkleBlock};
|
||||||
///
|
///
|
||||||
|
@ -426,23 +427,23 @@ impl MerkleBlock {
|
||||||
/// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap();
|
/// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap();
|
||||||
///
|
///
|
||||||
/// // Create a merkle block containing a single transaction
|
/// // Create a merkle block containing a single transaction
|
||||||
/// let txid = sha256d::Hash::from_hex(
|
/// let txid = Txid::from_hex(
|
||||||
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap();
|
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap();
|
||||||
/// let match_txids = vec![txid].into_iter().collect();
|
/// let match_txids = vec![txid].into_iter().collect();
|
||||||
/// let mb = MerkleBlock::from_block(&block, &match_txids);
|
/// let mb = MerkleBlock::from_block(&block, &match_txids);
|
||||||
///
|
///
|
||||||
/// // Authenticate and extract matched transaction ids
|
/// // Authenticate and extract matched transaction ids
|
||||||
/// let mut matches: Vec<sha256d::Hash> = vec![];
|
/// let mut matches: Vec<Txid> = vec![];
|
||||||
/// let mut index: Vec<u32> = vec![];
|
/// let mut index: Vec<u32> = vec![];
|
||||||
/// assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
/// assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
||||||
/// assert_eq!(txid, matches[0]);
|
/// assert_eq!(txid, matches[0]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_block(block: &Block, match_txids: &HashSet<sha256d::Hash>) -> Self {
|
pub fn from_block(block: &Block, match_txids: &HashSet<Txid>) -> Self {
|
||||||
let header = block.header;
|
let header = block.header;
|
||||||
|
|
||||||
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<sha256d::Hash> = 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(BitcoinHash::bitcoin_hash) {
|
||||||
matches.push(match_txids.contains(&hash));
|
matches.push(match_txids.contains(&hash));
|
||||||
|
@ -458,7 +459,7 @@ impl MerkleBlock {
|
||||||
/// returns Ok(()) on success, or error in case of failure
|
/// returns Ok(()) on success, or error in case of failure
|
||||||
pub fn extract_matches(
|
pub fn extract_matches(
|
||||||
&self,
|
&self,
|
||||||
matches: &mut Vec<sha256d::Hash>,
|
matches: &mut Vec<Txid>,
|
||||||
indexes: &mut Vec<u32>,
|
indexes: &mut Vec<u32>,
|
||||||
) -> Result<(), MerkleBlockError> {
|
) -> Result<(), MerkleBlockError> {
|
||||||
let merkle_root = self.txn.extract_matches(matches, indexes)?;
|
let merkle_root = self.txn.extract_matches(matches, indexes)?;
|
||||||
|
@ -495,6 +496,7 @@ impl Decodable for MerkleBlock {
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
|
use hash_types::Txid;
|
||||||
use hashes::hex::{FromHex, ToHex};
|
use hashes::hex::{FromHex, ToHex};
|
||||||
use hashes::{sha256d, Hash};
|
use hashes::{sha256d, Hash};
|
||||||
use secp256k1::rand::prelude::*;
|
use secp256k1::rand::prelude::*;
|
||||||
|
@ -512,7 +514,7 @@ mod tests {
|
||||||
for num_tx in tx_counts {
|
for num_tx in tx_counts {
|
||||||
// Create some fake tx ids
|
// Create some fake tx ids
|
||||||
let txids = (1..num_tx + 1) // change to `1..=num_tx` when min Rust >= 1.26.0
|
let txids = (1..num_tx + 1) // change to `1..=num_tx` when min Rust >= 1.26.0
|
||||||
.map(|i| sha256d::Hash::from_hex(&format!("{:064x}", i)).unwrap())
|
.map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Calculate the merkle root and height
|
// Calculate the merkle root and height
|
||||||
|
@ -555,7 +557,7 @@ mod tests {
|
||||||
deserialize(&serialized).expect("Could not deserialize own data");
|
deserialize(&serialized).expect("Could not deserialize own data");
|
||||||
|
|
||||||
// Extract merkle root and matched txids from copy
|
// Extract merkle root and matched txids from copy
|
||||||
let mut match_txid2 = vec![];
|
let mut match_txid2: Vec<Txid> = vec![];
|
||||||
let mut indexes = vec![];
|
let mut indexes = vec![];
|
||||||
let merkle_root_2 = pmt2
|
let merkle_root_2 = pmt2
|
||||||
.extract_matches(&mut match_txid2, &mut indexes)
|
.extract_matches(&mut match_txid2, &mut indexes)
|
||||||
|
@ -585,9 +587,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn pmt_malleability() {
|
fn pmt_malleability() {
|
||||||
// Create some fake tx ids with the last 2 hashes repeating
|
// Create some fake tx ids with the last 2 hashes repeating
|
||||||
let txids: Vec<sha256d::Hash> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10]
|
let txids: Vec<Txid> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| sha256d::Hash::from_hex(&format!("{:064x}", i)).unwrap())
|
.map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let matches = vec![
|
let matches = vec![
|
||||||
|
@ -628,12 +630,12 @@ mod tests {
|
||||||
fn merkleblock_construct_from_txids_found() {
|
fn merkleblock_construct_from_txids_found() {
|
||||||
let block = get_block_13b8a();
|
let block = get_block_13b8a();
|
||||||
|
|
||||||
let txids: Vec<sha256d::Hash> = [
|
let txids: Vec<Txid> = [
|
||||||
"74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20",
|
"74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20",
|
||||||
"f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07",
|
"f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07",
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hex| sha256d::Hash::from_hex(hex).unwrap())
|
.map(|hex| Txid::from_hex(hex).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let txid1 = txids[0];
|
let txid1 = txids[0];
|
||||||
|
@ -644,7 +646,7 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash());
|
assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash());
|
||||||
|
|
||||||
let mut matches: Vec<sha256d::Hash> = vec![];
|
let mut matches: Vec<Txid> = vec![];
|
||||||
let mut index: Vec<u32> = vec![];
|
let mut index: Vec<u32> = vec![];
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -670,14 +672,14 @@ mod tests {
|
||||||
let block = get_block_13b8a();
|
let block = get_block_13b8a();
|
||||||
let txids = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"]
|
let txids = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hex| sha256d::Hash::from_hex(hex).unwrap())
|
.map(|hex| Txid::from_hex(hex).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let merkle_block = MerkleBlock::from_block(&block, &txids);
|
let merkle_block = MerkleBlock::from_block(&block, &txids);
|
||||||
|
|
||||||
assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash());
|
assert_eq!(merkle_block.header.bitcoin_hash(), block.bitcoin_hash());
|
||||||
|
|
||||||
let mut matches: Vec<sha256d::Hash> = vec![];
|
let mut matches: Vec<Txid> = vec![];
|
||||||
let mut index: Vec<u32> = vec![];
|
let mut index: Vec<u32> = vec![];
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue