Jelajahi Sumber

expand smart_contracts.md section

x 3 tahun lalu
induk
melakukan
7e0c87c34f
2 mengubah file dengan 43 tambahan dan 8 penghapusan
  1. 9 0
      bin/daod/src/demo.rs
  2. 34 8
      doc/src/architecture/smart_contracts.md

+ 9 - 0
bin/daod/src/demo.rs

@@ -111,10 +111,14 @@ impl ZkContractTable {
     }
     }
 }
 }
 
 
+// ANCHOR: transaction
 pub struct Transaction {
 pub struct Transaction {
     pub func_calls: Vec<FuncCall>,
     pub func_calls: Vec<FuncCall>,
+    // TODO: this is wrong. It should be Vec<Vec<Signature>>
+    // each Vec<Signature> correspond to ONE function call
     pub signatures: Vec<Signature>,
     pub signatures: Vec<Signature>,
 }
 }
+// ANCHOR_END: transaction
 
 
 impl Transaction {
 impl Transaction {
     /// Verify ZK contracts for the entire tx
     /// Verify ZK contracts for the entire tx
@@ -158,6 +162,7 @@ impl Transaction {
         {
         {
             func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
             func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
             let signature_pub_keys = func_call.call_data.signature_public_keys();
             let signature_pub_keys = func_call.call_data.signature_public_keys();
+            // TODO: Wrong must be fixed
             for signature_pub_key in signature_pub_keys {
             for signature_pub_key in signature_pub_keys {
                 let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
                 let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
                 assert!(verify_result, "verify sigs[{}] failed", i);
                 assert!(verify_result, "verify sigs[{}] failed", i);
@@ -183,12 +188,14 @@ fn sign(signature_secrets: &[SecretKey], func_calls: &[FuncCall]) -> Vec<Signatu
 type ContractId = pallas::Base;
 type ContractId = pallas::Base;
 type FuncId = pallas::Base;
 type FuncId = pallas::Base;
 
 
+// ANCHOR: funccall
 pub struct FuncCall {
 pub struct FuncCall {
     pub contract_id: ContractId,
     pub contract_id: ContractId,
     pub func_id: FuncId,
     pub func_id: FuncId,
     pub call_data: Box<dyn CallDataBase>,
     pub call_data: Box<dyn CallDataBase>,
     pub proofs: Vec<Proof>,
     pub proofs: Vec<Proof>,
 }
 }
+// ANCHOR_END: funccall
 
 
 impl Encodable for FuncCall {
 impl Encodable for FuncCall {
     fn encode<W: io::Write>(&self, mut w: W) -> core::result::Result<usize, io::Error> {
     fn encode<W: io::Write>(&self, mut w: W) -> core::result::Result<usize, io::Error> {
@@ -201,6 +208,7 @@ impl Encodable for FuncCall {
     }
     }
 }
 }
 
 
+// ANCHOR: calldatabase_trait
 pub trait CallDataBase {
 pub trait CallDataBase {
     // Public values for verifying the proofs
     // Public values for verifying the proofs
     // Needed so we can convert internal types so they can be used in Proof::verify()
     // Needed so we can convert internal types so they can be used in Proof::verify()
@@ -217,6 +225,7 @@ pub trait CallDataBase {
         writer: &mut dyn std::io::Write,
         writer: &mut dyn std::io::Write,
     ) -> core::result::Result<usize, std::io::Error>;
     ) -> core::result::Result<usize, std::io::Error>;
 }
 }
+// ANCHOR_END: calldatabase_trait
 
 
 type GenericContractState = Box<dyn Any>;
 type GenericContractState = Box<dyn Any>;
 
 

+ 34 - 8
doc/src/architecture/smart_contracts.md

@@ -79,19 +79,13 @@ the entire tx is rejected. Additionally some smart contracts might impose additi
 on the transaction's structure or other function calls (such as their call data).
 on the transaction's structure or other function calls (such as their call data).
 
 
 ```rust
 ```rust
-struct Transaction {
-    func_calls: Vec<FuncCall>
-}
+{{#include ../../../bin/daod/src/demo.rs:transaction}}
 ```
 ```
 
 
 Function calls represent mutations of the current active state to a new state.
 Function calls represent mutations of the current active state to a new state.
 
 
 ```rust
 ```rust
-struct FuncCall {
-    contract_id: ContractId,
-    func_id: FuncId,
-    call_data: Box<dyn Any>,
-}
+{{#include ../../../bin/daod/src/demo.rs:funccall}}
 ```
 ```
 
 
 The `contract_id` corresponds to the top level module for the contract which
 The `contract_id` corresponds to the top level module for the contract which
@@ -173,6 +167,38 @@ The transaction verification pipeline roughly looks like this:
     1. Lookup specific `apply()` function based off the `contract_id` and `func_id`.
     1. Lookup specific `apply()` function based off the `contract_id` and `func_id`.
     2. Call `apply(update)` to finalize the change.
     2. Call `apply(update)` to finalize the change.
 
 
+## ZK Proofs and Signatures
+
+Lets review again the format of transactions.
+
+```rust
+{{#include ../../../bin/daod/src/demo.rs:transaction}}
+```
+
+And corresponding function calls.
+
+```rust
+{{#include ../../../bin/daod/src/demo.rs:funccall}}
+```
+
+As we can see the ZK proofs and signatures are separate from the actuall `call_data` interpreted
+by `state_transition()`. They are both automatically verified by the VM.
+
+However for verification to work, the ZK proofs also need corresponding public values, and
+the signatures need the public keys. We do this in the `CallDataBase` trait by exporting these
+methods:
+
+```rust
+{{#include ../../../bin/daod/src/demo.rs:calldatabase_trait}}
+```
+
+These methods export the required values needed for the ZK proofs and signature verification
+from the actual call data itself.
+
+For signature verification, the data we are verifying is simply the entire transactions minus
+the actual signatures. That's why the signatures are a separate top level field in the
+transaction.
+
 ## Parallelisation Techniques
 ## Parallelisation Techniques
 
 
 Since verification is done through `state_transition()` which returns an update that is then committed
 Since verification is done through `state_transition()` which returns an update that is then committed