Просмотр исходного кода

blockchain: major hashes cleanup

skoupidi 2 лет назад
Родитель
Сommit
930a511309

+ 3 - 3
bin/darkfid/src/proto/protocol_sync.rs

@@ -23,7 +23,7 @@ use log::{debug, error};
 use smol::Executor;
 use smol::Executor;
 
 
 use darkfi::{
 use darkfi::{
-    blockchain::BlockInfo,
+    blockchain::{BlockInfo, HeaderHash},
     impl_p2p_message,
     impl_p2p_message,
     net::{
     net::{
         ChannelPtr, Message, MessageSubscription, ProtocolBase, ProtocolBasePtr,
         ChannelPtr, Message, MessageSubscription, ProtocolBase, ProtocolBasePtr,
@@ -74,9 +74,9 @@ impl_p2p_message!(SyncResponse, "syncresponse");
 #[derive(Debug, SerialEncodable, SerialDecodable)]
 #[derive(Debug, SerialEncodable, SerialDecodable)]
 pub struct ForkSyncRequest {
 pub struct ForkSyncRequest {
     /// Canonical(finalized) tip block hash
     /// Canonical(finalized) tip block hash
-    pub tip: blake3::Hash,
+    pub tip: HeaderHash,
     /// Optional fork tip block hash
     /// Optional fork tip block hash
-    pub fork_tip: Option<blake3::Hash>,
+    pub fork_tip: Option<HeaderHash>,
 }
 }
 
 
 impl_p2p_message!(ForkSyncRequest, "forksyncrequest");
 impl_p2p_message!(ForkSyncRequest, "forksyncrequest");

+ 1 - 1
bin/darkfid/src/rpc_blockchain.rs

@@ -274,7 +274,7 @@ impl Darkfid {
         JsonResponse::new(
         JsonResponse::new(
             JsonValue::Object(HashMap::from([(
             JsonValue::Object(HashMap::from([(
                 "chain_id".to_string(),
                 "chain_id".to_string(),
-                chain_id.to_hex().to_string().into(),
+                chain_id.as_string().into(),
             )])),
             )])),
             id,
             id,
         )
         )

+ 2 - 2
bin/darkfid/src/task/miner.rs

@@ -228,13 +228,13 @@ async fn mine_next_block(
     next_block.header.nonce = *response.get::<f64>().unwrap() as u64;
     next_block.header.nonce = *response.get::<f64>().unwrap() as u64;
 
 
     // Sign the mined block
     // Sign the mined block
-    next_block.sign(secret)?;
+    next_block.sign(secret);
 
 
     // Verify it
     // Verify it
     extended_fork.module.verify_current_block(&next_block)?;
     extended_fork.module.verify_current_block(&next_block)?;
 
 
     // Append the mined block as a proposal
     // Append the mined block as a proposal
-    let proposal = Proposal::new(next_block)?;
+    let proposal = Proposal::new(next_block);
     node.validator.append_proposal(&proposal).await?;
     node.validator.append_proposal(&proposal).await?;
 
 
     // Broadcast proposal to the network
     // Broadcast proposal to the network

+ 2 - 2
bin/darkfid/src/task/sync.rs

@@ -88,7 +88,7 @@ pub async fn sync_task(node: &Darkfid) -> Result<()> {
     // and loops until the response is the same block (used to utilize
     // and loops until the response is the same block (used to utilize
     // batch requests).
     // batch requests).
     let mut last = node.validator.blockchain.last()?;
     let mut last = node.validator.blockchain.last()?;
-    info!(target: "darkfid::task::sync_task", "Last known block: {:?} - {:?}", last.0, last.1);
+    info!(target: "darkfid::task::sync_task", "Last known block: {} - {}", last.0, last.1);
     loop {
     loop {
         // Node creates a `SyncRequest` and sends it
         // Node creates a `SyncRequest` and sends it
         let request = SyncRequest { height: last.0 };
         let request = SyncRequest { height: last.0 };
@@ -109,7 +109,7 @@ pub async fn sync_task(node: &Darkfid) -> Result<()> {
         }
         }
 
 
         let last_received = node.validator.blockchain.last()?;
         let last_received = node.validator.blockchain.last()?;
-        info!(target: "darkfid::task::sync_task", "Last received block: {:?} - {:?}", last_received.0, last_received.1);
+        info!(target: "darkfid::task::sync_task", "Last received block: {} - {}", last_received.0, last_received.1);
 
 
         if last == last_received {
         if last == last_received {
             break
             break

+ 4 - 4
bin/darkfid/src/tests/forks.rs

@@ -17,7 +17,7 @@
  */
  */
 
 
 use darkfi::{
 use darkfi::{
-    blockchain::{BlockInfo, Blockchain},
+    blockchain::{BlockInfo, Blockchain, HeaderHash},
     validator::{consensus::Fork, pow::PoWModule},
     validator::{consensus::Fork, pow::PoWModule},
     Result,
     Result,
 };
 };
@@ -26,8 +26,8 @@ use darkfi::{
 fn forks() -> Result<()> {
 fn forks() -> Result<()> {
     smol::block_on(async {
     smol::block_on(async {
         // Dummy records we will insert
         // Dummy records we will insert
-        let record1 = blake3::hash(b"Let there be dark!");
-        let record2 = blake3::hash(b"Never skip brain day.");
+        let record1 = HeaderHash::new(blake3::hash(b"Let there be dark!").into());
+        let record2 = HeaderHash::new(blake3::hash(b"Never skip brain day.").into());
 
 
         // Create a temporary blockchain and a PoW module
         // Create a temporary blockchain and a PoW module
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
@@ -36,7 +36,7 @@ fn forks() -> Result<()> {
         // Generate and insert default genesis block
         // Generate and insert default genesis block
         let genesis_block = BlockInfo::default();
         let genesis_block = BlockInfo::default();
         blockchain.add_block(&genesis_block)?;
         blockchain.add_block(&genesis_block)?;
-        let genesis_block_hash = genesis_block.hash()?;
+        let genesis_block_hash = genesis_block.hash();
 
 
         // Create a fork
         // Create a fork
         let fork = Fork::new(blockchain.clone(), module).await?;
         let fork = Fork::new(blockchain.clone(), module).await?;

+ 3 - 3
bin/darkfid/src/tests/harness.rs

@@ -143,7 +143,7 @@ impl Harness {
         // We append the block as a proposal to Alice,
         // We append the block as a proposal to Alice,
         // and then we broadcast it to rest nodes
         // and then we broadcast it to rest nodes
         for block in blocks {
         for block in blocks {
-            let proposal = Proposal::new(block.clone())?;
+            let proposal = Proposal::new(block.clone());
             self.alice.validator.append_proposal(&proposal).await?;
             self.alice.validator.append_proposal(&proposal).await?;
             let message = ProposalMessage(proposal);
             let message = ProposalMessage(proposal);
             self.alice.p2p.broadcast(&message).await;
             self.alice.p2p.broadcast(&message).await;
@@ -203,7 +203,7 @@ impl Harness {
         let timestamp = previous.header.timestamp.checked_add(1.into())?;
         let timestamp = previous.header.timestamp.checked_add(1.into())?;
 
 
         // Generate header
         // Generate header
-        let header = Header::new(previous.hash()?, block_height, timestamp, last_nonce);
+        let header = Header::new(previous.hash(), block_height, timestamp, last_nonce);
 
 
         // Generate the block
         // Generate the block
         let mut block = BlockInfo::new_empty(header);
         let mut block = BlockInfo::new_empty(header);
@@ -212,7 +212,7 @@ impl Harness {
         block.append_txs(vec![tx]);
         block.append_txs(vec![tx]);
 
 
         // Attach signature
         // Attach signature
-        block.sign(&keypair.secret)?;
+        block.sign(&keypair.secret);
 
 
         Ok(block)
         Ok(block)
     }
     }

+ 2 - 2
bin/darkfid/src/tests/mod.rs

@@ -148,12 +148,12 @@ async fn sync_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     th.validate_chains(4 + (fork_sequence.len() - 2)).await?;
     th.validate_chains(4 + (fork_sequence.len() - 2)).await?;
     let bob = &th.bob.validator;
     let bob = &th.bob.validator;
     let last = alice.blockchain.last()?.1;
     let last = alice.blockchain.last()?.1;
-    assert_eq!(last, fork_sequence[fork_sequence.len() - 3].hash()?);
+    assert_eq!(last, fork_sequence[fork_sequence.len() - 3].hash());
     assert_eq!(last, bob.blockchain.last()?.1);
     assert_eq!(last, bob.blockchain.last()?.1);
     // Nodes must have one fork with 2 blocks
     // Nodes must have one fork with 2 blocks
     th.validate_fork_chains(1, vec![2]).await;
     th.validate_fork_chains(1, vec![2]).await;
     let last_proposal = alice.consensus.forks.read().await[0].proposals[1];
     let last_proposal = alice.consensus.forks.read().await[0].proposals[1];
-    assert_eq!(last_proposal, fork_sequence.last().unwrap().hash()?);
+    assert_eq!(last_proposal, fork_sequence.last().unwrap().hash());
     assert_eq!(last_proposal, bob.consensus.forks.read().await[0].proposals[1]);
     assert_eq!(last_proposal, bob.consensus.forks.read().await[0].proposals[1]);
 
 
     // Same for Charlie
     // Same for Charlie

+ 1 - 3
bin/minerd/src/error.rs

@@ -27,8 +27,7 @@ pub enum RpcError {
 
 
     // Miner errors
     // Miner errors
     MiningFailed = -32201,
     MiningFailed = -32201,
-    HashingFailed = -32202,
-    StopFailed = -32203,
+    StopFailed = -32202,
 }
 }
 
 
 fn to_tuple(e: RpcError) -> (i32, String) {
 fn to_tuple(e: RpcError) -> (i32, String) {
@@ -38,7 +37,6 @@ fn to_tuple(e: RpcError) -> (i32, String) {
         RpcError::BlockParseError => "Block parse error",
         RpcError::BlockParseError => "Block parse error",
         // Miner errors
         // Miner errors
         RpcError::MiningFailed => "Mining block failed",
         RpcError::MiningFailed => "Mining block failed",
-        RpcError::HashingFailed => "Hashing block failed",
         RpcError::StopFailed => "Failed to stop previous request",
         RpcError::StopFailed => "Failed to stop previous request",
     };
     };
 
 

+ 1 - 4
bin/minerd/src/rpc.rs

@@ -108,10 +108,7 @@ impl Minerd {
         };
         };
 
 
         // Mine provided block
         // Mine provided block
-        let Ok(block_hash) = block.hash() else {
-            error!(target: "minerd::rpc", "Failed to hash block");
-            return server_error(RpcError::HashingFailed, id, None)
-        };
+        let block_hash = block.hash();
         info!(target: "minerd::rpc", "Mining block {} for target: {}", block_hash, target);
         info!(target: "minerd::rpc", "Mining block {} for target: {}", block_hash, target);
         if let Err(e) = mine_block(&target, &mut block, self.threads, &self.stop_signal.clone()) {
         if let Err(e) = mine_block(&target, &mut block, self.threads, &self.stop_signal.clone()) {
             error!(target: "minerd::rpc", "Failed mining block {} with error: {}", block_hash, e);
             error!(target: "minerd::rpc", "Failed mining block {} with error: {}", block_hash, e);

+ 30 - 17
script/research/blockchain-explorer/src/main.rs

@@ -23,7 +23,7 @@ use darkfi::{
     blockchain::{
     blockchain::{
         block_store::{Block, BlockDifficulty, BlockRanks, BlockStore},
         block_store::{Block, BlockDifficulty, BlockRanks, BlockStore},
         contract_store::ContractStore,
         contract_store::ContractStore,
-        header_store::{Header, HeaderStore},
+        header_store::{Header, HeaderHash, HeaderStore},
         tx_store::TxStore,
         tx_store::TxStore,
         Blockchain,
         Blockchain,
     },
     },
@@ -35,6 +35,7 @@ use darkfi::{
 use darkfi_sdk::{
 use darkfi_sdk::{
     blockchain::block_epoch,
     blockchain::block_epoch,
     crypto::{ContractId, MerkleTree},
     crypto::{ContractId, MerkleTree},
+    tx::TransactionHash,
 };
 };
 use num_bigint::BigUint;
 use num_bigint::BigUint;
 
 
@@ -60,9 +61,9 @@ struct Args {
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct HeaderInfo {
 struct HeaderInfo {
-    _hash: blake3::Hash,
+    _hash: HeaderHash,
     _version: u8,
     _version: u8,
-    _previous: blake3::Hash,
+    _previous: HeaderHash,
     _height: u64,
     _height: u64,
     _timestamp: Timestamp,
     _timestamp: Timestamp,
     _nonce: u64,
     _nonce: u64,
@@ -70,7 +71,7 @@ struct HeaderInfo {
 }
 }
 
 
 impl HeaderInfo {
 impl HeaderInfo {
-    pub fn new(_hash: blake3::Hash, header: &Header) -> HeaderInfo {
+    pub fn new(_hash: HeaderHash, header: &Header) -> HeaderInfo {
         HeaderInfo {
         HeaderInfo {
             _hash,
             _hash,
             _version: header.version,
             _version: header.version,
@@ -106,14 +107,14 @@ impl HeaderStoreInfo {
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct BlockInfo {
 struct BlockInfo {
-    _hash: blake3::Hash,
-    _header: blake3::Hash,
-    _txs: Vec<blake3::Hash>,
+    _hash: HeaderHash,
+    _header: HeaderHash,
+    _txs: Vec<TransactionHash>,
     _signature: String,
     _signature: String,
 }
 }
 
 
 impl BlockInfo {
 impl BlockInfo {
-    pub fn new(_hash: blake3::Hash, block: &Block) -> BlockInfo {
+    pub fn new(_hash: HeaderHash, block: &Block) -> BlockInfo {
         BlockInfo {
         BlockInfo {
             _hash,
             _hash,
             _header: block.header,
             _header: block.header,
@@ -126,11 +127,11 @@ impl BlockInfo {
 #[derive(Debug)]
 #[derive(Debug)]
 struct OrderInfo {
 struct OrderInfo {
     _height: u64,
     _height: u64,
-    _hash: blake3::Hash,
+    _hash: HeaderHash,
 }
 }
 
 
 impl OrderInfo {
 impl OrderInfo {
-    pub fn new(_height: u64, _hash: blake3::Hash) -> OrderInfo {
+    pub fn new(_height: u64, _hash: HeaderHash) -> OrderInfo {
         OrderInfo { _height, _hash }
         OrderInfo { _height, _hash }
     }
     }
 }
 }
@@ -220,35 +221,47 @@ impl BlockStoreInfo {
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct TxInfo {
 struct TxInfo {
-    _hash: blake3::Hash,
+    _hash: TransactionHash,
     _payload: Transaction,
     _payload: Transaction,
 }
 }
 
 
 impl TxInfo {
 impl TxInfo {
-    pub fn new(_hash: blake3::Hash, tx: &Transaction) -> TxInfo {
+    pub fn new(_hash: TransactionHash, tx: &Transaction) -> TxInfo {
         TxInfo { _hash, _payload: tx.clone() }
         TxInfo { _hash, _payload: tx.clone() }
     }
     }
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct TxLocationInfo {
 struct TxLocationInfo {
-    _hash: blake3::Hash,
+    _hash: TransactionHash,
     _block_height: u64,
     _block_height: u64,
     _index: u64,
     _index: u64,
 }
 }
 
 
 impl TxLocationInfo {
 impl TxLocationInfo {
-    pub fn new(_hash: blake3::Hash, _block_height: u64, _index: u64) -> TxLocationInfo {
+    pub fn new(_hash: TransactionHash, _block_height: u64, _index: u64) -> TxLocationInfo {
         TxLocationInfo { _hash, _block_height, _index }
         TxLocationInfo { _hash, _block_height, _index }
     }
     }
 }
 }
 
 
+#[derive(Debug)]
+struct PendingOrderInfo {
+    _order: u64,
+    _hash: TransactionHash,
+}
+
+impl PendingOrderInfo {
+    pub fn new(_order: u64, _hash: TransactionHash) -> PendingOrderInfo {
+        PendingOrderInfo { _order, _hash }
+    }
+}
+
 #[derive(Debug)]
 #[derive(Debug)]
 struct TxStoreInfo {
 struct TxStoreInfo {
     _main: Vec<TxInfo>,
     _main: Vec<TxInfo>,
     _location: Vec<TxLocationInfo>,
     _location: Vec<TxLocationInfo>,
     _pending: Vec<TxInfo>,
     _pending: Vec<TxInfo>,
-    _pending_order: Vec<OrderInfo>,
+    _pending_order: Vec<PendingOrderInfo>,
 }
 }
 
 
 impl TxStoreInfo {
 impl TxStoreInfo {
@@ -287,8 +300,8 @@ impl TxStoreInfo {
         let result = txstore.get_all_pending_order();
         let result = txstore.get_all_pending_order();
         match result {
         match result {
             Ok(iter) => {
             Ok(iter) => {
-                for (height, hash) in iter.iter() {
-                    _pending_order.push(OrderInfo::new(*height, *hash));
+                for (order, hash) in iter.iter() {
+                    _pending_order.push(PendingOrderInfo::new(*order, *hash));
                 }
                 }
             }
             }
             Err(e) => println!("Error: {:?}", e),
             Err(e) => println!("Error: {:?}", e),

+ 45 - 60
src/blockchain/block_store.rs

@@ -32,7 +32,7 @@ use num_bigint::BigUint;
 
 
 use crate::{tx::Transaction, util::time::Timestamp, Error, Result};
 use crate::{tx::Transaction, util::time::Timestamp, Error, Result};
 
 
-use super::{parse_record, parse_u64_key_record, Header, SledDbOverlayPtr};
+use super::{parse_record, parse_u64_key_record, Header, HeaderHash, SledDbOverlayPtr};
 
 
 /// This struct represents a tuple of the form (`header`, `txs`, `signature`).
 /// This struct represents a tuple of the form (`header`, `txs`, `signature`).
 /// The header and transactions are stored as hashes, serving as pointers to the actual data
 /// The header and transactions are stored as hashes, serving as pointers to the actual data
@@ -41,7 +41,7 @@ use super::{parse_record, parse_u64_key_record, Header, SledDbOverlayPtr};
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct Block {
 pub struct Block {
     /// Block header
     /// Block header
-    pub header: blake3::Hash,
+    pub header: HeaderHash,
     /// Trasaction hashes
     /// Trasaction hashes
     pub txs: Vec<TransactionHash>,
     pub txs: Vec<TransactionHash>,
     /// Block producer signature
     /// Block producer signature
@@ -49,21 +49,21 @@ pub struct Block {
 }
 }
 
 
 impl Block {
 impl Block {
-    pub fn new(header: blake3::Hash, txs: Vec<TransactionHash>, signature: Signature) -> Self {
+    pub fn new(header: HeaderHash, txs: Vec<TransactionHash>, signature: Signature) -> Self {
         Self { header, txs, signature }
         Self { header, txs, signature }
     }
     }
 
 
     /// A block's hash is the same as the hash of its header
     /// A block's hash is the same as the hash of its header
-    pub fn hash(&self) -> blake3::Hash {
+    pub fn hash(&self) -> HeaderHash {
         self.header
         self.header
     }
     }
 
 
     /// Generate a `Block` from a `BlockInfo`
     /// Generate a `Block` from a `BlockInfo`
-    pub fn from_block_info(block_info: &BlockInfo) -> Result<Self> {
-        let header = block_info.header.hash()?;
+    pub fn from_block_info(block_info: &BlockInfo) -> Self {
+        let header = block_info.header.hash();
         let txs = block_info.txs.iter().map(|tx| tx.hash()).collect();
         let txs = block_info.txs.iter().map(|tx| tx.hash()).collect();
         let signature = block_info.signature;
         let signature = block_info.signature;
-        Ok(Self { header, txs, signature })
+        Self { header, txs, signature }
     }
     }
 }
 }
 
 
@@ -106,7 +106,7 @@ impl BlockInfo {
     }
     }
 
 
     /// A block's hash is the same as the hash of its header
     /// A block's hash is the same as the hash of its header
-    pub fn hash(&self) -> Result<blake3::Hash> {
+    pub fn hash(&self) -> HeaderHash {
         self.header.hash()
         self.header.hash()
     }
     }
 
 
@@ -126,10 +126,8 @@ impl BlockInfo {
 
 
     /// Sign block header using provided secret key
     /// Sign block header using provided secret key
     // TODO: sign more stuff?
     // TODO: sign more stuff?
-    pub fn sign(&mut self, secret_key: &SecretKey) -> Result<()> {
-        self.signature = secret_key.sign(&self.hash()?.as_bytes()[..]);
-
-        Ok(())
+    pub fn sign(&mut self, secret_key: &SecretKey) {
+        self.signature = secret_key.sign(self.hash().inner());
     }
     }
 }
 }
 
 
@@ -139,7 +137,7 @@ pub struct BlockOrder {
     /// Order number
     /// Order number
     pub number: u64,
     pub number: u64,
     /// Block headerhash of that number
     /// Block headerhash of that number
-    pub block: blake3::Hash,
+    pub block: HeaderHash,
 }
 }
 
 
 /// Auxiliary structure used to keep track of block ranking information.
 /// Auxiliary structure used to keep track of block ranking information.
@@ -297,16 +295,16 @@ impl BlockStore {
     }
     }
 
 
     /// Insert a slice of [`Block`] into the store's main tree.
     /// Insert a slice of [`Block`] into the store's main tree.
-    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<blake3::Hash>> {
-        let (batch, ret) = self.insert_batch(blocks)?;
+    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<HeaderHash>> {
+        let (batch, ret) = self.insert_batch(blocks);
         self.main.apply_batch(batch)?;
         self.main.apply_batch(batch)?;
         Ok(ret)
         Ok(ret)
     }
     }
 
 
     /// Insert a slice of `u64` and block hashes into the store's
     /// Insert a slice of `u64` and block hashes into the store's
     /// order tree.
     /// order tree.
-    pub fn insert_order(&self, order: &[u64], hashes: &[blake3::Hash]) -> Result<()> {
-        let batch = self.insert_batch_order(order, hashes)?;
+    pub fn insert_order(&self, order: &[u64], hashes: &[HeaderHash]) -> Result<()> {
+        let batch = self.insert_batch_order(order, hashes);
         self.order.apply_batch(batch)?;
         self.order.apply_batch(batch)?;
         Ok(())
         Ok(())
     }
     }
@@ -314,7 +312,7 @@ impl BlockStore {
     /// Insert a slice of [`BlockDifficulty`] into the store's
     /// Insert a slice of [`BlockDifficulty`] into the store's
     /// difficulty tree.
     /// difficulty tree.
     pub fn insert_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> Result<()> {
     pub fn insert_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> Result<()> {
-        let batch = self.insert_batch_difficulty(block_difficulties)?;
+        let batch = self.insert_batch_difficulty(block_difficulties);
         self.difficulty.apply_batch(batch)?;
         self.difficulty.apply_batch(batch)?;
         Ok(())
         Ok(())
     }
     }
@@ -324,60 +322,49 @@ impl BlockStore {
     /// The block's hash() function output is used as the key,
     /// The block's hash() function output is used as the key,
     /// while value is the serialized [`Block`] itself.
     /// while value is the serialized [`Block`] itself.
     /// On success, the function returns the block hashes in the same order.
     /// On success, the function returns the block hashes in the same order.
-    pub fn insert_batch(&self, blocks: &[Block]) -> Result<(sled::Batch, Vec<blake3::Hash>)> {
+    pub fn insert_batch(&self, blocks: &[Block]) -> (sled::Batch, Vec<HeaderHash>) {
         let mut ret = Vec::with_capacity(blocks.len());
         let mut ret = Vec::with_capacity(blocks.len());
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
         for block in blocks {
         for block in blocks {
             let blockhash = block.hash();
             let blockhash = block.hash();
-            batch.insert(blockhash.as_bytes(), serialize(block));
+            batch.insert(blockhash.inner(), serialize(block));
             ret.push(blockhash);
             ret.push(blockhash);
         }
         }
 
 
-        Ok((batch, ret))
+        (batch, ret)
     }
     }
 
 
     /// Generate the sled batch corresponding to an insert to the order
     /// Generate the sled batch corresponding to an insert to the order
     /// tree, so caller can handle the write operation.
     /// tree, so caller can handle the write operation.
     /// The block order number is used as the key, and the block hash is used as value.
     /// The block order number is used as the key, and the block hash is used as value.
-    pub fn insert_batch_order(
-        &self,
-        order: &[u64],
-        hashes: &[blake3::Hash],
-    ) -> Result<sled::Batch> {
-        if order.len() != hashes.len() {
-            return Err(Error::InvalidInputLengths)
-        }
-
+    pub fn insert_batch_order(&self, order: &[u64], hashes: &[HeaderHash]) -> sled::Batch {
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
         for (i, number) in order.iter().enumerate() {
         for (i, number) in order.iter().enumerate() {
-            batch.insert(&number.to_be_bytes(), hashes[i].as_bytes());
+            batch.insert(&number.to_be_bytes(), hashes[i].inner());
         }
         }
 
 
-        Ok(batch)
+        batch
     }
     }
 
 
     /// Generate the sled batch corresponding to an insert to the difficulty
     /// Generate the sled batch corresponding to an insert to the difficulty
     /// tree, so caller can handle the write operation.
     /// tree, so caller can handle the write operation.
     /// The block's height number is used as the key, while value is
     /// The block's height number is used as the key, while value is
     //  the serialized [`BlockDifficulty`] itself.
     //  the serialized [`BlockDifficulty`] itself.
-    pub fn insert_batch_difficulty(
-        &self,
-        block_difficulties: &[BlockDifficulty],
-    ) -> Result<sled::Batch> {
+    pub fn insert_batch_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> sled::Batch {
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
         for block_difficulty in block_difficulties {
         for block_difficulty in block_difficulties {
             batch.insert(&block_difficulty.height.to_be_bytes(), serialize(block_difficulty));
             batch.insert(&block_difficulty.height.to_be_bytes(), serialize(block_difficulty));
         }
         }
 
 
-        Ok(batch)
+        batch
     }
     }
 
 
     /// Check if the store's main tree contains a given block hash.
     /// Check if the store's main tree contains a given block hash.
-    pub fn contains(&self, blockhash: &blake3::Hash) -> Result<bool> {
-        Ok(self.main.contains_key(blockhash.as_bytes())?)
+    pub fn contains(&self, blockhash: &HeaderHash) -> Result<bool> {
+        Ok(self.main.contains_key(blockhash.inner())?)
     }
     }
 
 
     /// Check if the store's order tree contains a given order number.
     /// Check if the store's order tree contains a given order number.
@@ -390,18 +377,17 @@ impl BlockStore {
     /// was found in the block store, and otherwise it is `None`, if it has not.
     /// was found in the block store, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one block was not found.
     /// case at least one block was not found.
-    pub fn get(&self, block_hashes: &[blake3::Hash], strict: bool) -> Result<Vec<Option<Block>>> {
+    pub fn get(&self, block_hashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Block>>> {
         let mut ret = Vec::with_capacity(block_hashes.len());
         let mut ret = Vec::with_capacity(block_hashes.len());
 
 
         for hash in block_hashes {
         for hash in block_hashes {
-            if let Some(found) = self.main.get(hash.as_bytes())? {
+            if let Some(found) = self.main.get(hash.inner())? {
                 let block = deserialize(&found)?;
                 let block = deserialize(&found)?;
                 ret.push(Some(block));
                 ret.push(Some(block));
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = hash.to_hex().as_str().to_string();
-                return Err(Error::BlockNotFound(s))
+                return Err(Error::BlockNotFound(hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -414,7 +400,7 @@ impl BlockStore {
     /// was found in the block order store, and otherwise it is `None`, if it has not.
     /// was found in the block order store, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one order number was not found.
     /// case at least one order number was not found.
-    pub fn get_order(&self, order: &[u64], strict: bool) -> Result<Vec<Option<blake3::Hash>>> {
+    pub fn get_order(&self, order: &[u64], strict: bool) -> Result<Vec<Option<HeaderHash>>> {
         let mut ret = Vec::with_capacity(order.len());
         let mut ret = Vec::with_capacity(order.len());
 
 
         for number in order {
         for number in order {
@@ -463,7 +449,7 @@ impl BlockStore {
     /// Retrieve all blocks from the store's main tree in the form of a
     /// Retrieve all blocks from the store's main tree in the form of a
     /// tuple (`hash`, `block`).
     /// tuple (`hash`, `block`).
     /// Be careful as this will try to load everything in memory.
     /// Be careful as this will try to load everything in memory.
-    pub fn get_all(&self) -> Result<Vec<(blake3::Hash, Block)>> {
+    pub fn get_all(&self) -> Result<Vec<(HeaderHash, Block)>> {
         let mut blocks = vec![];
         let mut blocks = vec![];
 
 
         for block in self.main.iter() {
         for block in self.main.iter() {
@@ -476,7 +462,7 @@ impl BlockStore {
     /// Retrieve complete order from the store's order tree in the form
     /// Retrieve complete order from the store's order tree in the form
     /// of a vector containing (`number`, `hash`) tuples.
     /// of a vector containing (`number`, `hash`) tuples.
     /// Be careful as this will try to load everything in memory.
     /// Be careful as this will try to load everything in memory.
-    pub fn get_all_order(&self) -> Result<Vec<(u64, blake3::Hash)>> {
+    pub fn get_all_order(&self) -> Result<Vec<(u64, HeaderHash)>> {
         let mut order = vec![];
         let mut order = vec![];
 
 
         for record in self.order.iter() {
         for record in self.order.iter() {
@@ -502,7 +488,7 @@ impl BlockStore {
     /// Fetch n hashes after given order number. In the iteration, if an order
     /// Fetch n hashes after given order number. In the iteration, if an order
     /// number is not found, the iteration stops and the function returns what
     /// number is not found, the iteration stops and the function returns what
     /// it has found so far in the `BlockOrderStore`.
     /// it has found so far in the `BlockOrderStore`.
-    pub fn get_after(&self, number: u64, n: u64) -> Result<Vec<blake3::Hash>> {
+    pub fn get_after(&self, number: u64, n: u64) -> Result<Vec<HeaderHash>> {
         let mut ret = vec![];
         let mut ret = vec![];
 
 
         let mut key = number;
         let mut key = number;
@@ -523,7 +509,7 @@ impl BlockStore {
 
 
     /// Fetch the first block hash in the order tree, based on the `Ord`
     /// Fetch the first block hash in the order tree, based on the `Ord`
     /// implementation for `Vec<u8>`.
     /// implementation for `Vec<u8>`.
-    pub fn get_first(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn get_first(&self) -> Result<(u64, HeaderHash)> {
         let found = match self.order.first()? {
         let found = match self.order.first()? {
             Some(s) => s,
             Some(s) => s,
             None => return Err(Error::BlockNumberNotFound(0)),
             None => return Err(Error::BlockNumberNotFound(0)),
@@ -535,7 +521,7 @@ impl BlockStore {
 
 
     /// Fetch the last block hash in the order tree, based on the `Ord`
     /// Fetch the last block hash in the order tree, based on the `Ord`
     /// implementation for `Vec<u8>`.
     /// implementation for `Vec<u8>`.
-    pub fn get_last(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn get_last(&self) -> Result<(u64, HeaderHash)> {
         let found = self.order.last()?.unwrap();
         let found = self.order.last()?.unwrap();
         let (number, hash) = parse_u64_key_record(found)?;
         let (number, hash) = parse_u64_key_record(found)?;
 
 
@@ -591,13 +577,13 @@ impl BlockStoreOverlay {
     /// The block's hash() function output is used as the key,
     /// The block's hash() function output is used as the key,
     /// while value is the serialized [`Block`] itself.
     /// while value is the serialized [`Block`] itself.
     /// On success, the function returns the block hashes in the same order.
     /// On success, the function returns the block hashes in the same order.
-    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<blake3::Hash>> {
+    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<HeaderHash>> {
         let mut ret = Vec::with_capacity(blocks.len());
         let mut ret = Vec::with_capacity(blocks.len());
         let mut lock = self.0.lock().unwrap();
         let mut lock = self.0.lock().unwrap();
 
 
         for block in blocks {
         for block in blocks {
             let blockhash = block.hash();
             let blockhash = block.hash();
-            lock.insert(SLED_BLOCK_TREE, blockhash.as_bytes(), &serialize(block))?;
+            lock.insert(SLED_BLOCK_TREE, blockhash.inner(), &serialize(block))?;
             ret.push(blockhash);
             ret.push(blockhash);
         }
         }
 
 
@@ -606,7 +592,7 @@ impl BlockStoreOverlay {
 
 
     /// Insert a slice of `u64` and block hashes into overlay's order tree.
     /// Insert a slice of `u64` and block hashes into overlay's order tree.
     /// The block order number is used as the key, and the blockhash is used as value.
     /// The block order number is used as the key, and the blockhash is used as value.
-    pub fn insert_order(&self, order: &[u64], hashes: &[blake3::Hash]) -> Result<()> {
+    pub fn insert_order(&self, order: &[u64], hashes: &[HeaderHash]) -> Result<()> {
         if order.len() != hashes.len() {
         if order.len() != hashes.len() {
             return Err(Error::InvalidInputLengths)
             return Err(Error::InvalidInputLengths)
         }
         }
@@ -614,7 +600,7 @@ impl BlockStoreOverlay {
         let mut lock = self.0.lock().unwrap();
         let mut lock = self.0.lock().unwrap();
 
 
         for (i, number) in order.iter().enumerate() {
         for (i, number) in order.iter().enumerate() {
-            lock.insert(SLED_BLOCK_ORDER_TREE, &number.to_be_bytes(), hashes[i].as_bytes())?;
+            lock.insert(SLED_BLOCK_ORDER_TREE, &number.to_be_bytes(), hashes[i].inner())?;
         }
         }
 
 
         Ok(())
         Ok(())
@@ -640,19 +626,18 @@ impl BlockStoreOverlay {
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one block was not found.
     /// case at least one block was not found.
-    pub fn get(&self, block_hashes: &[blake3::Hash], strict: bool) -> Result<Vec<Option<Block>>> {
+    pub fn get(&self, block_hashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Block>>> {
         let mut ret = Vec::with_capacity(block_hashes.len());
         let mut ret = Vec::with_capacity(block_hashes.len());
         let lock = self.0.lock().unwrap();
         let lock = self.0.lock().unwrap();
 
 
         for hash in block_hashes {
         for hash in block_hashes {
-            if let Some(found) = lock.get(SLED_BLOCK_TREE, hash.as_bytes())? {
+            if let Some(found) = lock.get(SLED_BLOCK_TREE, hash.inner())? {
                 let block = deserialize(&found)?;
                 let block = deserialize(&found)?;
                 ret.push(Some(block));
                 ret.push(Some(block));
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = hash.to_hex().as_str().to_string();
-                return Err(Error::BlockNotFound(s))
+                return Err(Error::BlockNotFound(hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -665,7 +650,7 @@ impl BlockStoreOverlay {
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one number was not found.
     /// case at least one number was not found.
-    pub fn get_order(&self, order: &[u64], strict: bool) -> Result<Vec<Option<blake3::Hash>>> {
+    pub fn get_order(&self, order: &[u64], strict: bool) -> Result<Vec<Option<HeaderHash>>> {
         let mut ret = Vec::with_capacity(order.len());
         let mut ret = Vec::with_capacity(order.len());
         let lock = self.0.lock().unwrap();
         let lock = self.0.lock().unwrap();
 
 
@@ -686,7 +671,7 @@ impl BlockStoreOverlay {
 
 
     /// Fetch the last block hash in the overlay's order tree, based on the `Ord`
     /// Fetch the last block hash in the overlay's order tree, based on the `Ord`
     /// implementation for `Vec<u8>`.
     /// implementation for `Vec<u8>`.
-    pub fn get_last(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn get_last(&self) -> Result<(u64, HeaderHash)> {
         let found = match self.0.lock().unwrap().last(SLED_BLOCK_ORDER_TREE)? {
         let found = match self.0.lock().unwrap().last(SLED_BLOCK_ORDER_TREE)? {
             Some(b) => b,
             Some(b) => b,
             None => return Err(Error::BlockNumberNotFound(0)),
             None => return Err(Error::BlockNumberNotFound(0)),
@@ -705,7 +690,7 @@ impl BlockStoreOverlay {
 /// Auxiliary function to append a transaction to a Merkle tree.
 /// Auxiliary function to append a transaction to a Merkle tree.
 pub fn append_tx_to_merkle_tree(tree: &mut MerkleTree, tx: &Transaction) {
 pub fn append_tx_to_merkle_tree(tree: &mut MerkleTree, tx: &Transaction) {
     let mut buf = [0u8; 64];
     let mut buf = [0u8; 64];
-    buf[..blake3::OUT_LEN].copy_from_slice(tx.hash().inner());
+    buf[..32].copy_from_slice(tx.hash().inner());
     let leaf = pallas::Base::from_uniform_bytes(&buf);
     let leaf = pallas::Base::from_uniform_bytes(&buf);
     tree.append(leaf.into());
     tree.append(leaf.into());
 }
 }

+ 66 - 33
src/blockchain/header_store.rs

@@ -16,7 +16,9 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
  */
 
 
-use darkfi_sdk::{blockchain::block_version, crypto::MerkleTree};
+use std::fmt;
+
+use darkfi_sdk::{blockchain::block_version, crypto::MerkleTree, AsHex};
 
 
 #[cfg(feature = "async-serial")]
 #[cfg(feature = "async-serial")]
 use darkfi_serial::async_trait;
 use darkfi_serial::async_trait;
@@ -26,13 +28,38 @@ use crate::{util::time::Timestamp, Error, Result};
 
 
 use super::{parse_record, SledDbOverlayPtr};
 use super::{parse_record, SledDbOverlayPtr};
 
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq, SerialEncodable, SerialDecodable)]
+// We have to introduce a type rather than using an alias so we can restrict API access
+pub struct HeaderHash(pub [u8; 32]);
+
+impl HeaderHash {
+    pub fn new(data: [u8; 32]) -> Self {
+        Self(data)
+    }
+
+    #[inline]
+    pub fn inner(&self) -> &[u8; 32] {
+        &self.0
+    }
+
+    pub fn as_string(&self) -> String {
+        self.0.hex().to_string()
+    }
+}
+
+impl fmt::Display for HeaderHash {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.0.hex())
+    }
+}
+
 /// This struct represents a tuple of the form (version, previous, height, timestamp, nonce, merkle_tree).
 /// This struct represents a tuple of the form (version, previous, height, timestamp, nonce, merkle_tree).
 #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
 #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
 pub struct Header {
 pub struct Header {
     /// Block version
     /// Block version
     pub version: u8,
     pub version: u8,
     /// Previous block hash
     /// Previous block hash
-    pub previous: blake3::Hash,
+    pub previous: HeaderHash,
     /// Block height
     /// Block height
     pub height: u64,
     pub height: u64,
     /// Block creation timestamp
     /// Block creation timestamp
@@ -44,31 +71,39 @@ pub struct Header {
 }
 }
 
 
 impl Header {
 impl Header {
-    pub fn new(previous: blake3::Hash, height: u64, timestamp: Timestamp, nonce: u64) -> Self {
+    pub fn new(previous: HeaderHash, height: u64, timestamp: Timestamp, nonce: u64) -> Self {
         let version = block_version(height);
         let version = block_version(height);
         let tree = MerkleTree::new(1);
         let tree = MerkleTree::new(1);
         Self { version, previous, height, timestamp, nonce, tree }
         Self { version, previous, height, timestamp, nonce, tree }
     }
     }
 
 
     /// Compute the header's hash
     /// Compute the header's hash
-    pub fn hash(&self) -> Result<blake3::Hash> {
+    pub fn hash(&self) -> HeaderHash {
         let mut hasher = blake3::Hasher::new();
         let mut hasher = blake3::Hasher::new();
 
 
-        self.version.encode(&mut hasher)?;
-        self.previous.encode(&mut hasher)?;
-        self.height.encode(&mut hasher)?;
-        self.timestamp.encode(&mut hasher)?;
-        self.nonce.encode(&mut hasher)?;
-        self.tree.root(0).unwrap().encode(&mut hasher)?;
-
-        Ok(hasher.finalize())
+        // Blake3 hasher .update() method never fails.
+        // This call returns a Result due to how the Write trait is specified.
+        // Calling unwrap() here should be safe.
+        self.version.encode(&mut hasher).expect("blake3 hasher");
+        self.previous.encode(&mut hasher).expect("blake3 hasher");
+        self.height.encode(&mut hasher).expect("blake3 hasher");
+        self.timestamp.encode(&mut hasher).expect("blake3 hasher");
+        self.nonce.encode(&mut hasher).expect("blake3 hasher");
+        self.tree.root(0).unwrap().encode(&mut hasher).expect("blake3 hasher");
+
+        HeaderHash(hasher.finalize().into())
     }
     }
 }
 }
 
 
 impl Default for Header {
 impl Default for Header {
     /// Represents the genesis header on current timestamp
     /// Represents the genesis header on current timestamp
     fn default() -> Self {
     fn default() -> Self {
-        Header::new(blake3::hash(b"Let there be dark!"), 0, Timestamp::current_time(), 0)
+        Header::new(
+            HeaderHash::new(blake3::hash(b"Let there be dark!").into()),
+            0,
+            Timestamp::current_time(),
+            0,
+        )
     }
     }
 }
 }
 
 
@@ -88,8 +123,8 @@ impl HeaderStore {
     }
     }
 
 
     /// Insert a slice of [`Header`] into the blockstore.
     /// Insert a slice of [`Header`] into the blockstore.
-    pub fn insert(&self, headers: &[Header]) -> Result<Vec<blake3::Hash>> {
-        let (batch, ret) = self.insert_batch(headers)?;
+    pub fn insert(&self, headers: &[Header]) -> Result<Vec<HeaderHash>> {
+        let (batch, ret) = self.insert_batch(headers);
         self.0.apply_batch(batch)?;
         self.0.apply_batch(batch)?;
         Ok(ret)
         Ok(ret)
     }
     }
@@ -100,22 +135,22 @@ impl HeaderStore {
     /// while value is the serialized [`Header`] itself.
     /// while value is the serialized [`Header`] itself.
     /// On success, the function returns the header hashes in the same
     /// On success, the function returns the header hashes in the same
     /// order, along with the corresponding operation batch.
     /// order, along with the corresponding operation batch.
-    pub fn insert_batch(&self, headers: &[Header]) -> Result<(sled::Batch, Vec<blake3::Hash>)> {
+    pub fn insert_batch(&self, headers: &[Header]) -> (sled::Batch, Vec<HeaderHash>) {
         let mut ret = Vec::with_capacity(headers.len());
         let mut ret = Vec::with_capacity(headers.len());
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
         for header in headers {
         for header in headers {
-            let headerhash = header.hash()?;
-            batch.insert(headerhash.as_bytes(), serialize(header));
+            let headerhash = header.hash();
+            batch.insert(headerhash.inner(), serialize(header));
             ret.push(headerhash);
             ret.push(headerhash);
         }
         }
 
 
-        Ok((batch, ret))
+        (batch, ret)
     }
     }
 
 
     /// Check if the headerstore contains a given headerhash.
     /// Check if the headerstore contains a given headerhash.
-    pub fn contains(&self, headerhash: &blake3::Hash) -> Result<bool> {
-        Ok(self.0.contains_key(headerhash.as_bytes())?)
+    pub fn contains(&self, headerhash: &HeaderHash) -> Result<bool> {
+        Ok(self.0.contains_key(headerhash.inner())?)
     }
     }
 
 
     /// Fetch given headerhashes from the headerstore.
     /// Fetch given headerhashes from the headerstore.
@@ -123,18 +158,17 @@ impl HeaderStore {
     /// was found in the headerstore, and otherwise it is `None`, if it has not.
     /// was found in the headerstore, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one header was not found.
     /// case at least one header was not found.
-    pub fn get(&self, headerhashes: &[blake3::Hash], strict: bool) -> Result<Vec<Option<Header>>> {
+    pub fn get(&self, headerhashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Header>>> {
         let mut ret = Vec::with_capacity(headerhashes.len());
         let mut ret = Vec::with_capacity(headerhashes.len());
 
 
         for hash in headerhashes {
         for hash in headerhashes {
-            if let Some(found) = self.0.get(hash.as_bytes())? {
+            if let Some(found) = self.0.get(hash.inner())? {
                 let header = deserialize(&found)?;
                 let header = deserialize(&found)?;
                 ret.push(Some(header));
                 ret.push(Some(header));
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = hash.to_hex().as_str().to_string();
-                return Err(Error::HeaderNotFound(s))
+                return Err(Error::HeaderNotFound(hash.inner().hex()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -145,7 +179,7 @@ impl HeaderStore {
     /// Retrieve all headers from the headerstore in the form of a tuple
     /// Retrieve all headers from the headerstore in the form of a tuple
     /// (`headerhash`, `header`).
     /// (`headerhash`, `header`).
     /// Be careful as this will try to load everything in memory.
     /// Be careful as this will try to load everything in memory.
-    pub fn get_all(&self) -> Result<Vec<(blake3::Hash, Header)>> {
+    pub fn get_all(&self) -> Result<Vec<(HeaderHash, Header)>> {
         let mut headers = vec![];
         let mut headers = vec![];
 
 
         for header in self.0.iter() {
         for header in self.0.iter() {
@@ -169,13 +203,13 @@ impl HeaderStoreOverlay {
     /// The header's hash() function output is used as the key,
     /// The header's hash() function output is used as the key,
     /// while value is the serialized [`Header`] itself.
     /// while value is the serialized [`Header`] itself.
     /// On success, the function returns the header hashes in the same order.
     /// On success, the function returns the header hashes in the same order.
-    pub fn insert(&self, headers: &[Header]) -> Result<Vec<blake3::Hash>> {
+    pub fn insert(&self, headers: &[Header]) -> Result<Vec<HeaderHash>> {
         let mut ret = Vec::with_capacity(headers.len());
         let mut ret = Vec::with_capacity(headers.len());
         let mut lock = self.0.lock().unwrap();
         let mut lock = self.0.lock().unwrap();
 
 
         for header in headers {
         for header in headers {
-            let headerhash = header.hash()?;
-            lock.insert(SLED_HEADER_TREE, headerhash.as_bytes(), &serialize(header))?;
+            let headerhash = header.hash();
+            lock.insert(SLED_HEADER_TREE, headerhash.inner(), &serialize(header))?;
             ret.push(headerhash);
             ret.push(headerhash);
         }
         }
 
 
@@ -187,19 +221,18 @@ impl HeaderStoreOverlay {
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// The second parameter is a boolean which tells the function to fail in
     /// The second parameter is a boolean which tells the function to fail in
     /// case at least one header was not found.
     /// case at least one header was not found.
-    pub fn get(&self, headerhashes: &[blake3::Hash], strict: bool) -> Result<Vec<Option<Header>>> {
+    pub fn get(&self, headerhashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Header>>> {
         let mut ret = Vec::with_capacity(headerhashes.len());
         let mut ret = Vec::with_capacity(headerhashes.len());
         let lock = self.0.lock().unwrap();
         let lock = self.0.lock().unwrap();
 
 
         for hash in headerhashes {
         for hash in headerhashes {
-            if let Some(found) = lock.get(SLED_HEADER_TREE, hash.as_bytes())? {
+            if let Some(found) = lock.get(SLED_HEADER_TREE, hash.inner())? {
                 let header = deserialize(&found)?;
                 let header = deserialize(&found)?;
                 ret.push(Some(header));
                 ret.push(Some(header));
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = hash.to_hex().as_str().to_string();
-                return Err(Error::HeaderNotFound(s))
+                return Err(Error::HeaderNotFound(hash.inner().hex()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }

+ 20 - 20
src/blockchain/mod.rs

@@ -32,7 +32,7 @@ pub use block_store::{Block, BlockDifficulty, BlockInfo, BlockStore, BlockStoreO
 
 
 /// Header definition and storage implementation
 /// Header definition and storage implementation
 pub mod header_store;
 pub mod header_store;
-pub use header_store::{Header, HeaderStore, HeaderStoreOverlay};
+pub use header_store::{Header, HeaderHash, HeaderStore, HeaderStoreOverlay};
 
 
 /// Transactions related storage implementations
 /// Transactions related storage implementations
 pub mod tx_store;
 pub mod tx_store;
@@ -73,18 +73,18 @@ impl Blockchain {
     /// data that can be fed into the different trees of the database.
     /// data that can be fed into the different trees of the database.
     /// Upon success, the functions returns the block hash that
     /// Upon success, the functions returns the block hash that
     /// were given and appended to the ledger.
     /// were given and appended to the ledger.
-    pub fn add_block(&self, block: &BlockInfo) -> Result<blake3::Hash> {
+    pub fn add_block(&self, block: &BlockInfo) -> Result<HeaderHash> {
         let mut trees = vec![];
         let mut trees = vec![];
         let mut batches = vec![];
         let mut batches = vec![];
 
 
         // Store header
         // Store header
-        let (headers_batch, _) = self.headers.insert_batch(&[block.header.clone()])?;
+        let (headers_batch, _) = self.headers.insert_batch(&[block.header.clone()]);
         trees.push(self.headers.0.clone());
         trees.push(self.headers.0.clone());
         batches.push(headers_batch);
         batches.push(headers_batch);
 
 
         // Store block
         // Store block
-        let blk: Block = Block::from_block_info(block)?;
-        let (bocks_batch, block_hashes) = self.blocks.insert_batch(&[blk])?;
+        let blk: Block = Block::from_block_info(block);
+        let (bocks_batch, block_hashes) = self.blocks.insert_batch(&[blk]);
         let block_hash = block_hashes[0];
         let block_hash = block_hashes[0];
         let block_hash_vec = [block_hash];
         let block_hash_vec = [block_hash];
         trees.push(self.blocks.main.clone());
         trees.push(self.blocks.main.clone());
@@ -92,18 +92,18 @@ impl Blockchain {
 
 
         // Store block order
         // Store block order
         let blocks_order_batch =
         let blocks_order_batch =
-            self.blocks.insert_batch_order(&[block.header.height], &block_hash_vec)?;
+            self.blocks.insert_batch_order(&[block.header.height], &block_hash_vec);
         trees.push(self.blocks.order.clone());
         trees.push(self.blocks.order.clone());
         batches.push(blocks_order_batch);
         batches.push(blocks_order_batch);
 
 
         // Store transactions
         // Store transactions
-        let (txs_batch, txs_hashes) = self.transactions.insert_batch(&block.txs)?;
+        let (txs_batch, txs_hashes) = self.transactions.insert_batch(&block.txs);
         trees.push(self.transactions.main.clone());
         trees.push(self.transactions.main.clone());
         batches.push(txs_batch);
         batches.push(txs_batch);
 
 
         // Store transactions_locations
         // Store transactions_locations
         let txs_locations_batch =
         let txs_locations_batch =
-            self.transactions.insert_batch_location(&txs_hashes, block.header.height)?;
+            self.transactions.insert_batch_location(&txs_hashes, block.header.height);
         trees.push(self.transactions.location.clone());
         trees.push(self.transactions.location.clone());
         batches.push(txs_locations_batch);
         batches.push(txs_locations_batch);
 
 
@@ -127,11 +127,11 @@ impl Blockchain {
         }
         }
 
 
         // Check provided info produces the same hash
         // Check provided info produces the same hash
-        Ok(blockhash == block.hash()?)
+        Ok(blockhash == block.hash())
     }
     }
 
 
     /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
     /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
-    pub fn get_blocks_by_hash(&self, hashes: &[blake3::Hash]) -> Result<Vec<BlockInfo>> {
+    pub fn get_blocks_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<BlockInfo>> {
         let blocks = self.blocks.get(hashes, true)?;
         let blocks = self.blocks.get(hashes, true)?;
         let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
         let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
         let ret = self.get_blocks_infos(&blocks)?;
         let ret = self.get_blocks_infos(&blocks)?;
@@ -194,7 +194,7 @@ impl Blockchain {
     }
     }
 
 
     /// Retrieve genesis (first) block height and hash.
     /// Retrieve genesis (first) block height and hash.
-    pub fn genesis(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn genesis(&self) -> Result<(u64, HeaderHash)> {
         self.blocks.get_first()
         self.blocks.get_first()
     }
     }
 
 
@@ -205,7 +205,7 @@ impl Blockchain {
     }
     }
 
 
     /// Retrieve the last block height and hash.
     /// Retrieve the last block height and hash.
-    pub fn last(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn last(&self) -> Result<(u64, HeaderHash)> {
         self.blocks.get_last()
         self.blocks.get_last()
     }
     }
 
 
@@ -239,7 +239,7 @@ impl Blockchain {
     /// On success, the function returns the transaction hashes in the same order
     /// On success, the function returns the transaction hashes in the same order
     /// as the input transactions.
     /// as the input transactions.
     pub fn add_pending_txs(&self, txs: &[Transaction]) -> Result<Vec<TransactionHash>> {
     pub fn add_pending_txs(&self, txs: &[Transaction]) -> Result<Vec<TransactionHash>> {
-        let (txs_batch, txs_hashes) = self.transactions.insert_batch_pending(txs)?;
+        let (txs_batch, txs_hashes) = self.transactions.insert_batch_pending(txs);
         let txs_order_batch = self.transactions.insert_batch_pending_order(&txs_hashes)?;
         let txs_order_batch = self.transactions.insert_batch_pending_order(&txs_hashes)?;
 
 
         // Perform an atomic transaction over the trees and apply the batches.
         // Perform an atomic transaction over the trees and apply the batches.
@@ -312,7 +312,7 @@ impl Blockchain {
     /// Be careful as this will try to load everything in memory.
     /// Be careful as this will try to load everything in memory.
     pub fn get_all(&self) -> Result<Vec<BlockInfo>> {
     pub fn get_all(&self) -> Result<Vec<BlockInfo>> {
         let order = self.blocks.get_all_order()?;
         let order = self.blocks.get_all_order()?;
-        let order: Vec<blake3::Hash> = order.iter().map(|x| x.1).collect();
+        let order: Vec<HeaderHash> = order.iter().map(|x| x.1).collect();
         let blocks = self.get_blocks_by_hash(&order)?;
         let blocks = self.get_blocks_by_hash(&order)?;
 
 
         Ok(blocks)
         Ok(blocks)
@@ -357,7 +357,7 @@ impl BlockchainOverlay {
     }
     }
 
 
     /// Retrieve the last block height and hash.
     /// Retrieve the last block height and hash.
-    pub fn last(&self) -> Result<(u64, blake3::Hash)> {
+    pub fn last(&self) -> Result<(u64, HeaderHash)> {
         self.blocks.get_last()
         self.blocks.get_last()
     }
     }
 
 
@@ -385,12 +385,12 @@ impl BlockchainOverlay {
     /// were given and appended to the overlay.
     /// were given and appended to the overlay.
     /// Since we are adding to the overlay, we don't need to exeucte
     /// Since we are adding to the overlay, we don't need to exeucte
     /// the writes atomically.
     /// the writes atomically.
-    pub fn add_block(&self, block: &BlockInfo) -> Result<blake3::Hash> {
+    pub fn add_block(&self, block: &BlockInfo) -> Result<HeaderHash> {
         // Store header
         // Store header
         self.headers.insert(&[block.header.clone()])?;
         self.headers.insert(&[block.header.clone()])?;
 
 
         // Store block
         // Store block
-        let blk: Block = Block::from_block_info(block)?;
+        let blk: Block = Block::from_block_info(block);
         let txs_hashes = blk.txs.clone();
         let txs_hashes = blk.txs.clone();
         let block_hash = self.blocks.insert(&[blk])?[0];
         let block_hash = self.blocks.insert(&[blk])?[0];
         let block_hash_vec = [block_hash];
         let block_hash_vec = [block_hash];
@@ -421,11 +421,11 @@ impl BlockchainOverlay {
         }
         }
 
 
         // Check provided info produces the same hash
         // Check provided info produces the same hash
-        Ok(blockhash == block.hash()?)
+        Ok(blockhash == block.hash())
     }
     }
 
 
     /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
     /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
-    pub fn get_blocks_by_hash(&self, hashes: &[blake3::Hash]) -> Result<Vec<BlockInfo>> {
+    pub fn get_blocks_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<BlockInfo>> {
         let blocks = self.blocks.get(hashes, true)?;
         let blocks = self.blocks.get(hashes, true)?;
         let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
         let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
         let ret = self.get_blocks_infos(&blocks)?;
         let ret = self.get_blocks_infos(&blocks)?;
@@ -453,7 +453,7 @@ impl BlockchainOverlay {
     }
     }
 
 
     /// Retrieve [`Block`]s by given hashes and return their transactions hashes.
     /// Retrieve [`Block`]s by given hashes and return their transactions hashes.
-    pub fn get_blocks_txs_hashes(&self, hashes: &[blake3::Hash]) -> Result<Vec<TransactionHash>> {
+    pub fn get_blocks_txs_hashes(&self, hashes: &[HeaderHash]) -> Result<Vec<TransactionHash>> {
         let blocks = self.blocks.get(hashes, true)?;
         let blocks = self.blocks.get(hashes, true)?;
         let mut ret = vec![];
         let mut ret = vec![];
         for block in blocks {
         for block in blocks {

+ 16 - 20
src/blockchain/tx_store.rs

@@ -18,7 +18,7 @@
 
 
 use std::collections::HashMap;
 use std::collections::HashMap;
 
 
-use darkfi_sdk::{tx::TransactionHash, AsHex};
+use darkfi_sdk::tx::TransactionHash;
 use darkfi_serial::{deserialize, serialize};
 use darkfi_serial::{deserialize, serialize};
 
 
 use crate::{tx::Transaction, Error, Result};
 use crate::{tx::Transaction, Error, Result};
@@ -65,21 +65,21 @@ impl TxStore {
 
 
     /// Insert a slice of [`Transaction`] into the store's main tree.
     /// Insert a slice of [`Transaction`] into the store's main tree.
     pub fn insert(&self, transactions: &[Transaction]) -> Result<Vec<TransactionHash>> {
     pub fn insert(&self, transactions: &[Transaction]) -> Result<Vec<TransactionHash>> {
-        let (batch, ret) = self.insert_batch(transactions)?;
+        let (batch, ret) = self.insert_batch(transactions);
         self.main.apply_batch(batch)?;
         self.main.apply_batch(batch)?;
         Ok(ret)
         Ok(ret)
     }
     }
 
 
     /// Insert a slice of [`TransactionHash`] into the store's location tree.
     /// Insert a slice of [`TransactionHash`] into the store's location tree.
     pub fn insert_location(&self, txs_hashes: &[TransactionHash], block_height: u64) -> Result<()> {
     pub fn insert_location(&self, txs_hashes: &[TransactionHash], block_height: u64) -> Result<()> {
-        let batch = self.insert_batch_location(txs_hashes, block_height)?;
+        let batch = self.insert_batch_location(txs_hashes, block_height);
         self.location.apply_batch(batch)?;
         self.location.apply_batch(batch)?;
         Ok(())
         Ok(())
     }
     }
 
 
     /// Insert a slice of [`Transaction`] into the store's pending txs tree.
     /// Insert a slice of [`Transaction`] into the store's pending txs tree.
     pub fn insert_pending(&self, transactions: &[Transaction]) -> Result<Vec<TransactionHash>> {
     pub fn insert_pending(&self, transactions: &[Transaction]) -> Result<Vec<TransactionHash>> {
-        let (batch, ret) = self.insert_batch_pending(transactions)?;
+        let (batch, ret) = self.insert_batch_pending(transactions);
         self.pending.apply_batch(batch)?;
         self.pending.apply_batch(batch)?;
         Ok(ret)
         Ok(ret)
     }
     }
@@ -101,7 +101,7 @@ impl TxStore {
     pub fn insert_batch(
     pub fn insert_batch(
         &self,
         &self,
         transactions: &[Transaction],
         transactions: &[Transaction],
-    ) -> Result<(sled::Batch, Vec<TransactionHash>)> {
+    ) -> (sled::Batch, Vec<TransactionHash>) {
         let mut ret = Vec::with_capacity(transactions.len());
         let mut ret = Vec::with_capacity(transactions.len());
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
@@ -111,7 +111,7 @@ impl TxStore {
             ret.push(tx_hash);
             ret.push(tx_hash);
         }
         }
 
 
-        Ok((batch, ret))
+        (batch, ret)
     }
     }
 
 
     /// Generate the sled batch corresponding to an insert to the location tree,
     /// Generate the sled batch corresponding to an insert to the location tree,
@@ -122,7 +122,7 @@ impl TxStore {
         &self,
         &self,
         txs_hashes: &[TransactionHash],
         txs_hashes: &[TransactionHash],
         block_height: u64,
         block_height: u64,
-    ) -> Result<sled::Batch> {
+    ) -> sled::Batch {
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
         for (index, tx_hash) in txs_hashes.iter().enumerate() {
         for (index, tx_hash) in txs_hashes.iter().enumerate() {
@@ -130,7 +130,7 @@ impl TxStore {
             batch.insert(tx_hash.inner(), serialized);
             batch.insert(tx_hash.inner(), serialized);
         }
         }
 
 
-        Ok(batch)
+        batch
     }
     }
 
 
     /// Generate the sled batch corresponding to an insert to the pending txs tree,
     /// Generate the sled batch corresponding to an insert to the pending txs tree,
@@ -143,7 +143,7 @@ impl TxStore {
     pub fn insert_batch_pending(
     pub fn insert_batch_pending(
         &self,
         &self,
         transactions: &[Transaction],
         transactions: &[Transaction],
-    ) -> Result<(sled::Batch, Vec<TransactionHash>)> {
+    ) -> (sled::Batch, Vec<TransactionHash>) {
         let mut ret = Vec::with_capacity(transactions.len());
         let mut ret = Vec::with_capacity(transactions.len());
         let mut batch = sled::Batch::default();
         let mut batch = sled::Batch::default();
 
 
@@ -153,7 +153,7 @@ impl TxStore {
             ret.push(tx_hash);
             ret.push(tx_hash);
         }
         }
 
 
-        Ok((batch, ret))
+        (batch, ret)
     }
     }
 
 
     /// Generate the sled batch corresponding to an insert to the pending txs
     /// Generate the sled batch corresponding to an insert to the pending txs
@@ -207,8 +207,7 @@ impl TxStore {
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = tx_hash.inner().hex().as_str().to_string();
-                return Err(Error::TransactionNotFound(s))
+                return Err(Error::TransactionNotFound(tx_hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -235,8 +234,7 @@ impl TxStore {
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = tx_hash.inner().hex();
-                return Err(Error::TransactionNotFound(s))
+                return Err(Error::TransactionNotFound(tx_hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -263,8 +261,7 @@ impl TxStore {
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = tx_hash.inner().hex();
-                return Err(Error::TransactionNotFound(s))
+                return Err(Error::TransactionNotFound(tx_hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -437,8 +434,7 @@ impl TxStoreOverlay {
                 continue
                 continue
             }
             }
             if strict {
             if strict {
-                let s = tx_hash.inner().hex();
-                return Err(Error::TransactionNotFound(s))
+                return Err(Error::TransactionNotFound(tx_hash.as_string()))
             }
             }
             ret.push(None);
             ret.push(None);
         }
         }
@@ -450,7 +446,7 @@ impl TxStoreOverlay {
     /// raw bytes as input and doesn't deserialize the retrieved value.
     /// raw bytes as input and doesn't deserialize the retrieved value.
     /// The resulting vector contains `Option`, which is `Some` if the tx
     /// The resulting vector contains `Option`, which is `Some` if the tx
     /// was found in the overlay, and otherwise it is `None`, if it has not.
     /// was found in the overlay, and otherwise it is `None`, if it has not.
-    pub fn get_raw(&self, tx_hash: &[u8; blake3::OUT_LEN]) -> Result<Option<Vec<u8>>> {
+    pub fn get_raw(&self, tx_hash: &[u8; 32]) -> Result<Option<Vec<u8>>> {
         let lock = self.0.lock().unwrap();
         let lock = self.0.lock().unwrap();
         if let Some(found) = lock.get(SLED_TX_TREE, tx_hash)? {
         if let Some(found) = lock.get(SLED_TX_TREE, tx_hash)? {
             return Ok(Some(found.to_vec()))
             return Ok(Some(found.to_vec()))
@@ -463,7 +459,7 @@ impl TxStoreOverlay {
     /// retrieved value. The resulting vector contains `Option`, which is
     /// retrieved value. The resulting vector contains `Option`, which is
     /// `Some` if the location was found in the overlay, and otherwise it
     /// `Some` if the location was found in the overlay, and otherwise it
     /// is `None`, if it has not.
     /// is `None`, if it has not.
-    pub fn get_location_raw(&self, tx_hash: &[u8; blake3::OUT_LEN]) -> Result<Option<Vec<u8>>> {
+    pub fn get_location_raw(&self, tx_hash: &[u8; 32]) -> Result<Option<Vec<u8>>> {
         let lock = self.0.lock().unwrap();
         let lock = self.0.lock().unwrap();
         if let Some(found) = lock.get(SLED_TX_LOCATION_TREE, tx_hash)? {
         if let Some(found) = lock.get(SLED_TX_LOCATION_TREE, tx_hash)? {
             return Ok(Some(found.to_vec()))
             return Ok(Some(found.to_vec()))

+ 1 - 1
src/contract/test-harness/src/lib.rs

@@ -316,7 +316,7 @@ fn benchmark_wasm_calls(
             overlay.clone(),
             overlay.clone(),
             call.data.contract_id,
             call.data.contract_id,
             block_height,
             block_height,
-            tx.hash().clone(),
+            tx.hash(),
             idx as u32,
             idx as u32,
         )
         )
         .expect("runtime");
         .expect("runtime");

+ 2 - 2
src/contract/test-harness/src/money_pow_reward.rs

@@ -113,7 +113,7 @@ impl TestHarness {
 
 
         // Generate block header
         // Generate block header
         let header = Header::new(
         let header = Header::new(
-            previous.hash()?,
+            previous.hash(),
             previous.header.height + 1,
             previous.header.height + 1,
             timestamp,
             timestamp,
             previous.header.nonce,
             previous.header.nonce,
@@ -126,7 +126,7 @@ impl TestHarness {
         block.append_txs(vec![tx]);
         block.append_txs(vec![tx]);
 
 
         // Attach signature
         // Attach signature
-        block.sign(&wallet.keypair.secret)?;
+        block.sign(&wallet.keypair.secret);
 
 
         // For all holders, append the block
         // For all holders, append the block
         let mut found_owncoins = vec![];
         let mut found_owncoins = vec![];

+ 5 - 1
src/sdk/src/tx.rs

@@ -31,7 +31,7 @@ use super::{
     ContractError, GenericResult,
     ContractError, GenericResult,
 };
 };
 
 
-#[derive(Clone, Debug, Eq, Hash, PartialEq, SerialEncodable, SerialDecodable)]
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, SerialEncodable, SerialDecodable)]
 // We have to introduce a type rather than using an alias so we can implement Display
 // We have to introduce a type rather than using an alias so we can implement Display
 pub struct TransactionHash(pub [u8; 32]);
 pub struct TransactionHash(pub [u8; 32]);
 
 
@@ -48,6 +48,10 @@ impl TransactionHash {
     pub fn inner(&self) -> &[u8; 32] {
     pub fn inner(&self) -> &[u8; 32] {
         &self.0
         &self.0
     }
     }
+
+    pub fn as_string(&self) -> String {
+        self.0.hex().to_string()
+    }
 }
 }
 
 
 impl FromStr for TransactionHash {
 impl FromStr for TransactionHash {

+ 19 - 19
src/validator/consensus.rs

@@ -31,7 +31,7 @@ use smol::lock::RwLock;
 use crate::{
 use crate::{
     blockchain::{
     blockchain::{
         block_store::{BlockDifficulty, BlockRanks},
         block_store::{BlockDifficulty, BlockRanks},
-        BlockInfo, Blockchain, BlockchainOverlay, BlockchainOverlayPtr, Header,
+        BlockInfo, Blockchain, BlockchainOverlay, BlockchainOverlayPtr, Header, HeaderHash,
     },
     },
     tx::Transaction,
     tx::Transaction,
     util::time::Timestamp,
     util::time::Timestamp,
@@ -195,7 +195,7 @@ impl Consensus {
             let (next_target, next_difficulty) = fork.module.next_mine_target_and_difficulty()?;
             let (next_target, next_difficulty) = fork.module.next_mine_target_and_difficulty()?;
 
 
             // Calculate block rank
             // Calculate block rank
-            let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target)?;
+            let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target);
 
 
             // Update PoW module
             // Update PoW module
             fork.module.append(block.header.timestamp, &next_difficulty);
             fork.module.append(block.header.timestamp, &next_difficulty);
@@ -245,8 +245,8 @@ impl Consensus {
     /// an empty vector is returned.
     /// an empty vector is returned.
     pub async fn get_fork_proposals(
     pub async fn get_fork_proposals(
         &self,
         &self,
-        tip: blake3::Hash,
-        fork_tip: blake3::Hash,
+        tip: HeaderHash,
+        fork_tip: HeaderHash,
     ) -> Result<Vec<Proposal>> {
     ) -> Result<Vec<Proposal>> {
         // Tip must be canonical(finalized) blockchain last
         // Tip must be canonical(finalized) blockchain last
         if self.blockchain.last()?.1 != tip {
         if self.blockchain.last()?.1 != tip {
@@ -269,7 +269,7 @@ impl Consensus {
                 let blocks = fork.overlay.lock().unwrap().get_blocks_by_hash(&fork.proposals)?;
                 let blocks = fork.overlay.lock().unwrap().get_blocks_by_hash(&fork.proposals)?;
                 let mut ret = Vec::with_capacity(blocks.len());
                 let mut ret = Vec::with_capacity(blocks.len());
                 for block in blocks {
                 for block in blocks {
-                    ret.push(Proposal::new(block)?);
+                    ret.push(Proposal::new(block));
                 }
                 }
                 drop(forks);
                 drop(forks);
                 return Ok(ret)
                 return Ok(ret)
@@ -284,7 +284,7 @@ impl Consensus {
     /// If multiple best forks exist, grab the proposals of the first one
     /// If multiple best forks exist, grab the proposals of the first one
     /// If provided tip is not the canonical(finalized), or no forks exist,
     /// If provided tip is not the canonical(finalized), or no forks exist,
     /// an empty vector is returned.
     /// an empty vector is returned.
-    pub async fn get_best_fork_proposals(&self, tip: blake3::Hash) -> Result<Vec<Proposal>> {
+    pub async fn get_best_fork_proposals(&self, tip: HeaderHash) -> Result<Vec<Proposal>> {
         // Tip must be canonical(finalized) blockchain last
         // Tip must be canonical(finalized) blockchain last
         if self.blockchain.last()?.1 != tip {
         if self.blockchain.last()?.1 != tip {
             return Ok(vec![])
             return Ok(vec![])
@@ -306,7 +306,7 @@ impl Consensus {
         let blocks = fork.overlay.lock().unwrap().get_blocks_by_hash(&fork.proposals)?;
         let blocks = fork.overlay.lock().unwrap().get_blocks_by_hash(&fork.proposals)?;
         let mut ret = Vec::with_capacity(blocks.len());
         let mut ret = Vec::with_capacity(blocks.len());
         for block in blocks {
         for block in blocks {
-            ret.push(Proposal::new(block)?);
+            ret.push(Proposal::new(block));
         }
         }
 
 
         Ok(ret)
         Ok(ret)
@@ -318,7 +318,7 @@ impl Consensus {
     /// to canonical chain from the finalized fork.
     /// to canonical chain from the finalized fork.
     pub async fn reset_forks(
     pub async fn reset_forks(
         &self,
         &self,
-        prefix: &[blake3::Hash],
+        prefix: &[HeaderHash],
         finalized_fork_index: &usize,
         finalized_fork_index: &usize,
     ) -> Result<()> {
     ) -> Result<()> {
         // Grab a lock over current forks
         // Grab a lock over current forks
@@ -434,15 +434,15 @@ impl Consensus {
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct Proposal {
 pub struct Proposal {
     /// Block hash
     /// Block hash
-    pub hash: blake3::Hash,
+    pub hash: HeaderHash,
     /// Block data
     /// Block data
     pub block: BlockInfo,
     pub block: BlockInfo,
 }
 }
 
 
 impl Proposal {
 impl Proposal {
-    pub fn new(block: BlockInfo) -> Result<Self> {
-        let hash = block.hash()?;
-        Ok(Self { hash, block })
+    pub fn new(block: BlockInfo) -> Self {
+        let hash = block.hash();
+        Self { hash, block }
     }
     }
 }
 }
 
 
@@ -465,7 +465,7 @@ pub struct Fork {
     /// Current PoW module state,
     /// Current PoW module state,
     pub module: PoWModule,
     pub module: PoWModule,
     /// Fork proposal hashes sequence
     /// Fork proposal hashes sequence
-    pub proposals: Vec<blake3::Hash>,
+    pub proposals: Vec<HeaderHash>,
     /// Fork proposal overlay diffs sequence
     /// Fork proposal overlay diffs sequence
     pub diffs: Vec<SledDbOverlayState>,
     pub diffs: Vec<SledDbOverlayState>,
     /// Valid pending transaction hashes
     /// Valid pending transaction hashes
@@ -510,7 +510,7 @@ impl Fork {
 
 
         // Generate the new header
         // Generate the new header
         let header =
         let header =
-            Header::new(previous.block.hash()?, next_block_height, Timestamp::current_time(), 0);
+            Header::new(previous.block.hash(), next_block_height, Timestamp::current_time(), 0);
 
 
         // Generate the block
         // Generate the block
         let mut block = BlockInfo::new_empty(header);
         let mut block = BlockInfo::new_empty(header);
@@ -532,10 +532,10 @@ impl Fork {
         let mut block = self.generate_unsigned_block(producer_tx).await?;
         let mut block = self.generate_unsigned_block(producer_tx).await?;
 
 
         // Sign block
         // Sign block
-        block.sign(secret_key)?;
+        block.sign(secret_key);
 
 
         // Generate the block proposal from the block
         // Generate the block proposal from the block
-        let proposal = Proposal::new(block)?;
+        let proposal = Proposal::new(block);
 
 
         Ok(proposal)
         Ok(proposal)
     }
     }
@@ -546,7 +546,7 @@ impl Fork {
         let (next_target, next_difficulty) = self.module.next_mine_target_and_difficulty()?;
         let (next_target, next_difficulty) = self.module.next_mine_target_and_difficulty()?;
 
 
         // Calculate block rank
         // Calculate block rank
-        let (target_distance_sq, hash_distance_sq) = block_rank(&proposal.block, &next_target)?;
+        let (target_distance_sq, hash_distance_sq) = block_rank(&proposal.block, &next_target);
 
 
         // Update fork ranks
         // Update fork ranks
         self.targets_rank += target_distance_sq.clone();
         self.targets_rank += target_distance_sq.clone();
@@ -588,7 +588,7 @@ impl Fork {
                 .clone()
                 .clone()
         };
         };
 
 
-        Proposal::new(block)
+        Ok(Proposal::new(block))
     }
     }
 
 
     /// Auxiliary function to compute forks' next block height.
     /// Auxiliary function to compute forks' next block height.
@@ -620,7 +620,7 @@ impl Fork {
             }
             }
 
 
             // Push the tx hash into the unproposed transactions vector
             // Push the tx hash into the unproposed transactions vector
-            unproposed_txs.push(tx.clone());
+            unproposed_txs.push(*tx);
 
 
             // Check limit
             // Check limit
             if unproposed_txs.len() == TXS_CAP {
             if unproposed_txs.len() == TXS_CAP {

+ 5 - 5
src/validator/mod.rs

@@ -138,7 +138,7 @@ impl Validator {
 
 
         if tx_in_txstore || tx_in_pending_txs_store {
         if tx_in_txstore || tx_in_pending_txs_store {
             info!(target: "validator::append_tx", "We have already seen this tx");
             info!(target: "validator::append_tx", "We have already seen this tx");
-            return Err(TxVerifyFailed::AlreadySeenTx(tx_hash.to_string()).into())
+            return Err(TxVerifyFailed::AlreadySeenTx(tx_hash.as_string()).into())
         }
         }
 
 
         // Verify state transition
         // Verify state transition
@@ -177,7 +177,7 @@ impl Validator {
 
 
             // Store transaction hash in forks' mempool
             // Store transaction hash in forks' mempool
             if write {
             if write {
-                fork.mempool.push(tx_hash.clone());
+                fork.mempool.push(tx_hash);
             }
             }
         }
         }
 
 
@@ -426,14 +426,14 @@ impl Validator {
             if verify_block(&overlay, &module, block, previous).await.is_err() {
             if verify_block(&overlay, &module, block, previous).await.is_err() {
                 error!(target: "validator::add_blocks", "Erroneous block found in set");
                 error!(target: "validator::add_blocks", "Erroneous block found in set");
                 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
                 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
-                return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+                return Err(Error::BlockIsInvalid(block.hash().as_string()))
             };
             };
 
 
             // Grab next mine target and difficulty
             // Grab next mine target and difficulty
             let (next_target, next_difficulty) = module.next_mine_target_and_difficulty()?;
             let (next_target, next_difficulty) = module.next_mine_target_and_difficulty()?;
 
 
             // Calculate block rank
             // Calculate block rank
-            let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target)?;
+            let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target);
 
 
             // Update current ranks
             // Update current ranks
             current_targets_rank += target_distance_sq.clone();
             current_targets_rank += target_distance_sq.clone();
@@ -611,7 +611,7 @@ impl Validator {
             if verify_block(&overlay, &module, block, previous).await.is_err() {
             if verify_block(&overlay, &module, block, previous).await.is_err() {
                 error!(target: "validator::validate_blockchain", "Erroneous block found in set");
                 error!(target: "validator::validate_blockchain", "Erroneous block found in set");
                 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
                 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
-                return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+                return Err(Error::BlockIsInvalid(block.hash().as_string()))
             };
             };
 
 
             // Update PoW module
             // Update PoW module

+ 7 - 7
src/validator/pow.rs

@@ -252,13 +252,13 @@ impl PoWModule {
 
 
         // Setup verifier
         // Setup verifier
         let flags = RandomXFlags::default();
         let flags = RandomXFlags::default();
-        let cache = RandomXCache::new(flags, block.header.previous.as_bytes()).unwrap();
+        let cache = RandomXCache::new(flags, block.header.previous.inner()).unwrap();
         let vm = RandomXVM::new(flags, &cache).unwrap();
         let vm = RandomXVM::new(flags, &cache).unwrap();
         debug!(target: "validator::pow::verify_block", "[VERIFIER] Setup time: {:?}", verifier_setup.elapsed());
         debug!(target: "validator::pow::verify_block", "[VERIFIER] Setup time: {:?}", verifier_setup.elapsed());
 
 
         // Compute the output hash
         // Compute the output hash
         let verification_time = Instant::now();
         let verification_time = Instant::now();
-        let out_hash = vm.hash(block.hash()?.as_bytes());
+        let out_hash = vm.hash(block.hash().inner());
         let out_hash = BigUint::from_bytes_be(&out_hash);
         let out_hash = BigUint::from_bytes_be(&out_hash);
 
 
         // Verify hash is less than the expected mine target
         // Verify hash is less than the expected mine target
@@ -324,10 +324,10 @@ pub fn mine_block(
     debug!(target: "validator::pow::mine_block", "[MINER] Mine target: 0x{:064x}", target);
     debug!(target: "validator::pow::mine_block", "[MINER] Mine target: 0x{:064x}", target);
     // Get the PoW input. The key changes with every mined block.
     // Get the PoW input. The key changes with every mined block.
     let input = miner_block.header.previous;
     let input = miner_block.header.previous;
-    debug!(target: "validator::pow::mine_block", "[MINER] PoW input: {}", input.to_hex());
+    debug!(target: "validator::pow::mine_block", "[MINER] PoW input: {}", input);
     let flags = RandomXFlags::default() | RandomXFlags::FULLMEM;
     let flags = RandomXFlags::default() | RandomXFlags::FULLMEM;
     debug!(target: "validator::pow::mine_block", "[MINER] Initializing RandomX dataset...");
     debug!(target: "validator::pow::mine_block", "[MINER] Initializing RandomX dataset...");
-    let dataset = Arc::new(RandomXDataset::new(flags, input.as_bytes(), threads).unwrap());
+    let dataset = Arc::new(RandomXDataset::new(flags, input.inner(), threads).unwrap());
     debug!(target: "validator::pow::mine_block", "[MINER] Setup time: {:?}", miner_setup.elapsed());
     debug!(target: "validator::pow::mine_block", "[MINER] Setup time: {:?}", miner_setup.elapsed());
 
 
     // Multithreaded mining setup
     // Multithreaded mining setup
@@ -361,7 +361,7 @@ pub fn mine_block(
                     break
                     break
                 }
                 }
 
 
-                let out_hash = vm.hash(block.hash().unwrap().as_bytes());
+                let out_hash = vm.hash(block.hash().inner());
                 let out_hash = BigUint::from_bytes_be(&out_hash);
                 let out_hash = BigUint::from_bytes_be(&out_hash);
                 if out_hash <= target {
                 if out_hash <= target {
                     found_block.store(true, Ordering::SeqCst);
                     found_block.store(true, Ordering::SeqCst);
@@ -369,7 +369,7 @@ pub fn mine_block(
                     debug!(target: "validator::pow::mine_block", "[MINER] Thread #{} found block using nonce {}",
                     debug!(target: "validator::pow::mine_block", "[MINER] Thread #{} found block using nonce {}",
                         t, miner_nonce
                         t, miner_nonce
                     );
                     );
-                    debug!(target: "validator::pow::mine_block", "[MINER] Block hash {}", block.hash().unwrap().to_hex());
+                    debug!(target: "validator::pow::mine_block", "[MINER] Block hash {}", block.hash());
                     debug!(target: "validator::pow::mine_block", "[MINER] RandomX output: 0x{:064x}", out_hash);
                     debug!(target: "validator::pow::mine_block", "[MINER] RandomX output: 0x{:064x}", out_hash);
                     break
                     break
                 }
                 }
@@ -460,7 +460,7 @@ mod tests {
 
 
         // Mine next block
         // Mine next block
         let mut next_block = BlockInfo::default();
         let mut next_block = BlockInfo::default();
-        next_block.header.previous = genesis_block.hash()?;
+        next_block.header.previous = genesis_block.hash();
         module.mine_block(&mut next_block, DEFAULT_TEST_THREADS, &recvr)?;
         module.mine_block(&mut next_block, DEFAULT_TEST_THREADS, &recvr)?;
 
 
         // Verify it
         // Verify it

+ 5 - 5
src/validator/utils.rs

@@ -107,10 +107,10 @@ pub async fn deploy_native_contracts(overlay: &BlockchainOverlayPtr) -> Result<(
 /// Block's rank is the tuple of its squared mining target distance from max 32 bytes int,
 /// Block's rank is the tuple of its squared mining target distance from max 32 bytes int,
 /// along with its squared RandomX hash number distance from max 32 bytes int.
 /// along with its squared RandomX hash number distance from max 32 bytes int.
 /// Genesis block has rank (0, 0).
 /// Genesis block has rank (0, 0).
-pub fn block_rank(block: &BlockInfo, target: &BigUint) -> Result<(BigUint, BigUint)> {
+pub fn block_rank(block: &BlockInfo, target: &BigUint) -> (BigUint, BigUint) {
     // Genesis block has rank 0
     // Genesis block has rank 0
     if block.header.height == 0 {
     if block.header.height == 0 {
-        return Ok((0u64.into(), 0u64.into()))
+        return (0u64.into(), 0u64.into())
     }
     }
 
 
     // Grab the max 32 bytes int
     // Grab the max 32 bytes int
@@ -122,16 +122,16 @@ pub fn block_rank(block: &BlockInfo, target: &BigUint) -> Result<(BigUint, BigUi
 
 
     // Setup RandomX verifier
     // Setup RandomX verifier
     let flags = RandomXFlags::default();
     let flags = RandomXFlags::default();
-    let cache = RandomXCache::new(flags, block.header.previous.as_bytes()).unwrap();
+    let cache = RandomXCache::new(flags, block.header.previous.inner()).unwrap();
     let vm = RandomXVM::new(flags, &cache).unwrap();
     let vm = RandomXVM::new(flags, &cache).unwrap();
 
 
     // Compute the output hash distance
     // Compute the output hash distance
-    let out_hash = vm.hash(block.hash()?.as_bytes());
+    let out_hash = vm.hash(block.hash().inner());
     let out_hash = BigUint::from_bytes_be(&out_hash);
     let out_hash = BigUint::from_bytes_be(&out_hash);
     let hash_distance = max - out_hash;
     let hash_distance = max - out_hash;
     let hash_distance_sq = &hash_distance * &hash_distance;
     let hash_distance_sq = &hash_distance * &hash_distance;
 
 
-    Ok((target_distance_sq, hash_distance_sq))
+    (target_distance_sq, hash_distance_sq)
 }
 }
 
 
 /// Auxiliary function to calculate the middle value between provided u64 numbers
 /// Auxiliary function to calculate the middle value between provided u64 numbers

+ 16 - 17
src/validator/verification.rs

@@ -51,7 +51,7 @@ use crate::{
 
 
 /// Verify given genesis [`BlockInfo`], and apply it to the provided overlay
 /// Verify given genesis [`BlockInfo`], and apply it to the provided overlay
 pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockInfo) -> Result<()> {
 pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockInfo) -> Result<()> {
-    let block_hash = block.hash()?.to_string();
+    let block_hash = block.hash().as_string();
     debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {}", block_hash);
     debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {}", block_hash);
 
 
     // Check if block already exists
     // Check if block already exists
@@ -117,23 +117,22 @@ pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockI
 pub fn validate_block(block: &BlockInfo, previous: &BlockInfo, module: &PoWModule) -> Result<()> {
 pub fn validate_block(block: &BlockInfo, previous: &BlockInfo, module: &PoWModule) -> Result<()> {
     // Check block version (1)
     // Check block version (1)
     if block.header.version != block_version(block.header.height) {
     if block.header.version != block_version(block.header.height) {
-        return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+        return Err(Error::BlockIsInvalid(block.hash().as_string()))
     }
     }
 
 
     // Check previous hash (2)
     // Check previous hash (2)
-    let previous_hash = previous.hash()?;
-    if block.header.previous != previous_hash {
-        return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+    if block.header.previous != previous.hash() {
+        return Err(Error::BlockIsInvalid(block.hash().as_string()))
     }
     }
 
 
     // Check heights are incremental (3)
     // Check heights are incremental (3)
     if block.header.height != previous.header.height + 1 {
     if block.header.height != previous.header.height + 1 {
-        return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+        return Err(Error::BlockIsInvalid(block.hash().as_string()))
     }
     }
 
 
     // Check timestamp validity (4)
     // Check timestamp validity (4)
     if !module.verify_timestamp_by_median(block.header.timestamp) {
     if !module.verify_timestamp_by_median(block.header.timestamp) {
-        return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
+        return Err(Error::BlockIsInvalid(block.hash().as_string()))
     }
     }
 
 
     // Check block hash corresponds to next one (5)
     // Check block hash corresponds to next one (5)
@@ -172,12 +171,12 @@ pub async fn verify_block(
     block: &BlockInfo,
     block: &BlockInfo,
     previous: &BlockInfo,
     previous: &BlockInfo,
 ) -> Result<()> {
 ) -> Result<()> {
-    let block_hash = block.hash()?.to_string();
+    let block_hash = block.hash();
     debug!(target: "validator::verification::verify_block", "Validating block {}", block_hash);
     debug!(target: "validator::verification::verify_block", "Validating block {}", block_hash);
 
 
     // Check if block already exists
     // Check if block already exists
     if overlay.lock().unwrap().has_block(block)? {
     if overlay.lock().unwrap().has_block(block)? {
-        return Err(Error::BlockAlreadyExists(block_hash))
+        return Err(Error::BlockAlreadyExists(block_hash.as_string()))
     }
     }
 
 
     // Validate block, using its previous
     // Validate block, using its previous
@@ -185,7 +184,7 @@ pub async fn verify_block(
 
 
     // Verify transactions vector contains at least one(producers) transaction
     // Verify transactions vector contains at least one(producers) transaction
     if block.txs.is_empty() {
     if block.txs.is_empty() {
-        return Err(Error::BlockContainsNoTransactions(block_hash))
+        return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
     }
     }
 
 
     // Verify transactions, exluding producer(last) one
     // Verify transactions, exluding producer(last) one
@@ -214,7 +213,7 @@ pub async fn verify_block(
     // Verify tree matches header one
     // Verify tree matches header one
     if tree != block.header.tree {
     if tree != block.header.tree {
         error!(target: "validator::verification::verify_block", "Block Merkle tree is invalid");
         error!(target: "validator::verification::verify_block", "Block Merkle tree is invalid");
-        return Err(Error::BlockIsInvalid(block_hash))
+        return Err(Error::BlockIsInvalid(block_hash.as_string()))
     }
     }
 
 
     // Insert block
     // Insert block
@@ -227,7 +226,7 @@ pub async fn verify_block(
 /// Verify block proposer signature, using the proposal transaction signature as signing key
 /// Verify block proposer signature, using the proposal transaction signature as signing key
 /// over blocks header hash.
 /// over blocks header hash.
 pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> Result<()> {
 pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> Result<()> {
-    if !public_key.verify(&block.header.hash()?.as_bytes()[..], &block.signature) {
+    if !public_key.verify(block.header.hash().inner(), &block.signature) {
         warn!(target: "validator::verification::verify_producer_signature", "Proposer {} signature could not be verified", public_key);
         warn!(target: "validator::verification::verify_producer_signature", "Proposer {} signature could not be verified", public_key);
         return Err(Error::InvalidSignature)
         return Err(Error::InvalidSignature)
     }
     }
@@ -284,7 +283,7 @@ pub async fn verify_producer_transaction(
         overlay.clone(),
         overlay.clone(),
         call.data.contract_id,
         call.data.contract_id,
         verifying_block_height,
         verifying_block_height,
-        tx_hash.clone(),
+        tx_hash,
         // Call index in producer tx is 0
         // Call index in producer tx is 0
         0,
         0,
     )?;
     )?;
@@ -452,7 +451,7 @@ pub async fn verify_transaction(
             overlay.clone(),
             overlay.clone(),
             call.data.contract_id,
             call.data.contract_id,
             verifying_block_height,
             verifying_block_height,
-            tx_hash.clone(),
+            tx_hash,
             idx as u32,
             idx as u32,
         )?;
         )?;
 
 
@@ -527,7 +526,7 @@ pub async fn verify_transaction(
                 overlay.clone(),
                 overlay.clone(),
                 deploy_cid,
                 deploy_cid,
                 verifying_block_height,
                 verifying_block_height,
-                tx_hash.clone(),
+                tx_hash,
                 idx as u32,
                 idx as u32,
             )?;
             )?;
 
 
@@ -680,7 +679,7 @@ pub async fn verify_proposal(
     proposal: &Proposal,
     proposal: &Proposal,
 ) -> Result<(Fork, Option<usize>)> {
 ) -> Result<(Fork, Option<usize>)> {
     // Check if proposal hash matches actual one (1)
     // Check if proposal hash matches actual one (1)
-    let proposal_hash = proposal.block.hash()?;
+    let proposal_hash = proposal.block.hash();
     if proposal.hash != proposal_hash {
     if proposal.hash != proposal_hash {
         warn!(
         warn!(
             target: "validator::verification::verify_pow_proposal", "Received proposal contains mismatched hashes: {} - {}",
             target: "validator::verification::verify_pow_proposal", "Received proposal contains mismatched hashes: {} - {}",
@@ -709,7 +708,7 @@ pub async fn verify_proposal(
     if verify_block(&fork.overlay, &fork.module, &proposal.block, &previous).await.is_err() {
     if verify_block(&fork.overlay, &fork.module, &proposal.block, &previous).await.is_err() {
         error!(target: "validator::verification::verify_pow_proposal", "Erroneous proposal block found");
         error!(target: "validator::verification::verify_pow_proposal", "Erroneous proposal block found");
         fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
         fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
-        return Err(Error::BlockIsInvalid(proposal.hash.to_string()))
+        return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
     };
     };
 
 
     Ok((fork, index))
     Ok((fork, index))