From 15f6cf5ae9d528f8aae774a46e69a13541ab77f6 Mon Sep 17 00:00:00 2001 From: shotonoff Date: Fri, 31 Mar 2023 16:18:13 +0200 Subject: [PATCH 1/4] feat: add x11 hash algorithm to compute a block-hash from a header --- Cargo.toml | 2 + src/blockdata/block.rs | 19 ++-- src/consensus/encode.rs | 8 +- src/hash_types.rs | 6 +- src/hash_x11.rs | 150 +++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/network/message_blockdata.rs | 18 ++-- src/network/message_filter.rs | 14 +-- src/util/bip158.rs | 12 +-- 9 files changed, 197 insertions(+), 34 deletions(-) create mode 100644 src/hash_x11.rs diff --git a/Cargo.toml b/Cargo.toml index 316288b36..22faad319 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,8 @@ hashbrown = { version = "0.8", optional = true } anyhow = { version= "1.0", optional = true} hex = { version= "0.4", optional = true} +rs-x11-hash = "0.1" + [dev-dependencies] serde_json = "<1.0.45" serde_test = "1" diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 506045d35..f1f9738ad 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -27,11 +27,11 @@ use prelude::*; use core::fmt; -use util; +use ::{BlockHash, util}; use util::Error::{BlockBadTarget, BlockBadProofOfWork}; use util::hash::dash_merkle_root; use hashes::{Hash, HashEngine}; -use hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; +use hash_types::{Wtxid, BlockHash256, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; use util::uint::Uint256; use consensus::encode::Encodable; use network::constants::Network; @@ -48,7 +48,7 @@ pub struct BlockHeader { /// The protocol version. Should always be 1. pub version: i32, /// Reference to the previous block in the chain. - pub prev_blockhash: BlockHash, + pub prev_blockhash: BlockHash256, /// The root hash of the merkle tree of transactions in the block. pub merkle_root: TxMerkleNode, /// The timestamp of the block, as claimed by the miner. @@ -64,7 +64,14 @@ impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time impl BlockHeader { /// Returns the block hash. - pub fn block_hash(&self) -> BlockHash { + pub fn block_hash(&self) -> BlockHash256 { + let mut engine = BlockHash256::engine(); + self.consensus_encode(&mut engine).expect("engines don't error"); + BlockHash256::from_engine(engine) + } + + /// Returns the block hash. + pub fn block_hash_x11(&self) -> BlockHash { let mut engine = BlockHash::engine(); self.consensus_encode(&mut engine).expect("engines don't error"); BlockHash::from_engine(engine) @@ -134,7 +141,7 @@ impl BlockHeader { } /// Checks that the proof-of-work for the block is valid, returning the block hash. - pub fn validate_pow(&self, required_target: &Uint256) -> Result { + pub fn validate_pow(&self, required_target: &Uint256) -> Result { let target = &self.target(); if target != required_target { return Err(BlockBadTarget); @@ -173,7 +180,7 @@ impl_consensus_encoding!(Block, header, txdata); impl Block { /// Returns the block hash. - pub fn block_hash(&self) -> BlockHash { + pub fn block_hash(&self) -> BlockHash256 { self.header.block_hash() } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 8597ff755..507b74549 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -36,7 +36,7 @@ use core::{fmt, mem, u32, convert::From}; #[cfg(feature = "std")] use std::error; use hashes::{sha256d, Hash, sha256, hash160}; -use hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; +use hash_types::{BlockHash256, FilterHash, TxMerkleNode, FilterHeader}; use io::{self, Cursor, Read}; @@ -608,7 +608,7 @@ macro_rules! impl_vec { } } } -impl_vec!(BlockHash); +impl_vec!(BlockHash256); impl_vec!(FilterHash); impl_vec!(FilterHeader); impl_vec!(TxMerkleNode); @@ -822,7 +822,7 @@ mod tests { use super::*; use core::{mem::{self, discriminant}, fmt}; use super::{deserialize, serialize, Error, CheckedData, VarInt}; - use super::{Transaction, BlockHash, FilterHash, TxMerkleNode, TxOut, TxIn}; + use super::{Transaction, BlockHash256, FilterHash, TxMerkleNode, TxOut, TxIn}; use consensus::{Encodable, deserialize_partial, Decodable}; use util::endian::{u64_to_array_le, u32_to_array_le, u16_to_array_le}; use secp256k1::rand::{thread_rng, Rng}; @@ -1027,7 +1027,7 @@ mod tests { assert_eq!(discriminant(&err), discriminant(&rand_io_err)); test_len_is_max_vec::(); - test_len_is_max_vec::(); + test_len_is_max_vec::(); test_len_is_max_vec::(); test_len_is_max_vec::(); test_len_is_max_vec::(); diff --git a/src/hash_types.rs b/src/hash_types.rs index ef1074b95..84242fc57 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -24,6 +24,7 @@ //! use hashes::{Hash, sha256, sha256d, hash160}; +use hash_x11; macro_rules! impl_hashencode { ($hashtype:ident) => { @@ -44,7 +45,8 @@ macro_rules! impl_hashencode { hash_newtype!(Txid, sha256d::Hash, 32, doc="A dash transaction hash/transaction ID."); hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A dash witness transaction ID."); -hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A dash block hash."); +hash_newtype!(BlockHash, hash_x11::Hash, 32, doc="A dash block hash."); +hash_newtype!(BlockHash256, sha256d::Hash, 32, doc="A dash block sha256 hash."); hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm"); hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key."); @@ -71,7 +73,7 @@ hash_newtype!(QuorumVVecHash, sha256d::Hash, 32, doc="A hash of a quorum verific impl_hashencode!(Txid); impl_hashencode!(Wtxid); -impl_hashencode!(BlockHash); +impl_hashencode!(BlockHash256); impl_hashencode!(Sighash); impl_hashencode!(PubkeyHash); diff --git a/src/hash_x11.rs b/src/hash_x11.rs new file mode 100644 index 000000000..54bb32255 --- /dev/null +++ b/src/hash_x11.rs @@ -0,0 +1,150 @@ +use core::{str}; +use std::io; +use hashes::Error; +use hashes::{Hash as HashTrait, HashEngine as EngineTrait, hex}; +use ::{BlockHeader}; +use consensus; + +hex_fmt_impl!(Display, Hash); +hex_fmt_impl!(LowerHex, Hash); +index_impl!(Hash); +serde_impl!(Hash, 32); +borrow_slice_impl!(Hash); + +#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash, Debug)] +#[repr(transparent)] +pub struct Hash( + [u8; 32] +); + +impl str::FromStr for Hash { + type Err = hex::Error; + fn from_str(s: &str) -> Result { + hex::FromHex::from_hex(s) + } +} + +impl HashTrait for Hash { + type Engine = HashEngine; + type Inner = [u8; 32]; + + fn from_engine(e: Self::Engine) -> Self { + println!("from_engine"); + Hash(e.midstate().into_inner()) + } + + const LEN: usize = 32; + + fn from_slice(sl: &[u8]) -> Result { + if sl.len() != 32 { + Err(Error::InvalidLength(Self::LEN, sl.len())) + } else { + let mut ret = [0; 32]; + ret.copy_from_slice(sl); + Ok(Hash(ret)) + } + } + + fn into_inner(self) -> Self::Inner { + self.0 + } + + fn as_inner(&self) -> &Self::Inner { + &self.0 + } + + fn from_inner(inner: Self::Inner) -> Self { + Hash(inner) + } +} + +#[derive(Default, Clone)] +pub struct HashEngine { + // h: [u8; 32], + buf: Vec, + length: usize, +} + +impl EngineTrait for HashEngine { + type MidState = Midstate; + + fn midstate(&self) -> Self::MidState { + println!("midstate"); + let md: Vec = rs_x11_hash::get_x11_hash(self.buf.as_slice()); + let mut h: [u8; 32] = [0; 32]; + for n in 0..32 { + let v = md.get(n).unwrap(); + h[32-n-1] = *v; + } + Midstate(h) + } + + const BLOCK_SIZE: usize = 32; + + fn input(&mut self, data: &[u8]) { + self.buf.extend_from_slice(data); + } + + fn n_bytes_hashed(&self) -> usize { + self.length + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] +pub struct Midstate(pub [u8; 32]); + +index_impl!(Midstate); +serde_impl!(Midstate, 32); +borrow_slice_impl!(Midstate); + +impl str::FromStr for Midstate { + type Err = hex::Error; + fn from_str(s: &str) -> Result { + hex::FromHex::from_hex(s) + } +} + +impl Midstate { + /// Length of the midstate, in bytes. + const LEN: usize = 32; + + /// Construct a new midstate from the inner value. + pub fn from_inner(inner: [u8; 32]) -> Self { + Midstate(inner) + } + + /// Copies a byte slice into the [Midstate] object. + pub fn from_slice(sl: &[u8]) -> Result { + if sl.len() != Self::LEN { + Err(Error::InvalidLength(Self::LEN, sl.len())) + } else { + let mut ret = [0; 32]; + ret.copy_from_slice(sl); + Ok(Midstate(ret)) + } + } + + /// Unwraps the [Midstate] and returns the underlying byte array. + pub fn into_inner(self) -> [u8; 32] { + self.0 + } +} + +impl hex::FromHex for Midstate { + fn from_byte_iter(iter: I) -> Result + where I: Iterator> + + ExactSizeIterator + + DoubleEndedIterator, + { + Ok(Midstate::from_inner(hex::FromHex::from_byte_iter(iter.rev())?)) + } +} + +impl io::Write for HashEngine { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.input(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} diff --git a/src/lib.rs b/src/lib.rs index 800b640be..bb569058c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,6 +111,8 @@ pub extern crate anyhow; #[cfg(target_pointer_width = "16")] compile_error!("rust-bitcoin cannot be used on 16-bit architectures"); +pub mod hash_x11; + #[cfg(test)] #[macro_use] mod test_macros; diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 940840c0d..2d9c56e23 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -29,7 +29,7 @@ use hashes::sha256d; use network::constants; use consensus::encode::{self, Decodable, Encodable}; -use hash_types::{BlockHash, Txid, Wtxid}; +use hash_types::{BlockHash256, Txid, Wtxid}; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] @@ -39,13 +39,13 @@ pub enum Inventory { /// Transaction Transaction(Txid), /// Block - Block(BlockHash), + Block(BlockHash256), /// Witness Transaction by Wtxid WTx(Wtxid), /// Witness Transaction WitnessTransaction(Txid), /// Witness Block - WitnessBlock(BlockHash), + WitnessBlock(BlockHash256), /// Unknown inventory type Unknown { /// The inventory item type. @@ -104,9 +104,9 @@ pub struct GetBlocksMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the block to stop at, or zero to just fetch the maximum 500 blocks - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, } /// The `getheaders` message @@ -117,14 +117,14 @@ pub struct GetHeadersMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the header to stop at, or zero to just fetch the maximum 2000 headers - pub stop_hash: BlockHash + pub stop_hash: BlockHash256 } impl GetBlocksMessage { /// Construct a new `getblocks` message - pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetBlocksMessage { + pub fn new(locator_hashes: Vec, stop_hash: BlockHash256) -> GetBlocksMessage { GetBlocksMessage { version: constants::PROTOCOL_VERSION, locator_hashes, @@ -137,7 +137,7 @@ impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash); impl GetHeadersMessage { /// Construct a new `getheaders` message - pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetHeadersMessage { + pub fn new(locator_hashes: Vec, stop_hash: BlockHash256) -> GetHeadersMessage { GetHeadersMessage { version: constants::PROTOCOL_VERSION, locator_hashes, diff --git a/src/network/message_filter.rs b/src/network/message_filter.rs index 29f8adb2e..7a6265802 100644 --- a/src/network/message_filter.rs +++ b/src/network/message_filter.rs @@ -3,7 +3,7 @@ //! This module describes BIP157 Client Side Block Filtering network messages. //! -use hash_types::{BlockHash, FilterHash, FilterHeader}; +use hash_types::{BlockHash256, FilterHash, FilterHeader}; /// getcfilters message #[derive(PartialEq, Eq, Clone, Debug)] @@ -13,7 +13,7 @@ pub struct GetCFilters { /// The height of the first block in the requested range pub start_height: u32, /// The hash of the last block in the requested range - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, } impl_consensus_encoding!(GetCFilters, filter_type, start_height, stop_hash); @@ -23,7 +23,7 @@ pub struct CFilter { /// Byte identifying the type of filter being returned pub filter_type: u8, /// Block hash of the Bitcoin block for which the filter is being returned - pub block_hash: BlockHash, + pub block_hash: BlockHash256, /// The serialized compact filter for this block pub filter: Vec, } @@ -37,7 +37,7 @@ pub struct GetCFHeaders { /// The height of the first block in the requested range pub start_height: u32, /// The hash of the last block in the requested range - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, } impl_consensus_encoding!(GetCFHeaders, filter_type, start_height, stop_hash); @@ -47,7 +47,7 @@ pub struct CFHeaders { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, /// The filter header preceding the first block in the requested range pub previous_filter_header: FilterHeader, /// The filter hashes for each block in the requested range @@ -61,7 +61,7 @@ pub struct GetCFCheckpt { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, } impl_consensus_encoding!(GetCFCheckpt, filter_type, stop_hash); @@ -71,7 +71,7 @@ pub struct CFCheckpt { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash, + pub stop_hash: BlockHash256, /// The filter headers at intervals of 1,000 pub filter_headers: Vec, } diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 1705a1531..9dc9b37a2 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -52,7 +52,7 @@ use core::fmt::{self, Display, Formatter}; use core::cmp::{self, Ordering}; use hashes::{Hash, siphash24}; -use hash_types::{BlockHash, FilterHash, FilterHeader}; +use hash_types::{BlockHash256, FilterHash, FilterHeader}; use blockdata::block::Block; use blockdata::script::Script; @@ -137,13 +137,13 @@ impl BlockFilter { } /// match any query pattern - pub fn match_any(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { + pub fn match_any(&self, block_hash: &BlockHash256, query: &mut dyn Iterator) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_any(&mut Cursor::new(self.content.as_slice()), query) } /// match all query pattern - pub fn match_all(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { + pub fn match_all(&self, block_hash: &BlockHash256, query: &mut dyn Iterator) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_all(&mut Cursor::new(self.content.as_slice()), query) } @@ -210,7 +210,7 @@ pub struct BlockFilterReader { impl BlockFilterReader { /// Create a block filter reader - pub fn new(block_hash: &BlockHash) -> BlockFilterReader { + pub fn new(block_hash: &BlockHash256) -> BlockFilterReader { let block_hash_as_int = block_hash.into_inner(); 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]); @@ -513,7 +513,7 @@ impl<'a> BitStreamWriter<'a> { mod test { use io::Cursor; - use hash_types::BlockHash; + use hash_types::BlockHash256; use hashes::hex::FromHex; use super::*; @@ -532,7 +532,7 @@ mod test { let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); for t in testdata.iter().skip(1) { - let block_hash = BlockHash::from_hex(&t.get(1).unwrap().as_str().unwrap()).unwrap(); + let block_hash = BlockHash256::from_hex(&t.get(1).unwrap().as_str().unwrap()).unwrap(); let block: Block = deserialize(&Vec::from_hex(&t.get(2).unwrap().as_str().unwrap()).unwrap()).unwrap(); assert_eq!(block.block_hash(), block_hash); let scripts = t.get(3).unwrap().as_array().unwrap(); From 03749c8da702115cafe10a1956aaff62705bcffa Mon Sep 17 00:00:00 2001 From: shotonoff Date: Fri, 31 Mar 2023 18:34:30 +0200 Subject: [PATCH 2/4] feat: replaces BlockHash256 on BlockHash --- src/blockdata/block.rs | 24 ++++++++---------------- src/blockdata/constants.rs | 5 ++--- src/blockdata/transaction/mod.rs | 6 +++--- src/consensus/encode.rs | 22 +++++++++++++++++----- src/hash_types.rs | 21 ++++++++++----------- src/network/message.rs | 2 +- src/network/message_blockdata.rs | 18 +++++++++--------- src/network/message_filter.rs | 14 +++++++------- src/network/message_network.rs | 7 +++---- src/util/bip158.rs | 12 ++++++------ src/util/hash.rs | 4 ++-- 11 files changed, 68 insertions(+), 67 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index f1f9738ad..aeb2f4211 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -27,18 +27,17 @@ use prelude::*; use core::fmt; -use ::{BlockHash, util}; +use ::{util, BlockHash, VarInt}; use util::Error::{BlockBadTarget, BlockBadProofOfWork}; use util::hash::dash_merkle_root; use hashes::{Hash, HashEngine}; -use hash_types::{Wtxid, BlockHash256, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; +use hash_types::{Wtxid, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; use util::uint::Uint256; use consensus::encode::Encodable; use network::constants::Network; use blockdata::transaction::Transaction; use blockdata::constants::{max_target, WITNESS_SCALE_FACTOR}; use blockdata::script; -use VarInt; /// A block header, which contains all the block's information except /// the actual transactions @@ -48,7 +47,7 @@ pub struct BlockHeader { /// The protocol version. Should always be 1. pub version: i32, /// Reference to the previous block in the chain. - pub prev_blockhash: BlockHash256, + pub prev_blockhash: BlockHash, /// The root hash of the merkle tree of transactions in the block. pub merkle_root: TxMerkleNode, /// The timestamp of the block, as claimed by the miner. @@ -64,14 +63,7 @@ impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time impl BlockHeader { /// Returns the block hash. - pub fn block_hash(&self) -> BlockHash256 { - let mut engine = BlockHash256::engine(); - self.consensus_encode(&mut engine).expect("engines don't error"); - BlockHash256::from_engine(engine) - } - - /// Returns the block hash. - pub fn block_hash_x11(&self) -> BlockHash { + pub fn block_hash(&self) -> BlockHash { let mut engine = BlockHash::engine(); self.consensus_encode(&mut engine).expect("engines don't error"); BlockHash::from_engine(engine) @@ -141,7 +133,7 @@ impl BlockHeader { } /// Checks that the proof-of-work for the block is valid, returning the block hash. - pub fn validate_pow(&self, required_target: &Uint256) -> Result { + pub fn validate_pow(&self, required_target: &Uint256) -> Result { let target = &self.target(); if target != required_target { return Err(BlockBadTarget); @@ -173,14 +165,14 @@ pub struct Block { /// The block header pub header: BlockHeader, /// List of transactions contained in the block - pub txdata: Vec + pub txdata: Vec, } impl_consensus_encoding!(Block, header, txdata); impl Block { /// Returns the block hash. - pub fn block_hash(&self) -> BlockHash256 { + pub fn block_hash(&self) -> BlockHash { self.header.block_hash() } @@ -211,7 +203,7 @@ impl Block { // Commitment is in the last output that starts with magic bytes. if let Some(pos) = coinbase.output.iter() - .rposition(|o| o.script_pubkey.len () >= 38 && o.script_pubkey[0..6] == MAGIC) + .rposition(|o| o.script_pubkey.len() >= 38 && o.script_pubkey[0..6] == MAGIC) { let commitment = WitnessCommitment::from_slice(&coinbase.output[pos].script_pubkey.as_bytes()[6..38]).unwrap(); // Witness reserved value is in coinbase input witness. diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 6f0982b55..c965c22df 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -27,7 +27,6 @@ use prelude::*; use core::default::Default; use hashes::hex::{self, HexIterator}; -use hashes::sha256d; use blockdata::opcodes; use blockdata::script; use blockdata::block::{Block, BlockHeader}; @@ -36,7 +35,7 @@ use blockdata::transaction::txin::TxIn; use blockdata::transaction::txout::TxOut; use blockdata::witness::Witness; use network::constants::Network; -use Transaction; +use ::{hash_x11, Transaction}; use util::uint::Uint256; /// The maximum allowable sequence number @@ -125,7 +124,7 @@ fn dash_genesis_tx() -> Transaction { /// Constructs and returns the genesis block pub fn genesis_block(network: Network) -> Block { let txdata = vec![dash_genesis_tx()]; - let hash: sha256d::Hash = txdata[0].txid().into(); + let hash: hash_x11::Hash = txdata[0].txid().into(); let merkle_root = hash.into(); match network { Network::Dash => { diff --git a/src/blockdata/transaction/mod.rs b/src/blockdata/transaction/mod.rs index a9a45fa5e..779e088b6 100644 --- a/src/blockdata/transaction/mod.rs +++ b/src/blockdata/transaction/mod.rs @@ -38,7 +38,7 @@ use ::{io}; use core::{default::Default}; use core::convert::TryFrom; -use hashes::{Hash, sha256d}; +use hashes::{Hash}; use util::{endian}; use blockdata::constants::WITNESS_SCALE_FACTOR; @@ -53,7 +53,7 @@ use hash_types::{Sighash, Txid, Wtxid}; use ::{VarInt}; use blockdata::transaction::hash_type::EcdsaSighashType; use blockdata::transaction::special_transaction::{TransactionPayload, TransactionType}; -use InputsHash; +use ::{hash_x11, InputsHash}; #[cfg(feature="bitcoinconsensus")] use OutPoint; #[cfg(doc)] @@ -117,7 +117,7 @@ impl Transaction { /// Computes a "normalized TXID" which does not include any signatures. /// This gives a way to identify a transaction that is "the same" as /// another in the sense of having same inputs and outputs. - pub fn ntxid(&self) -> sha256d::Hash { + pub fn ntxid(&self) -> hash_x11::Hash { let cloned_tx = Transaction { version: self.version, lock_time: self.lock_time, diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 507b74549..2bc9dafd3 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -36,7 +36,7 @@ use core::{fmt, mem, u32, convert::From}; #[cfg(feature = "std")] use std::error; use hashes::{sha256d, Hash, sha256, hash160}; -use hash_types::{BlockHash256, FilterHash, TxMerkleNode, FilterHeader}; +use hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; use io::{self, Cursor, Read}; @@ -49,7 +49,7 @@ use blockdata::transaction::{txout::TxOut, Transaction, txin::TxIn, outpoint::Ou use blockdata::transaction::special_transaction::TransactionType; #[cfg(feature = "std")] use network::{message_blockdata::Inventory, address::{Address, AddrV2Message}}; -use Script; +use ::{hash_x11, Script}; /// Encoding error #[derive(Debug)] @@ -608,7 +608,7 @@ macro_rules! impl_vec { } } } -impl_vec!(BlockHash256); +impl_vec!(BlockHash); impl_vec!(FilterHash); impl_vec!(FilterHeader); impl_vec!(TxMerkleNode); @@ -792,12 +792,24 @@ impl Decodable for sha256d::Hash { } } +impl Decodable for hash_x11::Hash { + fn consensus_decode(d: D) -> Result { + Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) + } +} + impl Encodable for sha256::Hash { fn consensus_encode(&self, s: S) -> Result { self.into_inner().consensus_encode(s) } } +impl Encodable for hash_x11::Hash { + fn consensus_encode(&self, s: S) -> Result { + self.into_inner().consensus_encode(s) + } +} + impl Decodable for sha256::Hash { fn consensus_decode(d: D) -> Result { Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) @@ -822,7 +834,7 @@ mod tests { use super::*; use core::{mem::{self, discriminant}, fmt}; use super::{deserialize, serialize, Error, CheckedData, VarInt}; - use super::{Transaction, BlockHash256, FilterHash, TxMerkleNode, TxOut, TxIn}; + use super::{Transaction, BlockHash, FilterHash, TxMerkleNode, TxOut, TxIn}; use consensus::{Encodable, deserialize_partial, Decodable}; use util::endian::{u64_to_array_le, u32_to_array_le, u16_to_array_le}; use secp256k1::rand::{thread_rng, Rng}; @@ -1027,7 +1039,7 @@ mod tests { assert_eq!(discriminant(&err), discriminant(&rand_io_err)); test_len_is_max_vec::(); - test_len_is_max_vec::(); + test_len_is_max_vec::(); test_len_is_max_vec::(); test_len_is_max_vec::(); test_len_is_max_vec::(); diff --git a/src/hash_types.rs b/src/hash_types.rs index 84242fc57..52af203f6 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -43,10 +43,9 @@ macro_rules! impl_hashencode { } } -hash_newtype!(Txid, sha256d::Hash, 32, doc="A dash transaction hash/transaction ID."); -hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A dash witness transaction ID."); +hash_newtype!(Txid, hash_x11::Hash, 32, doc="A dash transaction hash/transaction ID."); +hash_newtype!(Wtxid, hash_x11::Hash, 32, doc="A dash witness transaction ID."); hash_newtype!(BlockHash, hash_x11::Hash, 32, doc="A dash block hash."); -hash_newtype!(BlockHash256, sha256d::Hash, 32, doc="A dash block sha256 hash."); hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm"); hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key."); @@ -54,18 +53,18 @@ hash_newtype!(ScriptHash, hash160::Hash, 20, doc="A hash of Dash 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!(TxMerkleNode, sha256d::Hash, 32, doc="A hash of the Merkle tree branch or root for transactions"); -hash_newtype!(WitnessMerkleNode, sha256d::Hash, 32, doc="A hash corresponding to the Merkle tree root for witness data"); +hash_newtype!(TxMerkleNode, hash_x11::Hash, 32, doc="A hash of the Merkle tree branch or root for transactions"); +hash_newtype!(WitnessMerkleNode, hash_x11::Hash, 32, doc="A hash corresponding to the Merkle tree root for witness data"); hash_newtype!(WitnessCommitment, sha256d::Hash, 32, doc="A hash corresponding to the witness structure commitment in the coinbase transaction"); hash_newtype!(XpubIdentifier, hash160::Hash, 20, doc="XpubIdentifier as defined in BIP-32."); -hash_newtype!(FilterHash, sha256d::Hash, 32, doc="Filter hash, as defined in BIP-157"); -hash_newtype!(FilterHeader, sha256d::Hash, 32, doc="Filter header, as defined in BIP-157"); +hash_newtype!(FilterHash, hash_x11::Hash, 32, doc="Filter hash, as defined in BIP-157"); +hash_newtype!(FilterHeader, hash_x11::Hash, 32, doc="Filter header, as defined in BIP-157"); -hash_newtype!(MerkleRootMasternodeList, sha256d::Hash, 32, doc="The merkle root of the masternode list"); -hash_newtype!(MerkleRootQuorums, sha256d::Hash, 32, doc="The merkle root of the quorums"); +hash_newtype!(MerkleRootMasternodeList, hash_x11::Hash, 32, doc="The merkle root of the masternode list"); +hash_newtype!(MerkleRootQuorums, hash_x11::Hash, 32, doc="The merkle root of the quorums"); -hash_newtype!(SpecialTransactionPayloadHash, sha256d::Hash, 32, doc="A special transaction payload hash"); +hash_newtype!(SpecialTransactionPayloadHash, hash_x11::Hash, 32, doc="A special transaction payload hash"); hash_newtype!(InputsHash, sha256d::Hash, 32, doc="A hash of all transaction inputs"); hash_newtype!(QuorumHash, sha256d::Hash, 32, doc="A hash used to identify a quorum"); @@ -73,7 +72,7 @@ hash_newtype!(QuorumVVecHash, sha256d::Hash, 32, doc="A hash of a quorum verific impl_hashencode!(Txid); impl_hashencode!(Wtxid); -impl_hashencode!(BlockHash256); +impl_hashencode!(BlockHash); impl_hashencode!(Sighash); impl_hashencode!(PubkeyHash); diff --git a/src/network/message.rs b/src/network/message.rs index 3ce7db870..4801fc5f9 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -420,7 +420,7 @@ mod test { use network::constants::ServiceFlags; use consensus::encode::{deserialize, deserialize_partial, serialize}; use hashes::hex::FromHex; - use hashes::sha256d::Hash; + use hash_x11::Hash; use hashes::Hash as HashTrait; use network::address::{Address, AddrV2, AddrV2Message}; use super::message_network::{Reject, RejectReason, VersionMessage}; diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 2d9c56e23..940840c0d 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -29,7 +29,7 @@ use hashes::sha256d; use network::constants; use consensus::encode::{self, Decodable, Encodable}; -use hash_types::{BlockHash256, Txid, Wtxid}; +use hash_types::{BlockHash, Txid, Wtxid}; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] @@ -39,13 +39,13 @@ pub enum Inventory { /// Transaction Transaction(Txid), /// Block - Block(BlockHash256), + Block(BlockHash), /// Witness Transaction by Wtxid WTx(Wtxid), /// Witness Transaction WitnessTransaction(Txid), /// Witness Block - WitnessBlock(BlockHash256), + WitnessBlock(BlockHash), /// Unknown inventory type Unknown { /// The inventory item type. @@ -104,9 +104,9 @@ pub struct GetBlocksMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the block to stop at, or zero to just fetch the maximum 500 blocks - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, } /// The `getheaders` message @@ -117,14 +117,14 @@ pub struct GetHeadersMessage { /// Locator hashes --- ordered newest to oldest. The remote peer will /// reply with its longest known chain, starting from a locator hash /// if possible and block 1 otherwise. - pub locator_hashes: Vec, + pub locator_hashes: Vec, /// References the header to stop at, or zero to just fetch the maximum 2000 headers - pub stop_hash: BlockHash256 + pub stop_hash: BlockHash } impl GetBlocksMessage { /// Construct a new `getblocks` message - pub fn new(locator_hashes: Vec, stop_hash: BlockHash256) -> GetBlocksMessage { + pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetBlocksMessage { GetBlocksMessage { version: constants::PROTOCOL_VERSION, locator_hashes, @@ -137,7 +137,7 @@ impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash); impl GetHeadersMessage { /// Construct a new `getheaders` message - pub fn new(locator_hashes: Vec, stop_hash: BlockHash256) -> GetHeadersMessage { + pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetHeadersMessage { GetHeadersMessage { version: constants::PROTOCOL_VERSION, locator_hashes, diff --git a/src/network/message_filter.rs b/src/network/message_filter.rs index 7a6265802..29f8adb2e 100644 --- a/src/network/message_filter.rs +++ b/src/network/message_filter.rs @@ -3,7 +3,7 @@ //! This module describes BIP157 Client Side Block Filtering network messages. //! -use hash_types::{BlockHash256, FilterHash, FilterHeader}; +use hash_types::{BlockHash, FilterHash, FilterHeader}; /// getcfilters message #[derive(PartialEq, Eq, Clone, Debug)] @@ -13,7 +13,7 @@ pub struct GetCFilters { /// The height of the first block in the requested range pub start_height: u32, /// The hash of the last block in the requested range - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, } impl_consensus_encoding!(GetCFilters, filter_type, start_height, stop_hash); @@ -23,7 +23,7 @@ pub struct CFilter { /// Byte identifying the type of filter being returned pub filter_type: u8, /// Block hash of the Bitcoin block for which the filter is being returned - pub block_hash: BlockHash256, + pub block_hash: BlockHash, /// The serialized compact filter for this block pub filter: Vec, } @@ -37,7 +37,7 @@ pub struct GetCFHeaders { /// The height of the first block in the requested range pub start_height: u32, /// The hash of the last block in the requested range - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, } impl_consensus_encoding!(GetCFHeaders, filter_type, start_height, stop_hash); @@ -47,7 +47,7 @@ pub struct CFHeaders { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, /// The filter header preceding the first block in the requested range pub previous_filter_header: FilterHeader, /// The filter hashes for each block in the requested range @@ -61,7 +61,7 @@ pub struct GetCFCheckpt { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, } impl_consensus_encoding!(GetCFCheckpt, filter_type, stop_hash); @@ -71,7 +71,7 @@ pub struct CFCheckpt { /// Filter type for which headers are requested pub filter_type: u8, /// The hash of the last block in the requested range - pub stop_hash: BlockHash256, + pub stop_hash: BlockHash, /// The filter headers at intervals of 1,000 pub filter_headers: Vec, } diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 2f2c97465..d81134589 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -23,13 +23,12 @@ use prelude::*; -use io; +use ::{hash_x11, io}; use network::address::Address; use network::constants::{self, ServiceFlags}; use consensus::{Encodable, Decodable, ReadExt}; use consensus::encode; -use hashes::sha256d; /// Some simple messages @@ -141,7 +140,7 @@ pub struct Reject { /// reason of rejectection pub reason: Cow<'static, str>, /// reference to rejected item - pub hash: sha256d::Hash + pub hash: hash_x11::Hash } impl_consensus_encoding!(Reject, message, ccode, reason, hash); @@ -153,7 +152,7 @@ mod tests { use super::RejectReason; use hashes::hex::FromHex; - use hashes::sha256d::Hash; + use hash_x11::Hash; use network::constants::ServiceFlags; use consensus::encode::{deserialize, serialize}; diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 9dc9b37a2..1705a1531 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -52,7 +52,7 @@ use core::fmt::{self, Display, Formatter}; use core::cmp::{self, Ordering}; use hashes::{Hash, siphash24}; -use hash_types::{BlockHash256, FilterHash, FilterHeader}; +use hash_types::{BlockHash, FilterHash, FilterHeader}; use blockdata::block::Block; use blockdata::script::Script; @@ -137,13 +137,13 @@ impl BlockFilter { } /// match any query pattern - pub fn match_any(&self, block_hash: &BlockHash256, query: &mut dyn Iterator) -> Result { + pub fn match_any(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_any(&mut Cursor::new(self.content.as_slice()), query) } /// match all query pattern - pub fn match_all(&self, block_hash: &BlockHash256, query: &mut dyn Iterator) -> Result { + pub fn match_all(&self, block_hash: &BlockHash, query: &mut dyn Iterator) -> Result { let filter_reader = BlockFilterReader::new(block_hash); filter_reader.match_all(&mut Cursor::new(self.content.as_slice()), query) } @@ -210,7 +210,7 @@ pub struct BlockFilterReader { impl BlockFilterReader { /// Create a block filter reader - pub fn new(block_hash: &BlockHash256) -> BlockFilterReader { + pub fn new(block_hash: &BlockHash) -> BlockFilterReader { let block_hash_as_int = block_hash.into_inner(); 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]); @@ -513,7 +513,7 @@ impl<'a> BitStreamWriter<'a> { mod test { use io::Cursor; - use hash_types::BlockHash256; + use hash_types::BlockHash; use hashes::hex::FromHex; use super::*; @@ -532,7 +532,7 @@ mod test { let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); for t in testdata.iter().skip(1) { - let block_hash = BlockHash256::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(&Vec::from_hex(&t.get(2).unwrap().as_str().unwrap()).unwrap()).unwrap(); assert_eq!(block.block_hash(), block_hash); let scripts = t.get(3).unwrap().as_array().unwrap(); diff --git a/src/util/hash.rs b/src/util/hash.rs index 27915797b..a6587cbb1 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -114,9 +114,9 @@ where #[cfg(test)] mod tests { use consensus::encode::deserialize; - use hashes::sha256d; use blockdata::block::Block; + use hash_x11; use super::*; #[test] @@ -128,7 +128,7 @@ mod tests { let hashes_iter = block.txdata.iter().map(|obj| obj.txid().as_hash()); - let mut hashes_array: [sha256d::Hash; 15] = [Default::default(); 15]; + let mut hashes_array: [hash_x11::Hash; 15] = [Default::default(); 15]; for (i, hash) in hashes_iter.clone().enumerate() { hashes_array[i] = hash; } From 9f51f6e8aa7cf9e433c10c6ec57902aeb233ec9b Mon Sep 17 00:00:00 2001 From: shotonoff Date: Mon, 3 Apr 2023 13:52:50 +0200 Subject: [PATCH 3/4] chore: remove unused import --- src/hash_x11.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hash_x11.rs b/src/hash_x11.rs index 54bb32255..7ab5a9962 100644 --- a/src/hash_x11.rs +++ b/src/hash_x11.rs @@ -2,7 +2,6 @@ use core::{str}; use std::io; use hashes::Error; use hashes::{Hash as HashTrait, HashEngine as EngineTrait, hex}; -use ::{BlockHeader}; use consensus; hex_fmt_impl!(Display, Hash); From 4db940f117fe711abeae43bd7b5e9b2714a3eb11 Mon Sep 17 00:00:00 2001 From: shotonoff Date: Mon, 3 Apr 2023 14:33:14 +0200 Subject: [PATCH 4/4] chore: update --- src/hash_x11.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/hash_x11.rs b/src/hash_x11.rs index 7ab5a9962..02fc18067 100644 --- a/src/hash_x11.rs +++ b/src/hash_x11.rs @@ -1,8 +1,27 @@ +// Rust Dash Library +// Originally written in 2014 by +// Andrew Poelstra +// For Bitcoin +// Updated for Dash in 2022 by +// The Dash Core Developers +// +// 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 . +// + +//! An implementation of a hash engine to support the X1 hash, +//! which is a wrapper around the rs-x11-hash library. + use core::{str}; use std::io; use hashes::Error; use hashes::{Hash as HashTrait, HashEngine as EngineTrait, hex}; -use consensus; hex_fmt_impl!(Display, Hash); hex_fmt_impl!(LowerHex, Hash); @@ -10,6 +29,7 @@ index_impl!(Hash); serde_impl!(Hash, 32); borrow_slice_impl!(Hash); +/// Output of the X11 hash function #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash, Debug)] #[repr(transparent)] pub struct Hash( @@ -28,7 +48,6 @@ impl HashTrait for Hash { type Inner = [u8; 32]; fn from_engine(e: Self::Engine) -> Self { - println!("from_engine"); Hash(e.midstate().into_inner()) } @@ -57,9 +76,9 @@ impl HashTrait for Hash { } } +/// A hashing engine of X11 algorithm, which bytes can be serialized into #[derive(Default, Clone)] pub struct HashEngine { - // h: [u8; 32], buf: Vec, length: usize, } @@ -68,7 +87,6 @@ impl EngineTrait for HashEngine { type MidState = Midstate; fn midstate(&self) -> Self::MidState { - println!("midstate"); let md: Vec = rs_x11_hash::get_x11_hash(self.buf.as_slice()); let mut h: [u8; 32] = [0; 32]; for n in 0..32 { @@ -89,6 +107,7 @@ impl EngineTrait for HashEngine { } } +/// Output of the X11 hash function #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] pub struct Midstate(pub [u8; 32]);