Jelajahi Sumber

dao2: banish the wasm stuff to a single validate() function

x 3 tahun lalu
induk
melakukan
79ba8fc0ef
1 mengubah file dengan 85 tambahan dan 75 penghapusan
  1. 85 75
      example/dao2/src/main.rs

+ 85 - 75
example/dao2/src/main.rs

@@ -83,6 +83,81 @@ fn show_money_state(chain: &Blockchain, contract_id: &ContractId) -> Result<()>
 
 type BoxResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
 
+fn validate(
+    tx: &Transaction,
+    dao_wasm_bytes: &[u8],
+    dao_contract_id: ContractId,
+    money_wasm_bytes: &[u8],
+    money_contract_id: ContractId,
+    blockchain: &Blockchain,
+    zk_bins: &ZkContractTable,
+) -> Result<()> {
+    // ContractId is not Hashable so put them in a Vec and do linear scan
+    let wasm_bytes_lookup = vec![
+        (dao_contract_id, "DAO", dao_wasm_bytes),
+        (money_contract_id, "Money", money_wasm_bytes),
+    ];
+
+    // We can do all exec(), zk proof checks and signature verifies in parallel.
+    let mut updates = vec![];
+    let mut zkpublic_table = vec![];
+    let mut sigpub_table = vec![];
+    // Validate all function calls in the tx
+    for (idx, call) in tx.calls.iter().enumerate() {
+        // So then the verifier will lookup the corresponding state_transition and apply
+        // functions based off the func_id
+
+        // Write the actual payload data
+        let mut payload = Vec::new();
+        // Call index
+        payload.write_u32(idx as u32)?;
+        // Actuall calldata
+        tx.calls.encode(&mut payload)?;
+
+        // Lookup the wasm bytes
+        let (_, contract_name, wasm_bytes) =
+            wasm_bytes_lookup.iter().find(|(id, _name, _bytes)| *id == call.contract_id).unwrap();
+        debug!(target: "demo", "{}::exec() contract called", contract_name);
+
+        let mut runtime = Runtime::new(wasm_bytes, blockchain.clone(), call.contract_id)?;
+        let update = runtime.exec(&payload)?;
+        updates.push(update);
+
+        let metadata = runtime.metadata(&payload)?;
+        let mut decoder = Cursor::new(&metadata);
+        let zk_public_values: Vec<(String, Vec<pallas::Base>)> = Decodable::decode(&mut decoder)?;
+        let signature_public_keys: Vec<pallas::Point> = Decodable::decode(&mut decoder)?;
+
+        zkpublic_table.push(zk_public_values);
+        sigpub_table.push(signature_public_keys);
+    }
+
+    tx.zk_verify(&zk_bins, &zkpublic_table)?;
+    //tx.verify_sigs();
+
+    // Now we finished verification stage, just apply all changes
+    assert_eq!(tx.calls.len(), updates.len());
+    for (call, update) in tx.calls.iter().zip(updates.iter()) {
+        match call.contract_id {
+            dao_contract_id => {
+                debug!(target: "demo", "DAO::apply() contract called");
+                let mut runtime =
+                    Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?;
+                runtime.apply(&update)?;
+            }
+            money_contract_id => {
+                debug!(target: "demo", "Money::apply() contract called");
+                let mut runtime =
+                    Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?;
+                runtime.apply(&update)?;
+            }
+            _ => {}
+        }
+    }
+
+    Ok(())
+}
+
 #[async_std::main]
 async fn main() -> BoxResult<()> {
     // Debug log configuration
@@ -253,81 +328,16 @@ async fn main() -> BoxResult<()> {
 
     //// Validator
 
-    // We can do all exec(), zk proof checks and signature verifies in parallel.
-    let mut updates = vec![];
-    let mut zkpublic_table = vec![];
-    let mut sigpub_table = vec![];
-    // Validate all function calls in the tx
-    for (idx, call) in tx.calls.iter().enumerate() {
-        // So then the verifier will lookup the corresponding state_transition and apply
-        // functions based off the func_id
-
-        // Write the actual payload data
-        let mut payload = Vec::new();
-        // Call index
-        payload.write_u32(idx as u32)?;
-        // Actuall calldata
-        tx.calls.encode(&mut payload)?;
-
-        match call.contract_id {
-            dao_contract_id => {
-                debug!(target: "demo", "DAO::exec() contract called");
-                let mut runtime =
-                    Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?;
-                let update = runtime.exec(&payload)?;
-                updates.push(update);
-
-                let metadata = runtime.metadata(&payload)?;
-                let mut decoder = Cursor::new(&metadata);
-                let zk_public_values: Vec<(String, Vec<pallas::Base>)> =
-                    Decodable::decode(&mut decoder)?;
-                let signature_public_keys: Vec<pallas::Point> = Decodable::decode(&mut decoder)?;
-
-                zkpublic_table.push(zk_public_values);
-                sigpub_table.push(signature_public_keys);
-            }
-            money_contract_id => {
-                debug!(target: "demo", "Money::exec() contract called");
-                let mut runtime =
-                    Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?;
-                let update = runtime.exec(&payload)?;
-                updates.push(update);
-
-                let metadata = runtime.metadata(&payload)?;
-                let mut decoder = Cursor::new(&metadata);
-                let zk_public_values: Vec<(String, Vec<pallas::Base>)> =
-                    Decodable::decode(&mut decoder)?;
-                let signature_public_keys: Vec<pallas::Point> = Decodable::decode(&mut decoder)?;
-
-                zkpublic_table.push(zk_public_values);
-                sigpub_table.push(signature_public_keys);
-            }
-            _ => {}
-        }
-    }
-
-    tx.zk_verify(&zk_bins, &zkpublic_table)?;
-    //tx.verify_sigs();
-
-    // Now we finished verification stage, just apply all changes
-    assert_eq!(tx.calls.len(), updates.len());
-    for (call, update) in tx.calls.iter().zip(updates.iter()) {
-        match call.contract_id {
-            dao_contract_id => {
-                debug!(target: "demo", "DAO::apply() contract called");
-                let mut runtime =
-                    Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?;
-                runtime.apply(&update)?;
-            }
-            money_contract_id => {
-                debug!(target: "demo", "Money::apply() contract called");
-                let mut runtime =
-                    Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?;
-                runtime.apply(&update)?;
-            }
-            _ => {}
-        }
-    }
+    validate(
+        &tx,
+        &dao_wasm_bytes,
+        dao_contract_id,
+        &money_wasm_bytes,
+        money_contract_id,
+        &blockchain,
+        &zk_bins,
+    )
+    .expect("validate failed");
 
     /////////////////////////////////////////////////
     // Old stuff