From 52561406f7e61d3613d80b0331ea31d96ec6ac60 Mon Sep 17 00:00:00 2001 From: x Date: Tue, 8 Nov 2022 13:10:31 +0000 Subject: [PATCH] dao2: money correctly saving and updating its own state --- example/dao2/contract/money/Cargo.toml | 2 +- example/dao2/contract/money/src/lib.rs | 40 +++++++++++++++++++++----- example/dao2/src/main.rs | 37 +++++++++++++----------- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/example/dao2/contract/money/Cargo.toml b/example/dao2/contract/money/Cargo.toml index eb5827431..660b3bf82 100644 --- a/example/dao2/contract/money/Cargo.toml +++ b/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. diff --git a/example/dao2/contract/money/src/lib.rs b/example/dao2/contract/money/src/lib.rs index a2eec395e..cef868879 100644 --- a/example/dao2/contract/money/src/lib.rs +++ b/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, + /// Coins + pub coins: Vec } /// 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)?; + } } } diff --git a/example/dao2/src/main.rs b/example/dao2/src/main.rs index 3495e5bfd..7a6895b1f 100644 --- a/example/dao2/src/main.rs +++ b/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 ///////////////////////////////////////////////////