Преглед изворни кода

tx: change tx.hash() -> Result<blake3::Hash> to tx.hash() -> TransactionHash, by calling .unwrap() on blake3 hasher. This should be safe (see code comment in tx/mod.rs:188 inside fn hash() )

zero пре 2 година
родитељ
комит
5c9e3bd4a1

+ 3 - 3
bin/darkfid/src/rpc_tx.rs

@@ -139,7 +139,7 @@ impl Darkfid {
             return server_error(RpcError::TxBroadcastFail, id, None)
         }
 
-        let tx_hash = tx.hash().unwrap().to_string();
+        let tx_hash = tx.hash().to_string();
         JsonResponse::new(JsonValue::String(tx_hash), id).into()
     }
 
@@ -169,7 +169,7 @@ impl Darkfid {
         };
 
         let pending_txs: Vec<JsonValue> =
-            pending_txs.iter().map(|x| JsonValue::String(x.hash().unwrap().to_string())).collect();
+            pending_txs.iter().map(|x| JsonValue::String(x.hash().to_string())).collect();
 
         JsonResponse::new(JsonValue::Array(pending_txs), id).into()
     }
@@ -205,7 +205,7 @@ impl Darkfid {
         };
 
         let pending_txs: Vec<JsonValue> =
-            pending_txs.iter().map(|x| JsonValue::String(x.hash().unwrap().to_string())).collect();
+            pending_txs.iter().map(|x| JsonValue::String(x.hash().to_string())).collect();
 
         JsonResponse::new(JsonValue::Array(pending_txs), id).into()
     }

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

@@ -70,7 +70,7 @@ impl Harness {
         let producer_tx = genesis_block.txs.pop().unwrap();
 
         // Append it again so its added to the merkle tree
-        genesis_block.append_txs(vec![producer_tx])?;
+        genesis_block.append_txs(vec![producer_tx]);
 
         // Generate validators configuration
         // NOTE: we are not using consensus constants here so we
@@ -209,7 +209,7 @@ impl Harness {
         let mut block = BlockInfo::new_empty(header);
 
         // Add producer transaction to the block
-        block.append_txs(vec![tx])?;
+        block.append_txs(vec![tx]);
 
         // Attach signature
         block.sign(&keypair.secret)?;

+ 4 - 3
bin/drk/src/main.rs

@@ -47,6 +47,7 @@ use darkfi_money_contract::model::{Coin, TokenId};
 use darkfi_sdk::{
     crypto::{FuncId, PublicKey, SecretKey},
     pasta::{group::ff::PrimeField, pallas},
+    tx::TransactionHash,
 };
 use darkfi_serial::{deserialize_async, serialize_async};
 
@@ -1303,7 +1304,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
         Subcmd::Explorer { command } => match command {
             ExplorerSubcmd::FetchTx { tx_hash, full, encode } => {
-                let tx_hash = blake3::Hash::from_hex(&tx_hash)?;
+                let tx_hash = TransactionHash(*blake3::Hash::from_hex(&tx_hash)?.as_bytes());
 
                 let drk =
                     Drk::new(args.wallet_path, args.wallet_pass, args.endpoint.clone(), ex.clone())
@@ -1323,7 +1324,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 // Make sure the tx is correct
-                assert_eq!(tx.hash()?, tx_hash);
+                assert_eq!(tx.hash(), tx_hash);
 
                 if encode {
                     println!("{}", base64::encode(&serialize_async(&tx).await));
@@ -1361,7 +1362,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                     }
                 };
 
-                println!("Transaction ID: {}", tx.hash()?);
+                println!("Transaction ID: {}", tx.hash());
                 println!("State: {}", if is_valid { "valid" } else { "invalid" });
 
                 Ok(())

+ 3 - 3
bin/drk/src/rpc.rs

@@ -32,7 +32,7 @@ use darkfi::{
     util::encoding::base64,
     Error, Result,
 };
-use darkfi_sdk::crypto::ContractId;
+use darkfi_sdk::{crypto::ContractId, tx::TransactionHash};
 use darkfi_serial::{deserialize_async, serialize_async};
 
 use crate::{
@@ -304,8 +304,8 @@ impl Drk {
     }
 
     /// Queries darkfid for a tx with given hash
-    pub async fn get_tx(&self, tx_hash: &blake3::Hash) -> Result<Option<Transaction>> {
-        let tx_hash_str = tx_hash.to_hex().to_string();
+    pub async fn get_tx(&self, tx_hash: &TransactionHash) -> Result<Option<Transaction>> {
+        let tx_hash_str = tx_hash.to_string();
         let req = JsonRequest::new(
             "blockchain.get_tx",
             JsonValue::Array(vec![JsonValue::String(tx_hash_str)]),

+ 2 - 2
bin/drk/src/txs_history.rs

@@ -49,7 +49,7 @@ impl Drk {
             WALLET_TXS_HISTORY_COL_STATUS,
             WALLET_TXS_HISTORY_COL_TX,
         );
-        let Ok(tx_hash) = tx.hash() else { return Err(WalletDbError::QueryPreparationFailed) };
+        let tx_hash = tx.hash();
         self.wallet
             .exec_sql(
                 &query,
@@ -169,7 +169,7 @@ impl Drk {
 
         let mut txs_hashes = Vec::with_capacity(txs.len());
         for tx in txs {
-            let Ok(tx_hash) = tx.hash() else { return Err(WalletDbError::QueryPreparationFailed) };
+            let tx_hash = tx.hash();
             txs_hashes.push(format!("{tx_hash}"));
         }
         let txs_hashes_string = format!("{:?}", txs_hashes).replace('[', "(").replace(']', ")");

+ 6 - 11
src/blockchain/block_store.rs

@@ -117,21 +117,17 @@ impl BlockInfo {
     }
 
     /// Append a transaction to the block. Also adds it to the Merkle tree.
-    pub fn append_tx(&mut self, tx: Transaction) -> Result<()> {
-        append_tx_to_merkle_tree(&mut self.header.tree, &tx)?;
+    pub fn append_tx(&mut self, tx: Transaction) {
+        append_tx_to_merkle_tree(&mut self.header.tree, &tx);
         self.txs.push(tx);
-
-        Ok(())
     }
 
     /// Append a vector of transactions to the block. Also adds them to the
     /// Merkle tree.
-    pub fn append_txs(&mut self, txs: Vec<Transaction>) -> Result<()> {
+    pub fn append_txs(&mut self, txs: Vec<Transaction>) {
         for tx in txs {
-            self.append_tx(tx)?;
+            self.append_tx(tx);
         }
-
-        Ok(())
     }
 
     /// Sign block header using provided secret key
@@ -739,10 +735,9 @@ impl BlockDifficultyStoreOverlay {
 }
 
 /// Auxiliary function to append a transaction to a Merkle tree.
-pub fn append_tx_to_merkle_tree(tree: &mut MerkleTree, tx: &Transaction) -> Result<()> {
+pub fn append_tx_to_merkle_tree(tree: &mut MerkleTree, tx: &Transaction) {
     let mut buf = [0u8; 64];
-    buf[..blake3::OUT_LEN].copy_from_slice(tx.hash()?.as_bytes());
+    buf[..blake3::OUT_LEN].copy_from_slice(tx.hash().inner());
     let leaf = pallas::Base::from_uniform_bytes(&buf);
     tree.append(leaf.into());
-    Ok(())
 }

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

@@ -222,7 +222,7 @@ impl TestHarness {
         let mut genesis_block = BlockInfo::default();
         genesis_block.header.timestamp = Timestamp::from_u64(1689772567);
         let producer_tx = genesis_block.txs.pop().unwrap();
-        genesis_block.append_txs(vec![producer_tx])?;
+        genesis_block.append_txs(vec![producer_tx]);
 
         // Deterministic PRNG
         let mut rng = Pcg32::new(42);
@@ -312,7 +312,7 @@ fn benchmark_wasm_calls(
             file,
             "{}, {}, {}, {}, {}, {}",
             callname,
-            tx.hash().unwrap(),
+            tx.hash(),
             idx,
             times[0],
             times[1],

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

@@ -123,7 +123,7 @@ impl TestHarness {
         let mut block = BlockInfo::new_empty(header);
 
         // Add producer transaction to the block
-        block.append_txs(vec![tx])?;
+        block.append_txs(vec![tx]);
 
         // Attach signature
         block.sign(&wallet.keypair.secret)?;

+ 1 - 1
src/runtime/vm_runtime.rs

@@ -21,7 +21,7 @@ use std::{
     sync::Arc,
 };
 
-use darkfi_sdk::{crypto::ContractId, entrypoint};
+use darkfi_sdk::{crypto::ContractId, entrypoint, tx::TransactionHash};
 use darkfi_serial::serialize;
 use log::{debug, error, info};
 use wasmer::{

+ 26 - 0
src/sdk/src/tx.rs

@@ -16,12 +16,38 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use std::fmt::{self, Debug};
+
 #[cfg(feature = "async")]
 use darkfi_serial::async_trait;
 use darkfi_serial::{SerialDecodable, SerialEncodable};
 
 use super::crypto::ContractId;
 
+#[derive(Clone, Debug, PartialEq)]
+// We have to introduce a type rather than using an alias so we can implement Display
+pub struct TransactionHash(pub [u8; 32]);
+
+impl TransactionHash {
+    pub fn new(data: [u8; 32]) -> Self {
+        Self(data)
+    }
+
+    pub fn none() -> Self {
+        Self([0; 32])
+    }
+
+    pub fn inner(&self) -> &[u8; 32] {
+        &self.0
+    }
+}
+
+impl fmt::Display for TransactionHash {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        self.0[..].fmt(formatter)
+    }
+}
+
 // ANCHOR: contractcall
 /// A ContractCall is the part of a transaction that executes a certain
 /// `contract_id` with `data` as the call's payload.

+ 7 - 4
src/tx/mod.rs

@@ -26,7 +26,7 @@ use darkfi_sdk::{
     dark_tree::{dark_forest_leaf_vec_integrity_check, DarkForest, DarkLeaf, DarkTree},
     error::DarkTreeResult,
     pasta::pallas,
-    tx::ContractCall,
+    tx::{ContractCall, TransactionHash},
 };
 
 #[cfg(feature = "async-serial")]
@@ -183,10 +183,13 @@ impl Transaction {
     }
 
     /// Get the transaction hash
-    pub fn hash(&self) -> Result<blake3::Hash> {
+    pub fn hash(&self) -> TransactionHash {
         let mut hasher = blake3::Hasher::new();
-        self.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.encode(&mut hasher).expect("blake3 hasher");
+        TransactionHash(hasher.finalize().into())
     }
 }
 

+ 1 - 1
src/validator/consensus.rs

@@ -514,7 +514,7 @@ impl Fork {
         let mut block = BlockInfo::new_empty(header);
 
         // Add transactions to the block
-        block.append_txs(unproposed_txs)?;
+        block.append_txs(unproposed_txs);
 
         Ok(block)
     }

+ 4 - 1
src/validator/utils.rs

@@ -16,7 +16,10 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use darkfi_sdk::crypto::{DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID};
+use darkfi_sdk::{
+    crypto::{DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID},
+    tx::TransactionHash,
+};
 use log::info;
 use num_bigint::BigUint;
 use randomx::{RandomXCache, RandomXFlags, RandomXVM};

+ 6 - 5
src/validator/verification.rs

@@ -96,7 +96,7 @@ pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockI
     }
 
     // Append producer transaction to the tree and check tree matches header one
-    append_tx_to_merkle_tree(&mut tree, producer_tx)?;
+    append_tx_to_merkle_tree(&mut tree, producer_tx);
     if tree != block.header.tree {
         error!(target: "validator::verification::verify_genesis_block", "Genesis Merkle tree is invalid");
         return Err(Error::BlockIsInvalid(block_hash))
@@ -246,7 +246,7 @@ pub async fn verify_producer_transaction(
     tx: &Transaction,
     tree: &mut MerkleTree,
 ) -> Result<PublicKey> {
-    let tx_hash = tx.hash()?;
+    let tx_hash = tx.hash();
     debug!(target: "validator::verification::verify_producer_transaction", "Validating proposal transaction {}", tx_hash);
 
     // Producer transactions must contain a single, non-empty call
@@ -360,7 +360,7 @@ pub async fn verify_producer_transaction(
     debug!(target: "validator::verification::verify_producer_transaction", "ZK proof verification successful");
 
     // Append hash to merkle tree
-    append_tx_to_merkle_tree(tree, tx)?;
+    append_tx_to_merkle_tree(tree, tx);
 
     debug!(target: "validator::verification::verify_producer_transaction", "Proposal transaction {} verified successfully", tx_hash);
 
@@ -378,7 +378,7 @@ pub async fn verify_transaction(
     verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
     verify_fee: bool,
 ) -> Result<u64> {
-    let tx_hash = tx.hash()?;
+    let tx_hash = tx.hash();
     debug!(target: "validator::verification::verify_transaction", "Validating transaction {}", tx_hash);
 
     // Gas accumulator
@@ -518,6 +518,7 @@ pub async fn verify_transaction(
                 overlay.clone(),
                 deploy_cid,
                 verifying_block_height,
+                tx_hash.clone(),
             )?;
 
             deploy_runtime.deploy(&deploy_params.ix)?;
@@ -598,7 +599,7 @@ pub async fn verify_transaction(
     debug!(target: "validator::verification::verify_transaction", "ZK proof verification successful");
 
     // Append hash to merkle tree
-    append_tx_to_merkle_tree(tree, tx)?;
+    append_tx_to_merkle_tree(tree, tx);
 
     debug!(target: "validator::verification::verify_transaction", "Transaction {} verified successfully", tx_hash);
     Ok(gas_used)