Jelajahi Sumber

tx: use DarkLeaf<ContractCall> in tx calls vec

aggstam 2 tahun lalu
induk
melakukan
bd86ce5678
3 mengubah file dengan 39 tambahan dan 29 penghapusan
  1. 15 9
      src/tx/mod.rs
  2. 6 5
      src/validator/utils.rs
  3. 18 15
      src/validator/verification.rs

+ 15 - 9
src/tx/mod.rs

@@ -23,7 +23,7 @@ use darkfi_sdk::{
         schnorr::{SchnorrPublic, SchnorrSecret, Signature},
         PublicKey, SecretKey,
     },
-    dark_tree::{dark_leaf_vec_integrity_check, DarkTree},
+    dark_tree::{dark_leaf_vec_integrity_check, DarkLeaf, DarkTree},
     error::DarkTreeResult,
     pasta::pallas,
     tx::ContractCall,
@@ -51,11 +51,12 @@ macro_rules! zip {
 
 // ANCHOR: transaction
 /// A Transaction contains an arbitrary number of `ContractCall` objects,
-/// along with corresponding ZK proofs and Schnorr signatures.
+/// along with corresponding ZK proofs and Schnorr signatures. `DarkLeaf`
+/// is used to map relations between contract calls in the transaciton.
 #[derive(Debug, Clone, Default, Eq, PartialEq, SerialEncodable, SerialDecodable)]
 pub struct Transaction {
     /// Calls executed in this transaction
-    pub calls: Vec<ContractCall>,
+    pub calls: Vec<DarkLeaf<ContractCall>>,
     /// Attached ZK proofs
     pub proofs: Vec<Vec<Proof>>,
     /// Attached Schnorr signatures
@@ -77,8 +78,8 @@ impl Transaction {
         for (call, (proofs, pubvals)) in zip!(self.calls, self.proofs, zkp_table) {
             assert_eq!(proofs.len(), pubvals.len());
 
-            let Some(contract_map) = verifying_keys.get(&call.contract_id.to_bytes()) else {
-                error!("Verifying keys not found for contract {}", call.contract_id);
+            let Some(contract_map) = verifying_keys.get(&call.data.contract_id.to_bytes()) else {
+                error!("Verifying keys not found for contract {}", call.data.contract_id);
                 return Err(TxVerifyFailed::InvalidZkProof.into())
             };
 
@@ -90,15 +91,15 @@ impl Transaction {
                         error!(
                             target: "",
                             "Failed verifying {}::{} ZK proof: {:#?}",
-                            call.contract_id, zk_ns, e
+                            call.data.contract_id, zk_ns, e
                         );
                         return Err(TxVerifyFailed::InvalidZkProof.into())
                     }
-                    debug!("Successfully verified {}::{} ZK proof", call.contract_id, zk_ns);
+                    debug!("Successfully verified {}::{} ZK proof", call.data.contract_id, zk_ns);
                     continue
                 }
 
-                let e = format!("{}:{} circuit VK nonexistent", call.contract_id, zk_ns);
+                let e = format!("{}:{} circuit VK nonexistent", call.data.contract_id, zk_ns);
                 error!("{}", e);
                 return Err(TxVerifyFailed::InvalidZkProof.into())
             }
@@ -225,7 +226,12 @@ impl TransactionBuilder {
         let mut proofs = Vec::with_capacity(leafs.len());
         let mut signatures = Vec::with_capacity(leafs.len());
         for leaf in leafs {
-            calls.push(leaf.data.call);
+            let call = DarkLeaf {
+                data: leaf.data.call,
+                parent_index: leaf.parent_index,
+                children_indexes: leaf.children_indexes,
+            };
+            calls.push(call);
             proofs.push(leaf.data.proofs);
             signatures.push(leaf.data.signatures);
         }

+ 6 - 5
src/validator/utils.rs

@@ -127,7 +127,7 @@ pub fn block_rank(
 
     // Extract VRF proof from the previous previous producer transaction
     let tx = previous_previous.txs.last().unwrap();
-    let data = &tx.calls[0].data;
+    let data = &tx.calls[0].data.data;
     let position = match previous_previous.header.version {
         // PoW uses MoneyPoWRewardParamsV1
         1 => 563,
@@ -194,11 +194,12 @@ pub fn genesis_txs_total(txs: &[Transaction]) -> Result<u64> {
             return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
         }
         let call = &tx.calls[0];
-        let data = &call.data;
+        let data = &call.data.data;
         let function = data[0];
-        if !(call.contract_id == *CONSENSUS_CONTRACT_ID || call.contract_id == *MONEY_CONTRACT_ID) ||
-            (call.contract_id == *CONSENSUS_CONTRACT_ID && function != 0x00_u8) ||
-            (call.contract_id == *MONEY_CONTRACT_ID && function != 0x01_u8)
+        if !(call.data.contract_id == *CONSENSUS_CONTRACT_ID ||
+            call.data.contract_id == *MONEY_CONTRACT_ID) ||
+            (call.data.contract_id == *CONSENSUS_CONTRACT_ID && function != 0x00_u8) ||
+            (call.data.contract_id == *MONEY_CONTRACT_ID && function != 0x01_u8)
         {
             return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
         }

+ 18 - 15
src/validator/verification.rs

@@ -206,7 +206,7 @@ pub async fn verify_producer_transaction(
     debug!(target: "validator::verification::verify_producer_transaction", "Validating proposal transaction {}", tx_hash);
 
     // Producer transactions must contain a single, non-empty call
-    if tx.calls.len() != 1 || tx.calls[0].data.is_empty() {
+    if tx.calls.len() != 1 || tx.calls[0].data.data.is_empty() {
         return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
     }
 
@@ -215,13 +215,13 @@ pub async fn verify_producer_transaction(
     match block_version {
         1 => {
             // Version 1 blocks must contain a Money::PoWReward(0x08) call
-            if call.contract_id != *MONEY_CONTRACT_ID || call.data[0] != 0x08 {
+            if call.data.contract_id != *MONEY_CONTRACT_ID || call.data.data[0] != 0x08 {
                 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
             }
         }
         2 => {
             // Version 2 blocks must contain a Consensus::Proposal(0x02) call
-            if call.contract_id != *CONSENSUS_CONTRACT_ID || call.data[0] != 0x02 {
+            if call.data.contract_id != *CONSENSUS_CONTRACT_ID || call.data.data[0] != 0x02 {
                 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
             }
         }
@@ -232,7 +232,7 @@ pub async fn verify_producer_transaction(
     let mut verifying_keys: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
 
     // Initialize the map
-    verifying_keys.insert(call.contract_id.to_bytes(), HashMap::new());
+    verifying_keys.insert(call.data.contract_id.to_bytes(), HashMap::new());
 
     // Table of public inputs used for ZK proof verification
     let mut zkp_table = vec![];
@@ -247,9 +247,10 @@ pub async fn verify_producer_transaction(
     tx.calls.encode(&mut payload)?; // Actual call data
 
     debug!(target: "validator::verification::verify_producer_transaction", "Instantiating WASM runtime");
-    let wasm = overlay.lock().unwrap().wasm_bincode.get(call.contract_id)?;
+    let wasm = overlay.lock().unwrap().wasm_bincode.get(call.data.contract_id)?;
 
-    let mut runtime = Runtime::new(&wasm, overlay.clone(), call.contract_id, time_keeper.clone())?;
+    let mut runtime =
+        Runtime::new(&wasm, overlay.clone(), call.data.contract_id, time_keeper.clone())?;
 
     debug!(target: "validator::verification::verify_producer_transaction", "Executing \"metadata\" call");
     let metadata = runtime.metadata(&payload)?;
@@ -274,11 +275,12 @@ pub async fn verify_producer_transaction(
     debug!(target: "validator::verification::verify_producer_transaction", "Performing VerifyingKey lookups from the sled db");
     for (zkas_ns, _) in &zkp_pub {
         // TODO: verify this is correct behavior
-        let inner_vk_map = verifying_keys.get_mut(&call.contract_id.to_bytes()).unwrap();
+        let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
         if inner_vk_map.contains_key(zkas_ns.as_str()) {
             continue
         }
-        let (_, vk) = overlay.lock().unwrap().contracts.get_zkas(&call.contract_id, zkas_ns)?;
+        let (_, vk) =
+            overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
         inner_vk_map.insert(zkas_ns.to_string(), vk);
     }
 
@@ -345,8 +347,8 @@ pub async fn verify_transaction(
     // Iterate over all calls to get the metadata
     for (idx, call) in tx.calls.iter().enumerate() {
         // Transaction must not contain a reward call, Money::PoWReward(0x08) or Consensus::Proposal(0x02)
-        if (call.contract_id == *MONEY_CONTRACT_ID && call.data[0] == 0x08) ||
-            (call.contract_id == *CONSENSUS_CONTRACT_ID && call.data[0] == 0x02)
+        if (call.data.contract_id == *MONEY_CONTRACT_ID && call.data.data[0] == 0x08) ||
+            (call.data.contract_id == *CONSENSUS_CONTRACT_ID && call.data.data[0] == 0x02)
         {
             error!(target: "validator::verification::verify_transaction", "Reward transaction detected");
             return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
@@ -360,10 +362,10 @@ pub async fn verify_transaction(
         tx.calls.encode(&mut payload)?; // Actual call data
 
         debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
-        let wasm = overlay.lock().unwrap().wasm_bincode.get(call.contract_id)?;
+        let wasm = overlay.lock().unwrap().wasm_bincode.get(call.data.contract_id)?;
 
         let mut runtime =
-            Runtime::new(&wasm, overlay.clone(), call.contract_id, time_keeper.clone())?;
+            Runtime::new(&wasm, overlay.clone(), call.data.contract_id, time_keeper.clone())?;
 
         debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
         let metadata = runtime.metadata(&payload)?;
@@ -380,7 +382,7 @@ pub async fn verify_transaction(
         // Here we'll look up verifying keys and insert them into the per-contract map.
         debug!(target: "validator::verification::verify_transaction", "Performing VerifyingKey lookups from the sled db");
         for (zkas_ns, _) in &zkp_pub {
-            let inner_vk_map = verifying_keys.get_mut(&call.contract_id.to_bytes()).unwrap();
+            let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
 
             // TODO: This will be a problem in case of ::deploy, unless we force a different
             // namespace and disable updating existing circuit. Might be a smart idea to do
@@ -389,7 +391,8 @@ pub async fn verify_transaction(
                 continue
             }
 
-            let (_, vk) = overlay.lock().unwrap().contracts.get_zkas(&call.contract_id, zkas_ns)?;
+            let (_, vk) =
+                overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
 
             inner_vk_map.insert(zkas_ns.to_string(), vk);
         }
@@ -461,7 +464,7 @@ pub async fn verify_transactions(
     // Initialize the map
     for tx in txs {
         for call in &tx.calls {
-            vks.insert(call.contract_id.to_bytes(), HashMap::new());
+            vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
         }
     }