Jelajahi Sumber

dao2: money correctly saving and updating its own state

x 3 tahun lalu
induk
melakukan
52561406f7

+ 1 - 1
example/dao2/contract/money/Cargo.toml

@@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"]
 
 [dependencies]
 darkfi-sdk = { path = "../../../../src/sdk" }
-darkfi-serial = { path = "../../../../src/serial" }
+darkfi-serial = { path = "../../../../src/serial", features = ["crypto"] }
 
 # We need to disable random using "custom" which makes the crate a noop
 # so the wasm32-unknown-unknown target is enabled.

+ 33 - 7
example/dao2/contract/money/src/lib.rs

@@ -1,9 +1,10 @@
 use darkfi_sdk::{
-    crypto::{ContractId, PublicKey},
+    crypto::{ContractId, PublicKey, MerkleNode, MerkleTree},
     db::{db_init, db_lookup, db_set},
     define_contract,
     msg,
     error::ContractResult,
+    merkle::merkle_add,
     pasta::{pallas, group::Curve, arithmetic::CurveAffine},
     tx::ContractCall,
     util::set_return_data,
@@ -35,8 +36,10 @@ pub struct MoneyTransferParams {
 }
 #[derive(SerialEncodable, SerialDecodable)]
 pub struct MoneyTransferUpdate {
-    // nullifiers
-    // coins
+    /// Nullifiers
+    pub nullifiers: Vec<pallas::Base>,
+    /// Coins
+    pub coins: Vec<pallas::Base>
 }
 
 /// A transaction's clear input
@@ -87,7 +90,16 @@ define_contract!(
 );
 
 fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
-    let db_handle = db_init(cid, "wagies")?;
+    let info_db = db_init(cid, "info")?;
+    let _ = db_init(cid, "coin_roots")?;
+
+    let coin_tree = MerkleTree::new(100);
+    let mut coin_tree_data = Vec::new();
+    coin_tree_data.write_u32(0)?;
+    coin_tree.encode(&mut coin_tree_data)?;
+    db_set(info_db, &serialize(&"coin_tree".to_string()), &coin_tree_data)?;
+
+    let _ = db_init(cid, "nulls")?;
 
     Ok(())
 }
@@ -165,7 +177,10 @@ fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
             let data = &self_.data[1..];
             let params: MoneyTransferParams = deserialize(data)?;
 
-            let update = MoneyTransferUpdate {};
+            let update = MoneyTransferUpdate {
+                nullifiers: params.inputs.iter().map(|input| input.nullifier).collect(),
+                coins: params.outputs.iter().map(|output| output.coin).collect(),
+            };
 
             let mut update_data = Vec::new();
             update_data.write_u8(MoneyFunction::Transfer as u8)?;
@@ -179,8 +194,19 @@ fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
 fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
     match MoneyFunction::from(update_data[0]) {
         MoneyFunction::Transfer => {
-            let db_handle = db_lookup(cid, "wagies")?;
-            db_set(db_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?;
+            let data = &update_data[1..];
+            let update: MoneyTransferUpdate = deserialize(data)?;
+
+            let db_info = db_lookup(cid, "info")?;
+            let db_nulls = db_lookup(cid, "nulls")?;
+            for nullifier in update.nullifiers {
+                db_set(db_nulls, &serialize(&nullifier), &[])?;
+            }
+            let db_roots = db_lookup(cid, "coin_roots")?;
+            for coin in update.coins {
+                let node = MerkleNode::new(coin);
+                merkle_add(db_info, db_roots, &serialize(&"coin_tree".to_string()), &node)?;
+            }
         }
     }
 

+ 21 - 16
example/dao2/src/main.rs

@@ -73,13 +73,27 @@ fn show_dao_state(chain: &Blockchain, contract_id: &ContractId) -> Result<()> {
 }
 
 fn show_money_state(chain: &Blockchain, contract_id: &ContractId) -> Result<()> {
-    let db = chain.contracts.lookup(&chain.sled_db, contract_id, "wagies")?;
+    let db_info = chain.contracts.lookup(&chain.sled_db, contract_id, "info")?;
+    let value = db_info.get(&serialize(&"coin_tree".to_string())).expect("coin_tree").unwrap();
+    let mut decoder = Cursor::new(&value);
+    let set_size: u32 = Decodable::decode(&mut decoder)?;
+    let tree: MerkleTree = Decodable::decode(decoder)?;
     debug!(target: "demo", "Money state:");
-    for obj in db.iter() {
+    debug!(target: "demo", "    tree: {} bytes", value.len());
+    debug!(target: "demo", "    set size: {}", set_size);
+
+    let db_roots = chain.contracts.lookup(&chain.sled_db, contract_id, "coin_roots")?;
+    for i in 0..set_size {
+        let root = db_roots.get(&serialize(&i)).expect("coin_roots").unwrap();
+        let root: MerkleNode = deserialize(&root)?;
+        debug!(target: "demo", "    root {}: {:?}", i, root);
+    }
+
+    let db_nulls = chain.contracts.lookup(&chain.sled_db, contract_id, "info")?;
+    debug!(target: "demo", "    nullifiers:");
+    for obj in db_nulls.iter() {
         let (key, value) = obj.unwrap();
-        let name: String = deserialize(&key)?;
-        let age: u32 = deserialize(&value)?;
-        debug!(target: "demo", "    {}: {}", name, age);
+        debug!(target: "demo", "        {:02x?}", &key[..]);
     }
     Ok(())
 }
@@ -136,7 +150,7 @@ fn validate(
     }
 
     tx.zk_verify(&zk_bins, &zkpublic_table)?;
-    tx.verify_sigs(&sigpub_table);
+    tx.verify_sigs(&sigpub_table)?;
 
     // Now we finished verification stage, just apply all changes
     assert_eq!(tx.calls.len(), updates.len());
@@ -453,16 +467,7 @@ async fn main() -> BoxResult<()> {
     )
     .expect("validate failed");
 
-    //let func_call = builder.build(&zk_bins)?;
-    //let func_calls = vec![func_call];
-
-    //let mut signatures = vec![];
-    //for func_call in &func_calls {
-    //    let sign = sign([cashier_signature_secret].to_vec(), func_call);
-    //    signatures.push(sign);
-    //}
-
-    //let tx = Transaction { func_calls, signatures };
+    // Wallet stuff
 
     ///////////////////////////////////////////////////