ソースを参照

Remove obsolete dao bins.

parazyd 3 年 前
コミット
b0bd9036a3
46 ファイル変更0 行追加6519 行削除
  1. 0 1
      bin/dao/README.md
  2. 0 33
      bin/dao/dao-cli/Cargo.toml
  3. 0 43
      bin/dao/dao-cli/run_demo.sh
  4. 0 280
      bin/dao/dao-cli/src/main.rs
  5. 0 130
      bin/dao/dao-cli/src/rpc.rs
  6. 0 0
      bin/dao/dao_config.toml
  7. 0 45
      bin/dao/daod/Cargo.toml
  8. 0 9
      bin/dao/daod/Makefile
  9. 0 251
      bin/dao/daod/demo-spec.md
  10. 0 168
      bin/dao/daod/proof/dao-exec.zk
  11. 0 32
      bin/dao/daod/proof/dao-mint.zk
  12. 0 63
      bin/dao/daod/proof/dao-propose-burn.zk
  13. 0 88
      bin/dao/daod/proof/dao-propose-main.zk
  14. 0 64
      bin/dao/daod/proof/dao-vote-burn.zk
  15. 0 98
      bin/dao/daod/proof/dao-vote-main.zk
  16. 0 14
      bin/dao/daod/proof/foo.zk
  17. 0 28
      bin/dao/daod/src/contract/dao/exec/mod.rs
  18. 0 220
      bin/dao/daod/src/contract/dao/exec/validate.rs
  19. 0 211
      bin/dao/daod/src/contract/dao/exec/wallet.rs
  20. 0 62
      bin/dao/daod/src/contract/dao/mint/mod.rs
  21. 0 90
      bin/dao/daod/src/contract/dao/mint/validate.rs
  22. 0 112
      bin/dao/daod/src/contract/dao/mint/wallet.rs
  23. 0 38
      bin/dao/daod/src/contract/dao/mod.rs
  24. 0 28
      bin/dao/daod/src/contract/dao/propose/mod.rs
  25. 0 186
      bin/dao/daod/src/contract/dao/propose/validate.rs
  26. 0 286
      bin/dao/daod/src/contract/dao/propose/wallet.rs
  27. 0 115
      bin/dao/daod/src/contract/dao/state.rs
  28. 0 28
      bin/dao/daod/src/contract/dao/vote/mod.rs
  29. 0 219
      bin/dao/daod/src/contract/dao/vote/validate.rs
  30. 0 308
      bin/dao/daod/src/contract/dao/vote/wallet.rs
  31. 0 28
      bin/dao/daod/src/contract/example/foo/mod.rs
  32. 0 108
      bin/dao/daod/src/contract/example/foo/validate.rs
  33. 0 92
      bin/dao/daod/src/contract/example/foo/wallet.rs
  34. 0 30
      bin/dao/daod/src/contract/example/mod.rs
  35. 0 39
      bin/dao/daod/src/contract/example/state.rs
  36. 0 21
      bin/dao/daod/src/contract/mod.rs
  37. 0 31
      bin/dao/daod/src/contract/money/mod.rs
  38. 0 129
      bin/dao/daod/src/contract/money/state.rs
  39. 0 29
      bin/dao/daod/src/contract/money/transfer/mod.rs
  40. 0 394
      bin/dao/daod/src/contract/money/transfer/validate.rs
  41. 0 235
      bin/dao/daod/src/contract/money/transfer/wallet.rs
  42. 0 74
      bin/dao/daod/src/error.rs
  43. 0 1204
      bin/dao/daod/src/main.rs
  44. 0 122
      bin/dao/daod/src/note.rs
  45. 0 453
      bin/dao/daod/src/rpc.rs
  46. 0 280
      bin/dao/daod/src/util.rs

+ 0 - 1
bin/dao/README.md

@@ -1 +0,0 @@
-# DAO

+ 0 - 33
bin/dao/dao-cli/Cargo.toml

@@ -1,33 +0,0 @@
-[package]
-name = "dao"
-version = "0.3.0"
-homepage = "https://dark.fi"
-description = "CLI utility for interacting with daod"
-authors = ["Dyne.org foundation <foundation@dyne.org>"]
-repository = "https://github.com/darkrenaissance/darkfi"
-license = "AGPL-3.0-only"
-edition = "2021"
-
-[dependencies.darkfi]
-path = "../../../"
-features = ["rpc"]
-
-[dependencies]
-# Async
-smol = "1.3.0"
-futures = "0.3.26"
-async-std = {version = "1.12.0", features = ["attributes"]}
-async-trait = "0.1.64"
-async-channel = "1.8.0"
-async-executor = "1.5.0"
-
-# Misc
-clap = {version = "4.1.4", features = ["derive"]}
-log = "0.4.17"
-num_cpus = "1.15.0"
-simplelog = "0.12.0"
-url = "2.3.1"
-prettytable-rs = "0.10.0"
-
-# Encoding and parsing
-serde_json = "1.0.91"

+ 0 - 43
bin/dao/dao-cli/run_demo.sh

@@ -1,43 +0,0 @@
-#!/bin/bash
-dao="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd ../../.. && pwd )/dao"
-
-$dao create 110 110 1 2
-addr=$($dao addr | cut -d " " -f 4)
-addr2=$(echo $addr | cut -c 2-)
-addr3=${addr2::-1}
-echo "address: $addr3"
-
-$dao mint 1000000 $addr3
-
-alice=$($dao keygen)
-alice=$($dao keygen | cut -d " " -f 4)
-alice2=$(echo $alice | cut -c 2-)
-alice3=${alice2::-1}
-echo "alice key: $alice3"
-
-bob=$($dao keygen)
-bob=$($dao keygen | cut -d " " -f 4)
-bob2=$(echo $bob | cut -c 2-)
-bob3=${bob2::-1}
-echo "bob key: $bob3"
-
-charlie=$($dao keygen)
-charlie=$($dao keygen | cut -d " " -f 4)
-charlie2=$(echo $charlie | cut -c 2-)
-charlie3=${charlie2::-1}
-echo "charlie key: $charlie3"
-
-$dao airdrop $alice3 10000
-$dao airdrop $bob3 100000
-$dao airdrop $charlie3 10000
-
-proposal=$($dao propose $alice3 $charlie3 10000 | cut -d " " -f 3)
-proposal2=$(echo $proposal | cut -c 2-)
-proposal3=${proposal2::-5}
-echo "Proposal bulla: $proposal3"
-
-$dao vote $alice3 yes
-$dao vote $bob3 yes
-$dao vote $charlie3 no
-
-$dao exec $proposal3

+ 0 - 280
bin/dao/dao-cli/src/main.rs

@@ -1,280 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::process::exit;
-
-use clap::{IntoApp, Parser, Subcommand};
-use prettytable::{format, row, Table};
-use url::Url;
-
-use darkfi::{rpc::client::RpcClient, Result};
-
-mod rpc;
-
-#[derive(Subcommand)]
-pub enum CliDaoSubCommands {
-    /// Create DAO
-    Create {
-        /// Minium number of governance tokens a user must have to propose a vote.
-        dao_proposer_limit: u64,
-
-        /// Minimum number of governance tokens staked on a proposal for it to pass.
-        dao_quorum: u64,
-
-        /// Quotient value of minimum vote ratio of yes:no votes required for a proposal to pass.
-        dao_approval_ratio_quot: u64,
-
-        /// Base value of minimum vote ratio of yes:no votes required for a proposal to pass.
-        dao_approval_ratio_base: u64,
-    },
-    /// Get DAO public address.
-    Addr {},
-    /// Get votes on current proposal in the form of [[true/false, user's GOV_tokens],[...]].
-    GetVotes {},
-    /// Get proposals in the form of [[destination, amount, token_id], [...]].
-    GetProposals {},
-    /// Mint tokens.
-    Mint {
-        /// Number of treasury tokens to mint.
-        token_supply: u64,
-
-        /// Public key of the DAO treasury.
-        dao_addr: String,
-    },
-    /// Get user balance.
-    UserBalance {
-        /// User public address.
-        addr: String,
-    },
-    /// Get DAO treasury balance.
-    DaoBalance {},
-    /// Get DAO bulla.
-    DaoBulla {},
-    /// Generate a new PublicKey.
-    Keygen {},
-    /// Airdrop tokens given recipient address and value.
-    Airdrop {
-        /// Airdrop recipient address.
-        addr: String,
-        /// Value to be airdropped.
-        value: u64,
-    },
-    /// Create a Proposal.
-    Propose {
-        /// Sender PublicKey.
-        sender: String,
-        /// Recipient PublicKey.
-        recipient: String,
-        /// Amount of tokens to be sent.
-        amount: u64,
-    },
-    /// Vote
-    Vote {
-        /// Voter's public address.
-        addr: String,
-        /// Vote value [yes/no].
-        vote: String,
-    },
-    /// Execute proposal bulla.
-    Exec {
-        /// Bulla.
-        bulla: String,
-    },
-}
-
-/// DAO cli
-#[derive(Parser)]
-#[clap(name = "dao")]
-#[clap(arg_required_else_help(true))]
-pub struct CliDao {
-    /// Increase verbosity
-    #[clap(short, parse(from_occurrences))]
-    pub verbose: u8,
-    #[clap(subcommand)]
-    pub command: Option<CliDaoSubCommands>,
-}
-
-pub struct Rpc {
-    client: RpcClient,
-}
-
-async fn start(options: CliDao) -> Result<()> {
-    let rpc_addr = "tcp://127.0.0.1:7777";
-    let client = Rpc { client: RpcClient::new(Url::parse(rpc_addr)?).await? };
-    match options.command {
-        Some(CliDaoSubCommands::Create {
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_base,
-            dao_approval_ratio_quot,
-        }) => {
-            let reply = client
-                .create(
-                    dao_proposer_limit,
-                    dao_quorum,
-                    dao_approval_ratio_quot,
-                    dao_approval_ratio_base,
-                )
-                .await?;
-            println!("Created DAO bulla: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Addr {}) => {
-            let reply = client.addr().await?;
-            println!("DAO public address: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::GetVotes {}) => {
-            let reply = client.get_votes().await?;
-            println!("Votes on current proposals: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::GetProposals {}) => {
-            let reply = client.get_proposals().await?;
-            println!("Current proposals: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Mint { token_supply, dao_addr }) => {
-            let reply = client.mint(token_supply, dao_addr).await?;
-            println!("{}", &reply.as_str().unwrap().to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Keygen {}) => {
-            let reply = client.keygen().await?;
-            println!("User public key: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Airdrop { addr, value }) => {
-            println!("Requesting airdrop of {} GOV", value);
-
-            let reply = client.airdrop(addr, value).await?;
-            println!("{}", &reply.as_str().unwrap().to_string());
-
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::DaoBalance {}) => {
-            let rep = client.dao_balance().await?;
-
-            if !rep.is_object() {
-                eprintln!("Invalid balance data received from darkfid RPC endpoint.");
-                exit(1);
-            }
-
-            let mut table = Table::new();
-            table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
-            table.set_titles(row!["Token", "Balance"]);
-
-            for i in rep.as_object().unwrap().keys() {
-                if let Some(balance) = rep[i].as_u64() {
-                    table.add_row(row![i, balance]);
-                    continue
-                }
-
-                eprintln!("Found invalid balance data for key \"{}\"", i);
-            }
-
-            if table.is_empty() {
-                println!("No balances.");
-            } else {
-                println!("{}", table);
-            }
-            // println!("DAO balance: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::DaoBulla {}) => {
-            let reply = client.dao_bulla().await?;
-            println!("DAO bulla: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::UserBalance { addr }) => {
-            let rep = client.user_balance(addr).await?;
-
-            if !rep.is_object() {
-                eprintln!("Invalid balance data received from darkfid RPC endpoint.");
-                exit(1);
-            }
-
-            let mut table = Table::new();
-            table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
-            table.set_titles(row!["Token", "Balance"]);
-
-            for i in rep.as_object().unwrap().keys() {
-                if let Some(balance) = rep[i].as_u64() {
-                    table.add_row(row![i, balance]);
-                    continue
-                }
-
-                eprintln!("Found invalid balance data for key \"{}\"", i);
-            }
-
-            if table.is_empty() {
-                println!("No balances.");
-            } else {
-                println!("{}", table);
-            }
-            // println!("User balance: {}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Propose { sender, recipient, amount }) => {
-            let reply = client.propose(sender.clone(), recipient.clone(), amount).await?;
-            println!(
-                "Proposal bulla: {}\nSender: {}\nRecipient: {}\nAmount: {} DRK",
-                &reply.to_string(),
-                sender,
-                recipient,
-                amount
-            );
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Vote { addr, vote }) => {
-            let reply = client.vote(addr, vote).await?;
-            println!("{}", &reply.to_string());
-            return Ok(())
-        }
-        Some(CliDaoSubCommands::Exec { bulla }) => {
-            let reply = client.exec(bulla).await?;
-            println!("{}", &reply.to_string());
-            return Ok(())
-        }
-        None => {}
-    }
-
-    Ok(())
-}
-
-#[async_std::main]
-async fn main() -> Result<()> {
-    let args = CliDao::parse();
-    let _matches = CliDao::command().get_matches();
-
-    //let config_path = if args.config.is_some() {
-    //    expand_path(&args.config.clone().unwrap())?
-    //} else {
-    //    join_config_path(&PathBuf::from("drk.toml"))?
-    //};
-
-    // Spawn config file if it's not in place already.
-    //spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
-
-    //let (lvl, conf) = log_config(matches)?;
-    //TermLogger::init(lvl, conf, TerminalMode::Mixed, ColorChoice::Auto)?;
-
-    //let config = Config::<DrkConfig>::load(config_path)?;
-
-    start(args).await
-}

+ 0 - 130
bin/dao/dao-cli/src/rpc.rs

@@ -1,130 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use serde_json::{json, Value};
-
-use darkfi::{rpc::jsonrpc::JsonRequest, Result};
-
-use crate::Rpc;
-
-impl Rpc {
-    // --> {"jsonrpc": "2.0", "method": "create", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "creating dao...", "id": 42}
-    pub async fn create(
-        &self,
-        dao_proposer_limit: u64,
-        dao_quorum: u64,
-        dao_approval_ratio_quot: u64,
-        dao_approval_ratio_base: u64,
-    ) -> Result<Value> {
-        let req = JsonRequest::new(
-            "create",
-            json!([
-                dao_proposer_limit,
-                dao_quorum,
-                dao_approval_ratio_quot,
-                dao_approval_ratio_base,
-            ]),
-        );
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "mint", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "minting tokens...", "id": 42}
-    pub async fn addr(&self) -> Result<Value> {
-        let req = JsonRequest::new("get_dao_addr", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "mint", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "minting tokens...", "id": 42}
-    pub async fn mint(&self, token_supply: u64, dao_addr: String) -> Result<Value> {
-        let req = JsonRequest::new("mint", json!([token_supply, dao_addr]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "airdrop", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "airdropping tokens...", "id": 42}
-    pub async fn airdrop(&self, nym: String, value: u64) -> Result<Value> {
-        let req = JsonRequest::new("airdrop", json!([nym, value]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "airdrop", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "airdropping tokens...", "id": 42}
-    pub async fn keygen(&self) -> Result<Value> {
-        let req = JsonRequest::new("keygen", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "airdrop", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "airdropping tokens...", "id": 42}
-    pub async fn dao_balance(&self) -> Result<Value> {
-        let req = JsonRequest::new("dao_balance", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "airdrop", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "airdropping tokens...", "id": 42}
-    pub async fn dao_bulla(&self) -> Result<Value> {
-        let req = JsonRequest::new("dao_bulla", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "airdrop", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "airdropping tokens...", "id": 42}
-    pub async fn user_balance(&self, nym: String) -> Result<Value> {
-        let req = JsonRequest::new("user_balance", json!([nym]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "propose", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "creating proposal...", "id": 42}
-    pub async fn propose(&self, sender: String, recipient: String, amount: u64) -> Result<Value> {
-        let req = JsonRequest::new("propose", json!([sender, recipient, amount]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "vote", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "voting...", "id": 42}
-    pub async fn vote(&self, nym: String, vote: String) -> Result<Value> {
-        let req = JsonRequest::new("vote", json!([nym, vote]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "exec", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "executing...", "id": 42}
-    pub async fn get_votes(&self) -> Result<Value> {
-        let req = JsonRequest::new("get_votes", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "exec", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "executing...", "id": 42}
-    pub async fn get_proposals(&self) -> Result<Value> {
-        let req = JsonRequest::new("get_proposals", json!([]));
-        self.client.request(req).await
-    }
-
-    // --> {"jsonrpc": "2.0", "method": "exec", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "executing...", "id": 42}
-    pub async fn exec(&self, bulla: String) -> Result<Value> {
-        let req = JsonRequest::new("exec", json!([bulla]));
-        self.client.request(req).await
-    }
-}

+ 0 - 0
bin/dao/dao_config.toml


+ 0 - 45
bin/dao/daod/Cargo.toml

@@ -1,45 +0,0 @@
-[package]
-name = "daod"
-version = "0.3.0"
-homepage = "https://dark.fi"
-description = "DarkFi DAO daemon"
-authors = ["Dyne.org foundation <foundation@dyne.org>"]
-repository = "https://github.com/darkrenaissance/darkfi"
-license = "AGPL-3.0-only"
-edition = "2021"
-
-[dependencies]
-darkfi = {path = "../../../", features = ["rpc", "crypto", "tx"]}
-darkfi-sdk = {path = "../../../src/sdk"}
-darkfi-serial = {path = "../../../src/serial"}
-
-# Async
-smol = "1.3.0"
-futures = "0.3.26"
-async-std = {version = "1.12.0", features = ["attributes"]}
-async-trait = "0.1.64"
-async-channel = "1.8.0"
-async-executor = "1.5.0"
-easy-parallel = "3.2.0"
-
-# Misc
-log = "0.4.17"
-num_cpus = "1.15.0"
-simplelog = "0.12.0"
-thiserror = "1.0.38"
-
-# Crypto
-halo2_gadgets = "0.2.0"
-halo2_proofs = "0.2.0"
-rand = "0.8.5"
-chacha20poly1305 = "0.10.1"
-pasta_curves = "0.4.1"
-incrementalmerkletree = "0.3.0"
-
-# Encoding and parsing
-serde_json = "1.0.91"
-bs58 = "0.4.0"
-
-# Utilities
-lazy_static = "1.4.0"
-url = "2.3.1"

+ 0 - 9
bin/dao/daod/Makefile

@@ -1,9 +0,0 @@
-ZK_SRC_FILES := $(wildcard proof/*.zk)
-ZK_BIN_FILES := $(patsubst proof/%.zk, proof/%.zk.bin, $(ZK_SRC_FILES))
-
-daod: $(ZK_BIN_FILES)
-	cargo run --release
-
-proof/%.zk.bin: proof/%.zk
-	zkas $<
-

+ 0 - 251
bin/dao/daod/demo-spec.md

@@ -1,251 +0,0 @@
----
-title: DAO demo architecture
-author: jstark
----
-
-This document outlines a simple demo to showcase the smart contract
-schema underlying the initial DAO MVP. We have tried to mimic the
-basic DarkFi architecture while remaining as simple as possible.
-
-We do not have a blockchain, p2p network, or encrypted wallet database
-in this highly simplified demo. It is just a local network of 4 nodes
-and a relayer.  The values are all stored in memory.
-
-# Layers
-
-**bin**
-Located in darkfi/bin/dao.
-
-* **daod/**: receives rpc requests and operates a `client`.
-* **dao-cli/**: command-line interface that receives input and sends rpc requests.
-* **relayerd/**: receives transactions on TCP and relays them to all nodes.
-
-**src**
-Located in darkfi/bin/dao/daod.
-
-* **contract/**: source code for dao and money contracts.
-* **util/**: demo-wide utilities.
-* **state/**: stores dao and money states.
-* **tx**: underlying types required by transactions, function calls and call data.
-* **node/**: a dao full node.
-
-**node**
-A dao node containing `client` and `wallet` submodules.
-
-* **client/**: operates a wallet and performs state transition and validate methods.
-* **wallet/**: owns and operates secret values.
-
-**proof**
-Located in darkfi/bin/dao/proof. Contains the zk proofs.
-
-# Command Flow
-
-The following assumes that a user has already compiled the zk contracts
-by running `make`.
-
-This requires a `Makescript` as follows:
-
-```
-ZK_SRC_FILES := $(wildcard proof/*.zk)
-ZK_BIN_FILES := $(patsubst proof/%.zk, proof/%.zk.bin, $(ZK_SRC_FILES))
-
-daod: $(ZK_BIN_FILES)
-	cargo run --release
-
-proof/%.zk.bin: proof/%.zk
-	zkas $<
-```
-
-We will also need to write a shell script that opens 9 terminals and
-runs the following:
-
-*Terminal 1:* relayerd.
-*Terminal 2-5:* 4 instances of daod.
-*Terminal 6-9:* 4 instances of dao-cli.
-
-Relayerd and daod should be sent to the background, so the demo will
-consist visually of 4 terminals running dao-cli.
-
-## Start relayer
-
-1. `relayerd` starts a listener for all TCP ports specified in config.
-
-## Initialize DAO 
-
-Note: this happens automatically on daod first run.
-
-1. `daod`: starts a listener on the relayer TCP port.
-2. `daod:` creates a client and calls `client.init()`.
-3. `client`: creates a money wallet.
-4. `money-wallet`: generates cashier, faucet keys.
-5. `client`: gets public keys from wallet and calls `state.new()`.
-6. `state`: creates ZkContractTable, StateRegistry. 
-7. `state`: loads all zk binaries and saves them in ZkContractTable.
-8. `state`: creates a new money/dao state and registers them in StateRegistry.
-
-## Stage 1: create DAO
-
-1. `dao-cli:` sends `create()` rpc request to daod.
-2. `daod`: receives rpc request and calls `client.create()`.
-3. `client`: creates a dao wallet.
-4. `dao-wallet`: specifies the dao params.
-5. `dao-wallet`: creates a dao keypair, bulla blind, and signature secret.
- 
-**build sequence.**
-
-Note: Builders differ according to the FuncCall, but the basic sequence
-is the same.
-
-6. `dao-wallet`: build: creates dao_contract::mint::wallet::Builder.
-7. `dao-wallet`: generates a FuncCall from builder.build().
-8. `dao-wallet`: adds FuncCall to a vector.
-9. `dao-wallet`: sign the vector of FuncCalls.
-
-**send sequence.**
-
-10. `dao-wallet`: create a Transaction.
-11. `dao-wallet`: send the Transaction to the relayer.
-12. `relayer`: receives a Transaction on one of its connections.
-13. `relayer`: relays the Transaction to all connected nodes.
-
-**recv sequence.**
-
-14. `daod`: receives a Transaction on its relayerd listener.
-15. 'daod`: sends the Transaction to Client.
-
-**validate sequence.**
-
-16. `client`: validate: creates an empty vector of updates.
-16. `client`: loops through all FuncCalls in the Transaction.
-17. `client`: runs a match statement on the FUNC_ID.
-18. `client`: finds mint FUNC_ID and runs a state transition function.
-20. `client`: pushes the result to Vec<Update>
-21. `client`: outside the loop, atomically applies all updates.
-22. `client`: calls zk_verify() on the Transaction.
-23. `client`: verifies signatures.
-
-------------------------------------------------------------------------
-
-24. `client`: sends Transaction to the relayer.
-25. `relayer`: receives Transaction and relays.
-* TODO: `dao-wallet`: waits until Transction is confirmed. (how?)
-27. `dao-wallet`: look up the dao state and call witness().
-28. `dao-wallet`: get the dao bulla from the Transaction.
-29. `dao-cli`: print "Created DAO {}".
-
-## Stage 2: fund DAO
-
-* TODO: for the demo it might be better to call mint() first and then
-fund(), passing the values into fund()
-
-Here we are creating a treasury token and sending it to the DAO.
-
-1. `dao-cli:` `fund()` rpc request to daod
-2. `daod`: receives rpc request and calls `client.fund()`.
-3. `client`: creates treasury token, random token ID and supply
-
-Note: dao-wallet must manually track coins to retrieve coins belonging
-to its private key.
-
-4. `dao-wallet`: looks up the money state, and calls state.wallet_cache.track()
-
-5. `money-wallet`: sets spend hook to dao_contract::exec::FUNC_ID
-5. `money-wallet`: sets user_data to dao_bulla
-
-* TODO: how does it get the dao_bulla? Must be stored somewhere.
-
-6. `money-wallet`: specifies dao public key and treasury token BuilderOutputInfo.
-5. `money-wallet`: runs the build sequence for money::transfer.
-9. `money-wallet`: create Transaction and send.
-10. `relayer`: receives Transaction and relays.
-11. `daod`: receives a Transaction and sends to client.
-12. `client`: runs the validate sequence.
-
-Note: here we get all coins associated with the private key.
-13. `dao-wallet`: looks up the state and calls WalletCache.get_received()
-14. `dao-wallet`: check the coin is valid by recreating Coin
-15. `daod`: sendswith token ID and balance to dao-cli.
-16. `dao-cli`: displays data using pretty table.
-
-## Stage 3: airdrop
-
-1. `dao-cli`: calls keygen()
-2. `daod`: client.keygen()
-3. `daod`: money-wallet.keygen()
-4. `money-wallet`: creates new keypair
-5. `money-wallet`: looks up the money_contract State and calls WalletCache.track()
-6. `money-wallet`: return the public key
-7. `dao-cli`: prints the public key
-
-Note: do this 3 times to generate 3 pubkey keys for different daod instances.
-
-8. `dao-cli`: calls mint()
-9. `daod`: call client.mint()
-10. `client:` creates governance token with random token ID and supply
-11. `dao-cli`: prints "created token {} with supply {}"
-12. `dao-cli`: calls airdrop() and passes a value and a pubkey.
-13. `dao-wallet:` runs the build sequence for money::transfer.
-14. `dao-wallet`: create Transaction and send.
-15. `relayer`: receives Transaction and relays.
-16. `daod`: receives a Transaction and sends to client.
-17. `client`: runs the validate sequence.
-18. `money-wallet`: state.wallet_cache.get_received()
-19. `money-wallet`: check the coin is valid by recreating Coin
-20. `daod`: sends token ID and balance to cli
-21. `dao-cli`: prints "received coin {} with value {}".
-
-* TODO: money-wallet must keep track of Coins and have a flag for whether or not they are spent.
-* Hashmap of <Coin, bool> ?
-
-## Stage 4: create proposal
-
-* TODO: maybe for the demo we should just hardcode a user/ proposal recipient.
-
-1. `dao-cli`: calls propose() and enter a user pubkey and an amount
-3. `dao-wallet`: runs the build sequence for dao_contract::propose
-4. `dao-wallet`: specifies user pubkey, amount and token ID in Proposal
-5. `dao-cli`: prints "Created proposal to send {} xDRK to {}"
-6. `dao-wallet`: create Transaction and send.
-7. `relayer`: receives Transaction and relays.
-8. `daod`: receives a Transaction and sends to client.
-9. `client`: runs the validate sequence.
-* TODO: how does everyone have access to DAO private key?
-10. `dao-wallet`: reads received proposal and tries to decrypt Note
-11. `dao-wallet`: sends decrypted values to daod
-12. `dao-cli`: prints "Proposal is now active"
-
-## Stage 5 vote
-
-1. `dao-cli`: calls vote() and enters a vote option (yes or no) and an amount
-2. `daod`: calls client.vote()
-3. `money-wallet`: get money_leaf_position and money_merkle_path
-4. `money-wallet`: create builder sequence for dao_contract::vote
-5. `money-wallet`: specify dao_keypair in vote_keypair field
-* TODO: this implies that money-wallet is able to access private values in dao-wallet
-6. `money-wallet`: signs and sends
-7. `relayer`: receives Transaction and relays.
-8. `daod`: receives a Transaction and sends to client.
-9. `client`: runs the validate sequence.
-10. `dao-wallet`: tries to decrypt the Vote.
-11. `dao-cli`: prints "Received vote {} value {}"
-
-Note: repeat 3 times with different values and vote options.
-
-* TODO: ignore section re: vote commitments?
-* TODO: determine outcome: yes_votes_value/ all_votes_value
-        e.g. when the quorum is reached, print "Quorum reached! Outcome {}"
-        or just hardcode it for X n. of voters
-
-## Stage 6: Executing the proposal
-
-1. `dao-cli`: calls exec()
-* TODO: how does dao have access to user data?
-2. `dao-wallet`: get money_leaf_position and money_merkle_path
-3. `dao-wallet`: specifies user_kaypair and proposal amount in 1st output
-4. `dao-wallet`: specifies change in 2nd output
-5. `dao-wallet`: run build sequence for money_contract::transfer
-6. `dao-wallet`: run build sequence for dao_contract::exec
-7. `dao-wallet`: signs transaction and sends
-8. `relayer`: receives Transaction and relays.
-9. `daod`: receives a Transaction and sends to client.
-10. `client`: runs the validate sequence.

+ 0 - 168
bin/dao/daod/proof/dao-exec.zk

@@ -1,168 +0,0 @@
-constant "DaoExec" {
-	EcFixedPointShort VALUE_COMMIT_VALUE,
-	EcFixedPoint VALUE_COMMIT_RANDOM,
-}
-
-contract "DaoExec" {
-    # proposal params
-    Base proposal_dest_x,
-    Base proposal_dest_y,
-    Base proposal_amount,
-    Base proposal_serial,
-    Base proposal_token_id,
-    Base proposal_blind,
-
-    # DAO params
-    Base dao_proposer_limit,
-    Base dao_quorum,
-    Base dao_approval_ratio_quot,
-    Base dao_approval_ratio_base,
-    Base gov_token_id,
-    Base dao_public_x,
-    Base dao_public_y,
-    Base dao_bulla_blind,
-
-    # votes
-    Base yes_votes_value,
-    Base all_votes_value,
-    Scalar yes_votes_blind,
-    Scalar all_votes_blind,
-    
-    # outputs + inputs
-    Base user_serial,
-    Base user_coin_blind,
-    Base dao_serial,
-    Base dao_coin_blind,
-    Base input_value,
-    Scalar input_value_blind,
-
-    # misc
-    Base dao_spend_hook,
-    Base user_spend_hook,
-    Base user_data,
-}
-
-circuit "DaoExec" {
-    dao_bulla = poseidon_hash(
-        dao_proposer_limit,
-        dao_quorum,
-        dao_approval_ratio_quot,
-        dao_approval_ratio_base,
-        gov_token_id,
-        dao_public_x,
-        dao_public_y,
-        dao_bulla_blind,
-    );
-    # Proposal bulla is valid means DAO bulla is also valid
-    # because of dao-propose-main.zk, already checks that when
-    # we first create the proposal. So it is redundant here.
-
-    proposal_bulla = poseidon_hash(
-        proposal_dest_x,
-        proposal_dest_y,
-        proposal_amount,
-        proposal_serial,
-        proposal_token_id,
-        dao_bulla,
-        proposal_blind,
-        # @tmp-workaround
-        proposal_blind,
-    );
-    constrain_instance(proposal_bulla);
-
-    coin_0 = poseidon_hash(
-       proposal_dest_x,
-       proposal_dest_y,
-       proposal_amount,
-       proposal_token_id,
-       proposal_serial,
-       user_spend_hook,
-       user_data,
-       proposal_blind,
-    );
-    constrain_instance(coin_0);
-
-    change = base_sub(input_value, proposal_amount);
-
-    coin_1 = poseidon_hash(
-       dao_public_x,
-       dao_public_y,
-       change,
-       proposal_token_id,
-       dao_serial,
-       dao_spend_hook,
-       dao_bulla,
-       dao_coin_blind,
-    );
-    constrain_instance(coin_1);
-
-    # Create pedersen commits for win_votes, and total_votes
-    # and make public
-    yes_votes_value_c = ec_mul_short(yes_votes_value, VALUE_COMMIT_VALUE);
-    yes_votes_blind_c = ec_mul(yes_votes_blind, VALUE_COMMIT_RANDOM);
-    yes_votes_commit = ec_add(yes_votes_value_c, yes_votes_blind_c);
-
-    # get curve points and constrain
-	yes_votes_commit_x = ec_get_x(yes_votes_commit);
-	yes_votes_commit_y = ec_get_y(yes_votes_commit);
-	constrain_instance(yes_votes_commit_x);
-	constrain_instance(yes_votes_commit_y);
-
-    all_votes_c = ec_mul_short(all_votes_value, VALUE_COMMIT_VALUE);
-    all_votes_blind_c = ec_mul(all_votes_blind, VALUE_COMMIT_RANDOM);
-    all_votes_commit = ec_add(all_votes_c, all_votes_blind_c);
-
-    # get curve points and constrain
-	all_votes_commit_x = ec_get_x(all_votes_commit);
-	all_votes_commit_y = ec_get_y(all_votes_commit);
-	constrain_instance(all_votes_commit_x);
-	constrain_instance(all_votes_commit_y);
-
-    # Create pedersen commit for input_value and make public
-    
-    input_value_v = ec_mul_short(input_value, VALUE_COMMIT_VALUE);
-    input_value_r = ec_mul(input_value_blind, VALUE_COMMIT_RANDOM);
-    input_value_commit = ec_add(input_value_v, input_value_r);
-
-    # get curve points and constrain
-	input_value_x = ec_get_x(input_value_commit);
-	input_value_y = ec_get_y(input_value_commit);
-	constrain_instance(input_value_x);
-	constrain_instance(input_value_y);
-
-    constrain_instance(dao_spend_hook);
-    constrain_instance(user_spend_hook);
-    constrain_instance(user_data);
-
-    # Check that dao_quorum is less than or equal to all_votes_value
-    one = witness_base(1);
-    all_votes_value_1 = base_add(all_votes_value, one);
-    less_than_strict(dao_quorum, all_votes_value_1);
-
-    # approval_ratio_quot / approval_ratio_base <= yes_votes / all_votes
-    #
-    # The above is also equivalent to this:
-    #
-    # all_votes * approval_ratio_quot <= yes_votes * approval_ratio_base
-
-    rhs = base_mul(all_votes_value, dao_approval_ratio_quot);
-    lhs = base_mul(yes_votes_value, dao_approval_ratio_base);
-
-    lhs_1 = base_add(lhs, one);
-    less_than_strict(rhs, lhs_1);
-    
-    ####
-
-    # Create coin 0
-    # Create coin 1
-    # Check values of coin 0 + coin 1 == input value
-    # Check value of coin 0 == proposal_amount
-    # Check public key matches too
-    # Create the input value commit
-    # Create the value commits
-
-    # NOTE: there is a vulnerability here where someone can create the exec
-    # transaction with a bad note so it cannot be decrypted by the receiver
-    # TODO: research verifiable encryption inside ZK
-}
-

+ 0 - 32
bin/dao/daod/proof/dao-mint.zk

@@ -1,32 +0,0 @@
-constant "DaoMint" {
-}
-
-contract "DaoMint" {
-    Base dao_proposer_limit,
-    Base dao_quorum,
-    Base dao_approval_ratio_quot,
-    Base dao_approval_ratio_base,
-    Base gdrk_token_id,
-    Base dao_public_x,
-    Base dao_public_y,
-    Base dao_bulla_blind,
-}
-
-circuit "DaoMint" {
-    # This circuit is not that interesting.
-    # It just states the bulla is a hash of 8 values.
-
-    # BullaMint subroutine
-    bulla = poseidon_hash(
-        dao_proposer_limit,
-        dao_quorum,
-        dao_approval_ratio_quot,
-        dao_approval_ratio_base,
-        gdrk_token_id,
-        dao_public_x,
-        dao_public_y,
-        dao_bulla_blind,
-    );
-    constrain_instance(bulla);
-}
-

+ 0 - 63
bin/dao/daod/proof/dao-propose-burn.zk

@@ -1,63 +0,0 @@
-constant "DaoProposeInput" {
-	EcFixedPointShort VALUE_COMMIT_VALUE,
-	EcFixedPoint VALUE_COMMIT_RANDOM,
-	EcFixedPointBase NULLIFIER_K,
-}
-
-contract "DaoProposeInput" {
-	Base secret,
-	Base serial,
-	Base spend_hook,
-	Base user_data,
-	Base value,
-	Base token,
-	Base coin_blind,
-	Scalar value_blind,
-	Base token_blind,
-	Uint32 leaf_pos,
-	MerklePath path,
-	Base signature_secret,
-}
-
-circuit "DaoProposeInput" {
-	# Poseidon hash of the nullifier
-	#nullifier = poseidon_hash(secret, serial);
-	#constrain_instance(nullifier);
-
-	# Pedersen commitment for coin's value
-	vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
-	vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
-	value_commit = ec_add(vcv, vcr);
-	# Since value_commit is a curve point, we fetch its coordinates
-	# and constrain them:
-	value_commit_x = ec_get_x(value_commit);
-	value_commit_y = ec_get_y(value_commit);
-	constrain_instance(value_commit_x);
-	constrain_instance(value_commit_y);
-
-	# Commitment for coin's token ID
-    token_commit = poseidon_hash(token, token_blind);
-    constrain_instance(token_commit);
-
-	# Coin hash
-	pub = ec_mul_base(secret, NULLIFIER_K);
-	pub_x = ec_get_x(pub);
-	pub_y = ec_get_y(pub);
-	C = poseidon_hash(pub_x, pub_y, value, token, serial, spend_hook, user_data, coin_blind);
-
-	# Merkle root
-	root = merkle_root(leaf_pos, path, C);
-	constrain_instance(root);
-
-	# Finally, we derive a public key for the signature and
-	# constrain its coordinates:
-	signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
-	signature_x = ec_get_x(signature_public);
-	signature_y = ec_get_y(signature_public);
-	constrain_instance(signature_x);
-	constrain_instance(signature_y);
-
-	# At this point we've enforced all of our public inputs.
-}
-
-

+ 0 - 88
bin/dao/daod/proof/dao-propose-main.zk

@@ -1,88 +0,0 @@
-constant "DaoProposeMain" {
-	EcFixedPointShort VALUE_COMMIT_VALUE,
-	EcFixedPoint VALUE_COMMIT_RANDOM,
-}
-
-contract "DaoProposeMain" {
-    # Proposers total number of gov tokens
-    Base total_funds,
-    Scalar total_funds_blind,
-
-    # Check the inputs and this proof are for the same token
-    Base gov_token_blind,
-
-    # proposal params
-    Base proposal_dest_x,
-    Base proposal_dest_y,
-    Base proposal_amount,
-    Base proposal_serial,
-    Base proposal_token_id,
-    Base proposal_blind,
-
-    # DAO params
-    Base dao_proposer_limit,
-    Base dao_quorum,
-    Base dao_approval_ratio_quot,
-    Base dao_approval_ratio_base,
-    Base gov_token_id,
-    Base dao_public_x,
-    Base dao_public_y,
-    Base dao_bulla_blind,
-
-	Uint32 dao_leaf_pos,
-	MerklePath dao_path,
-}
-
-circuit "DaoProposeMain" {
-    token_commit = poseidon_hash(gov_token_id, gov_token_blind);
-	constrain_instance(token_commit);
-
-    dao_bulla = poseidon_hash(
-        dao_proposer_limit,
-        dao_quorum,
-        dao_approval_ratio_quot,
-        dao_approval_ratio_base,
-        gov_token_id,
-        dao_public_x,
-        dao_public_y,
-        dao_bulla_blind,
-    );
-	dao_root = merkle_root(dao_leaf_pos, dao_path, dao_bulla);
-	constrain_instance(dao_root);
-    # Proves this DAO is valid
-
-    proposal_bulla = poseidon_hash(
-        proposal_dest_x,
-        proposal_dest_y,
-        proposal_amount,
-        proposal_serial,
-        proposal_token_id,
-        dao_bulla,
-        proposal_blind,
-        # @tmp-workaround
-        proposal_blind,
-    );
-    constrain_instance(proposal_bulla);
-
-    # Rangeproof check for proposal amount
-    zero = witness_base(0);
-    less_than_strict(zero, proposal_amount);
-
-    # This is the main check
-    # We check that dao_proposer_limit <= total_funds
-    one = witness_base(1);
-    total_funds_1 = base_add(total_funds, one);
-    less_than_strict(dao_proposer_limit, total_funds_1);
-
-	# Pedersen commitment for coin's value
-	vcv = ec_mul_short(total_funds, VALUE_COMMIT_VALUE);
-	vcr = ec_mul(total_funds_blind, VALUE_COMMIT_RANDOM);
-	total_funds_commit = ec_add(vcv, vcr);
-	# Since total_funds_commit is a curve point, we fetch its coordinates
-	# and constrain them:
-	total_funds_commit_x = ec_get_x(total_funds_commit);
-	total_funds_commit_y = ec_get_y(total_funds_commit);
-	constrain_instance(total_funds_commit_x);
-	constrain_instance(total_funds_commit_y);
-}
-

+ 0 - 64
bin/dao/daod/proof/dao-vote-burn.zk

@@ -1,64 +0,0 @@
-constant "DaoVoteInput" {
-	EcFixedPointShort VALUE_COMMIT_VALUE,
-	EcFixedPoint VALUE_COMMIT_RANDOM,
-	EcFixedPointBase NULLIFIER_K,
-}
-
-contract "DaoVoteInput" {
-	Base secret,
-	Base serial,
-	Base spend_hook,
-	Base user_data,
-	Base value,
-	Base gov_token_id,
-	Base coin_blind,
-	Scalar value_blind,
-	Base gov_token_blind,
-	Uint32 leaf_pos,
-	MerklePath path,
-	Base signature_secret,
-}
-
-circuit "DaoVoteInput" {
-	# Poseidon hash of the nullifier
-	nullifier = poseidon_hash(secret, serial);
-	constrain_instance(nullifier);
-
-	# Pedersen commitment for coin's value
-	vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
-	vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
-	value_commit = ec_add(vcv, vcr);
-	# Since value_commit is a curve point, we fetch its coordinates
-	# and constrain them:
-	value_commit_x = ec_get_x(value_commit);
-	value_commit_y = ec_get_y(value_commit);
-	constrain_instance(value_commit_x);
-	constrain_instance(value_commit_y);
-
-	# Commitment for coin's token ID
-    token_commit = poseidon_hash(gov_token_id, gov_token_blind);
-    constrain_instance(token_commit);
-
-	# Coin hash
-	pub = ec_mul_base(secret, NULLIFIER_K);
-	pub_x = ec_get_x(pub);
-	pub_y = ec_get_y(pub);
-	C = poseidon_hash(pub_x, pub_y, value, gov_token_id, serial, spend_hook, user_data, coin_blind);
-
-	# Merkle root
-	root = merkle_root(leaf_pos, path, C);
-	constrain_instance(root);
-
-	# Finally, we derive a public key for the signature and
-	# constrain its coordinates:
-	signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
-	signature_x = ec_get_x(signature_public);
-	signature_y = ec_get_y(signature_public);
-	constrain_instance(signature_x);
-	constrain_instance(signature_y);
-
-	# At this point we've enforced all of our public inputs.
-}
-
-
-

+ 0 - 98
bin/dao/daod/proof/dao-vote-main.zk

@@ -1,98 +0,0 @@
-constant "DaoVoteMain" {
-	EcFixedPointShort VALUE_COMMIT_VALUE,
-	EcFixedPoint VALUE_COMMIT_RANDOM,
-}
-
-contract "DaoVoteMain" {
-    # proposal params
-    Base proposal_dest_x,
-    Base proposal_dest_y,
-    Base proposal_amount,
-    Base proposal_serial,
-    Base proposal_token_id,
-    Base proposal_blind,
-
-    # DAO params
-    Base dao_proposer_limit,
-    Base dao_quorum,
-    Base dao_approval_ratio_quot,
-    Base dao_approval_ratio_base,
-    Base gov_token_id,
-    Base dao_public_x,
-    Base dao_public_y,
-    Base dao_bulla_blind,
-
-    # Is the vote yes or no
-    Base vote_option,
-    Scalar yes_vote_blind,
-
-    # Total amount of capital allocated to vote
-    Base all_votes_value,
-    Scalar all_votes_blind,
-
-    # Check the inputs and this proof are for the same token
-    Base gov_token_blind,
-}
-
-circuit "DaoVoteMain" {
-    token_commit = poseidon_hash(gov_token_id, gov_token_blind);
-	constrain_instance(token_commit);
-
-    dao_bulla = poseidon_hash(
-        dao_proposer_limit,
-        dao_quorum,
-        dao_approval_ratio_quot,
-        dao_approval_ratio_base,
-        gov_token_id,
-        dao_public_x,
-        dao_public_y,
-        dao_bulla_blind,
-    );
-    # Proposal bulla is valid means DAO bulla is also valid
-    # because of dao-propose-main.zk, already checks that when
-    # we first create the proposal. So it is redundant here.
-
-    proposal_bulla = poseidon_hash(
-        proposal_dest_x,
-        proposal_dest_y,
-        proposal_amount,
-        proposal_serial,
-        proposal_token_id,
-        dao_bulla,
-        proposal_blind,
-        # @tmp-workaround
-        proposal_blind,
-    );
-    constrain_instance(proposal_bulla);
-    # TODO: we need to check the proposal isn't invalidated
-    # that is expired or already executed.
-
-    # normally we call this yes vote
-	# Pedersen commitment for vote option
-    yes_votes_value = base_mul(vote_option, all_votes_value);
-	yes_votes_value_c = ec_mul_short(yes_votes_value, VALUE_COMMIT_VALUE);
-	yes_votes_blind_c = ec_mul(yes_vote_blind, VALUE_COMMIT_RANDOM);
-	yes_votes_commit = ec_add(yes_votes_value_c, yes_votes_blind_c);
-
-    # get curve points and constrain
-	yes_votes_commit_x = ec_get_x(yes_votes_commit);
-	yes_votes_commit_y = ec_get_y(yes_votes_commit);
-	constrain_instance(yes_votes_commit_x);
-	constrain_instance(yes_votes_commit_y);
-
-	# Pedersen commitment for vote value
-	all_votes_c = ec_mul_short(all_votes_value, VALUE_COMMIT_VALUE);
-	all_votes_blind_c = ec_mul(all_votes_blind, VALUE_COMMIT_RANDOM);
-	all_votes_commit = ec_add(all_votes_c, all_votes_blind_c);
-
-    # get curve points and constrain
-	all_votes_commit_x = ec_get_x(all_votes_commit);
-	all_votes_commit_y = ec_get_y(all_votes_commit);
-	constrain_instance(all_votes_commit_x);
-	constrain_instance(all_votes_commit_y);
-
-    # Vote option should be 0 or 1
-    bool_check(vote_option);
-}
-
-

+ 0 - 14
bin/dao/daod/proof/foo.zk

@@ -1,14 +0,0 @@
-constant "DaoMint" {
-}
-
-contract "DaoMint" {
-    Base a,
-    Base b,
-}
-
-circuit "DaoMint" {
-    c = base_add(a, b);
-    constrain_instance(c);
-}
-
-

+ 0 - 28
bin/dao/daod/src/contract/dao/exec/mod.rs

@@ -1,28 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-pub mod wallet;
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 220
bin/dao/daod/src/contract/dao/exec/validate.rs

@@ -1,220 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::{Any, TypeId};
-
-use darkfi_sdk::{
-    crypto::PublicKey,
-    pasta::{
-        arithmetic::CurveAffine,
-        group::{ff::PrimeField, Curve, Group},
-        pallas,
-    },
-};
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-
-use darkfi::{
-    crypto::{coin::Coin, types::DrkCircuitField},
-    Error as DarkFiError,
-};
-
-use crate::{
-    contract::{dao, dao::CONTRACT_ID, money},
-    util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-};
-
-type Result<T> = std::result::Result<T, Error>;
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-
-    #[error("InvalidNumberOfFuncCalls")]
-    InvalidNumberOfFuncCalls,
-
-    #[error("InvalidIndex")]
-    InvalidIndex,
-
-    #[error("InvalidCallData")]
-    InvalidCallData,
-
-    #[error("InvalidNumberOfOutputs")]
-    InvalidNumberOfOutputs,
-
-    #[error("InvalidOutput")]
-    InvalidOutput,
-
-    #[error("InvalidValueCommit")]
-    InvalidValueCommit,
-
-    #[error("InvalidVoteCommit")]
-    InvalidVoteCommit,
-}
-
-impl From<DarkFiError> for Error {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    pub proposal: pallas::Base,
-    pub coin_0: pallas::Base,
-    pub coin_1: pallas::Base,
-    pub yes_votes_commit: pallas::Point,
-    pub all_votes_commit: pallas::Point,
-    pub input_value_commit: pallas::Point,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        let yes_votes_commit_coords = self.yes_votes_commit.to_affine().coordinates().unwrap();
-
-        let all_votes_commit_coords = self.all_votes_commit.to_affine().coordinates().unwrap();
-
-        let input_value_commit_coords = self.input_value_commit.to_affine().coordinates().unwrap();
-
-        vec![(
-            "dao-exec".to_string(),
-            vec![
-                self.proposal,
-                self.coin_0,
-                self.coin_1,
-                *yes_votes_commit_coords.x(),
-                *yes_votes_commit_coords.y(),
-                *all_votes_commit_coords.x(),
-                *all_votes_commit_coords.y(),
-                *input_value_commit_coords.x(),
-                *input_value_commit_coords.y(),
-                *super::FUNC_ID,
-                pallas::Base::from(0),
-                pallas::Base::from(0),
-            ],
-        )]
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        vec![]
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}
-
-pub fn state_transition(
-    states: &StateRegistry,
-    func_call_index: usize,
-    parent_tx: &Transaction,
-) -> Result<Box<dyn UpdateBase + Send>> {
-    let func_call = &parent_tx.func_calls[func_call_index];
-    let call_data = func_call.call_data.as_any();
-
-    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
-    let call_data = call_data.downcast_ref::<CallData>();
-
-    // This will be inside wasm so unwrap is fine.
-    let call_data = call_data.unwrap();
-
-    // Enforce tx has correct format:
-    // 1. There should only be 2 func_call's
-    if parent_tx.func_calls.len() != 2 {
-        return Err(Error::InvalidNumberOfFuncCalls)
-    }
-
-    // 2. func_call_index == 1
-    if func_call_index != 1 {
-        return Err(Error::InvalidIndex)
-    }
-
-    // 3. First item should be a Money::transfer() calldata
-    if parent_tx.func_calls[0].func_id != *money::transfer::FUNC_ID {
-        return Err(Error::InvalidCallData)
-    }
-
-    let money_transfer_call_data = parent_tx.func_calls[0].call_data.as_any();
-    let money_transfer_call_data =
-        money_transfer_call_data.downcast_ref::<money::transfer::validate::CallData>();
-    let money_transfer_call_data = money_transfer_call_data.unwrap();
-    assert_eq!(
-        money_transfer_call_data.type_id(),
-        TypeId::of::<money::transfer::validate::CallData>()
-    );
-
-    // 4. Money::transfer() has exactly 2 outputs
-    if money_transfer_call_data.outputs.len() != 2 {
-        return Err(Error::InvalidNumberOfOutputs)
-    }
-
-    // Checks:
-    // 1. Check both coins in Money::transfer() are equal to our coin_0, coin_1
-    if money_transfer_call_data.outputs[0].revealed.coin != Coin(call_data.coin_0) {
-        return Err(Error::InvalidOutput)
-    }
-    if money_transfer_call_data.outputs[1].revealed.coin != Coin(call_data.coin_1) {
-        return Err(Error::InvalidOutput)
-    }
-
-    // 2. sum of Money::transfer() calldata input_value_commits == our input value commit
-    let mut input_value_commits = pallas::Point::identity();
-    for input in &money_transfer_call_data.inputs {
-        input_value_commits += input.revealed.value_commit;
-    }
-    if input_value_commits != call_data.input_value_commit {
-        return Err(Error::InvalidValueCommit)
-    }
-
-    // 3. get the ProposalVote from DAO::State
-    let state =
-        states.lookup::<dao::State>(*CONTRACT_ID).expect("Return type is not of type State");
-    let proposal_votes = state.proposal_votes.get(&call_data.proposal.to_repr()).unwrap();
-
-    // 4. check yes_votes_commit is the same as in ProposalVote
-    if proposal_votes.yes_votes_commit != call_data.yes_votes_commit {
-        return Err(Error::InvalidVoteCommit)
-    }
-    // 5. also check all_votes_commit
-    if proposal_votes.all_votes_commit != call_data.all_votes_commit {
-        return Err(Error::InvalidVoteCommit)
-    }
-
-    Ok(Box::new(Update { proposal: call_data.proposal }))
-}
-
-#[derive(Clone)]
-pub struct Update {
-    pub proposal: pallas::Base,
-}
-
-impl UpdateBase for Update {
-    fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        let state = states
-            .lookup_mut::<dao::State>(*CONTRACT_ID)
-            .expect("Return type is not of type State");
-        state.proposal_votes.remove(&self.proposal.to_repr()).unwrap();
-    }
-}

+ 0 - 211
bin/dao/daod/src/contract/dao/exec/wallet.rs

@@ -1,211 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{pedersen::pedersen_commitment_u64, poseidon_hash, SecretKey};
-use halo2_proofs::circuit::Value;
-use log::debug;
-use pasta_curves::{arithmetic::CurveAffine, group::Curve, pallas};
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::Proof,
-    zk::vm::{Witness, ZkCircuit},
-};
-
-use crate::{
-    contract::dao::{
-        exec::validate::CallData, mint::wallet::DaoParams, propose::wallet::Proposal, CONTRACT_ID,
-    },
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
-};
-
-pub struct Builder {
-    pub proposal: Proposal,
-    pub dao: DaoParams,
-    pub yes_votes_value: u64,
-    pub all_votes_value: u64,
-    pub yes_votes_blind: pallas::Scalar,
-    pub all_votes_blind: pallas::Scalar,
-    pub user_serial: pallas::Base,
-    pub user_coin_blind: pallas::Base,
-    pub dao_serial: pallas::Base,
-    pub dao_coin_blind: pallas::Base,
-    pub input_value: u64,
-    pub input_value_blind: pallas::Scalar,
-    pub hook_dao_exec: pallas::Base,
-    pub signature_secret: SecretKey,
-}
-
-impl Builder {
-    pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
-        debug!(target: "dao_contract::exec::wallet::Builder", "build()");
-        let mut proofs = vec![];
-
-        let (proposal_dest_x, proposal_dest_y) = self.proposal.dest.xy();
-
-        let proposal_amount = pallas::Base::from(self.proposal.amount);
-
-        let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
-        let dao_quorum = pallas::Base::from(self.dao.quorum);
-        let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
-        let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
-
-        let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
-
-        let user_spend_hook = pallas::Base::from(0);
-        let user_data = pallas::Base::from(0);
-        let input_value = pallas::Base::from(self.input_value);
-        let change = input_value - proposal_amount;
-
-        let dao_bulla = poseidon_hash::<8>([
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            self.dao.gov_token_id.inner(),
-            dao_pub_x,
-            dao_pub_y,
-            self.dao.bulla_blind,
-        ]);
-
-        let proposal_bulla = poseidon_hash::<8>([
-            proposal_dest_x,
-            proposal_dest_y,
-            proposal_amount,
-            self.proposal.serial,
-            self.proposal.token_id.inner(),
-            dao_bulla,
-            self.proposal.blind,
-            // @tmp-workaround
-            self.proposal.blind,
-        ]);
-
-        let coin_0 = poseidon_hash::<8>([
-            proposal_dest_x,
-            proposal_dest_y,
-            proposal_amount,
-            self.proposal.token_id.inner(),
-            self.proposal.serial,
-            user_spend_hook,
-            user_data,
-            self.proposal.blind,
-        ]);
-
-        let coin_1 = poseidon_hash::<8>([
-            dao_pub_x,
-            dao_pub_y,
-            change,
-            self.proposal.token_id.inner(),
-            self.dao_serial,
-            self.hook_dao_exec,
-            dao_bulla,
-            self.dao_coin_blind,
-        ]);
-
-        let yes_votes_commit = pedersen_commitment_u64(self.yes_votes_value, self.yes_votes_blind);
-        let yes_votes_commit_coords = yes_votes_commit.to_affine().coordinates().unwrap();
-
-        let all_votes_commit = pedersen_commitment_u64(self.all_votes_value, self.all_votes_blind);
-        let all_votes_commit_coords = all_votes_commit.to_affine().coordinates().unwrap();
-
-        let input_value_commit = pedersen_commitment_u64(self.input_value, self.input_value_blind);
-        let input_value_commit_coords = input_value_commit.to_affine().coordinates().unwrap();
-
-        let zk_info = zk_bins.lookup(&"dao-exec".to_string()).unwrap();
-        let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-            info
-        } else {
-            panic!("Not binary info")
-        };
-
-        let zk_bin = zk_info.bincode.clone();
-
-        let prover_witnesses = vec![
-            //
-            // proposal params
-            Witness::Base(Value::known(proposal_dest_x)),
-            Witness::Base(Value::known(proposal_dest_y)),
-            Witness::Base(Value::known(proposal_amount)),
-            Witness::Base(Value::known(self.proposal.serial)),
-            Witness::Base(Value::known(self.proposal.token_id.inner())),
-            Witness::Base(Value::known(self.proposal.blind)),
-            // DAO params
-            Witness::Base(Value::known(dao_proposer_limit)),
-            Witness::Base(Value::known(dao_quorum)),
-            Witness::Base(Value::known(dao_approval_ratio_quot)),
-            Witness::Base(Value::known(dao_approval_ratio_base)),
-            Witness::Base(Value::known(self.dao.gov_token_id.inner())),
-            Witness::Base(Value::known(dao_pub_x)),
-            Witness::Base(Value::known(dao_pub_y)),
-            Witness::Base(Value::known(self.dao.bulla_blind)),
-            // votes
-            Witness::Base(Value::known(pallas::Base::from(self.yes_votes_value))),
-            Witness::Base(Value::known(pallas::Base::from(self.all_votes_value))),
-            Witness::Scalar(Value::known(self.yes_votes_blind)),
-            Witness::Scalar(Value::known(self.all_votes_blind)),
-            // outputs + inputs
-            Witness::Base(Value::known(self.user_serial)),
-            Witness::Base(Value::known(self.user_coin_blind)),
-            Witness::Base(Value::known(self.dao_serial)),
-            Witness::Base(Value::known(self.dao_coin_blind)),
-            Witness::Base(Value::known(input_value)),
-            Witness::Scalar(Value::known(self.input_value_blind)),
-            // misc
-            Witness::Base(Value::known(self.hook_dao_exec)),
-            Witness::Base(Value::known(user_spend_hook)),
-            Witness::Base(Value::known(user_data)),
-        ];
-
-        let public_inputs = vec![
-            proposal_bulla,
-            coin_0,
-            coin_1,
-            *yes_votes_commit_coords.x(),
-            *yes_votes_commit_coords.y(),
-            *all_votes_commit_coords.x(),
-            *all_votes_commit_coords.y(),
-            *input_value_commit_coords.x(),
-            *input_value_commit_coords.y(),
-            self.hook_dao_exec,
-            user_spend_hook,
-            user_data,
-        ];
-
-        let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-        let proving_key = &zk_info.proving_key;
-        let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-            .expect("DAO::exec() proving error!)");
-        proofs.push(input_proof);
-
-        let call_data = CallData {
-            proposal: proposal_bulla,
-            coin_0,
-            coin_1,
-            yes_votes_commit,
-            all_votes_commit,
-            input_value_commit,
-        };
-
-        FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs,
-        }
-    }
-}

+ 0 - 62
bin/dao/daod/src/contract/dao/mint/mod.rs

@@ -1,62 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-/// This is an anonymous contract function that mutates the internal DAO state.
-///
-/// Corresponds to `mint(proposer_limit, quorum, approval_ratio, dao_pubkey, dao_blind)`
-///
-/// The prover creates a `Builder`, which then constructs the `Tx` that the verifier can
-/// check using `state_transition()`.
-///
-/// # Arguments
-///
-/// * `proposer_limit` - Number of governance tokens that holder must possess in order to
-///   propose a new vote.
-/// * `quorum` - Number of minimum votes that must be met for a proposal to pass.
-/// * `approval_ratio` - Ratio of winning to total votes for a proposal to pass.
-/// * `dao_pubkey` - Public key of the DAO for permissioned access. This can also be
-///   shared publicly if you want a full decentralized DAO.
-/// * `dao_blind` - Blinding factor for the DAO bulla.
-///
-/// # Example
-///
-/// ```rust
-/// let dao_proposer_limit = 110;
-/// let dao_quorum = 110;
-/// let dao_approval_ratio = 2;
-///
-/// let builder = dao_contract::Mint::Builder(
-///     dao_proposer_limit,
-///     dao_quorum,
-///     dao_approval_ratio,
-///     gov_token_id,
-///     dao_pubkey,
-///     dao_blind
-/// );
-/// let tx = builder.build();
-/// ```
-pub mod wallet;
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 90
bin/dao/daod/src/contract/dao/mint/validate.rs

@@ -1,90 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::{Any, TypeId};
-
-use darkfi::crypto::types::DrkCircuitField;
-use darkfi_sdk::crypto::PublicKey;
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-
-use crate::{
-    contract::dao::{DaoBulla, State, CONTRACT_ID},
-    util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-};
-
-pub fn state_transition(
-    _states: &StateRegistry,
-    func_call_index: usize,
-    parent_tx: &Transaction,
-) -> Result<Box<dyn UpdateBase + Send>> {
-    let func_call = &parent_tx.func_calls[func_call_index];
-    let call_data = func_call.call_data.as_any();
-
-    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
-    let call_data = call_data.downcast_ref::<CallData>();
-
-    // This will be inside wasm so unwrap is fine.
-    let call_data = call_data.unwrap();
-
-    Ok(Box::new(Update { dao_bulla: call_data.dao_bulla.clone() }))
-}
-
-#[derive(Clone)]
-pub struct Update {
-    pub dao_bulla: DaoBulla,
-}
-
-impl UpdateBase for Update {
-    fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        // Lookup dao_contract state from registry
-        let state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
-        // Add dao_bulla to state.dao_bullas
-        state.add_dao_bulla(self.dao_bulla);
-    }
-}
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {}
-
-type Result<T> = std::result::Result<T, Error>;
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    pub dao_bulla: DaoBulla,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        vec![("dao-mint".to_string(), vec![self.dao_bulla.0])]
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        vec![]
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}

+ 0 - 112
bin/dao/daod/src/contract/dao/mint/wallet.rs

@@ -1,112 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{poseidon_hash, PublicKey, SecretKey, TokenId};
-use halo2_proofs::circuit::Value;
-use pasta_curves::pallas;
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::Proof,
-    zk::vm::{Witness, ZkCircuit},
-};
-
-use crate::{
-    contract::dao::{mint::validate::CallData, state::DaoBulla, CONTRACT_ID},
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
-};
-
-#[derive(Clone)]
-pub struct DaoParams {
-    pub proposer_limit: u64,
-    pub quorum: u64,
-    pub approval_ratio_quot: u64,
-    pub approval_ratio_base: u64,
-    pub gov_token_id: TokenId,
-    pub public_key: PublicKey,
-    pub bulla_blind: pallas::Base,
-}
-
-pub struct Builder {
-    pub dao_proposer_limit: u64,
-    pub dao_quorum: u64,
-    pub dao_approval_ratio_quot: u64,
-    pub dao_approval_ratio_base: u64,
-    pub gov_token_id: TokenId,
-    pub dao_pubkey: PublicKey,
-    pub dao_bulla_blind: pallas::Base,
-    pub _signature_secret: SecretKey,
-}
-
-impl Builder {
-    /// Consumes self, and produces the function call
-    pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
-        // Dao bulla
-        let dao_proposer_limit = pallas::Base::from(self.dao_proposer_limit);
-        let dao_quorum = pallas::Base::from(self.dao_quorum);
-        let dao_approval_ratio_quot = pallas::Base::from(self.dao_approval_ratio_quot);
-        let dao_approval_ratio_base = pallas::Base::from(self.dao_approval_ratio_base);
-
-        let (dao_pub_x, dao_pub_y) = self.dao_pubkey.xy();
-
-        let dao_bulla = poseidon_hash::<8>([
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            self.gov_token_id.inner(),
-            dao_pub_x,
-            dao_pub_y,
-            self.dao_bulla_blind,
-        ]);
-        let dao_bulla = DaoBulla(dao_bulla);
-
-        // Now create the mint proof
-        let zk_info = zk_bins.lookup(&"dao-mint".to_string()).unwrap();
-        let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-            info
-        } else {
-            panic!("Not binary info")
-        };
-        let zk_bin = zk_info.bincode.clone();
-        let prover_witnesses = vec![
-            Witness::Base(Value::known(dao_proposer_limit)),
-            Witness::Base(Value::known(dao_quorum)),
-            Witness::Base(Value::known(dao_approval_ratio_quot)),
-            Witness::Base(Value::known(dao_approval_ratio_base)),
-            Witness::Base(Value::known(self.gov_token_id.inner())),
-            Witness::Base(Value::known(dao_pub_x)),
-            Witness::Base(Value::known(dao_pub_y)),
-            Witness::Base(Value::known(self.dao_bulla_blind)),
-        ];
-        let public_inputs = vec![dao_bulla.0];
-        let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-
-        let proving_key = &zk_info.proving_key;
-        let mint_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-            .expect("DAO::mint() proving error!");
-
-        let call_data = CallData { dao_bulla };
-        FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs: vec![mint_proof],
-        }
-    }
-}

+ 0 - 38
bin/dao/daod/src/contract/dao/mod.rs

@@ -1,38 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-// mint()
-pub mod mint;
-// propose()
-pub mod propose;
-// vote{}
-pub mod vote;
-// exec{}
-pub mod exec;
-
-pub mod state;
-
-pub use state::{DaoBulla, State};
-
-lazy_static! {
-    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 28
bin/dao/daod/src/contract/dao/propose/mod.rs

@@ -1,28 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-pub mod wallet;
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 186
bin/dao/daod/src/contract/dao/propose/validate.rs

@@ -1,186 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::{Any, TypeId};
-
-use darkfi_sdk::crypto::{MerkleNode, PublicKey};
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-use log::error;
-use pasta_curves::{
-    arithmetic::CurveAffine,
-    group::{Curve, Group},
-    pallas,
-};
-
-use darkfi::{crypto::types::DrkCircuitField, Error as DarkFiError};
-
-use crate::{
-    contract::{dao, dao::State as DaoState, money, money::state::State as MoneyState},
-    note::EncryptedNote2,
-    util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-};
-
-// used for debugging
-// const TARGET: &str = "dao_contract::propose::validate::state_transition()";
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {
-    #[error("Invalid input merkle root")]
-    InvalidInputMerkleRoot,
-
-    #[error("Invalid DAO merkle root")]
-    InvalidDaoMerkleRoot,
-
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-}
-type Result<T> = std::result::Result<T, Error>;
-
-impl From<DarkFiError> for Error {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    pub header: Header,
-    pub inputs: Vec<Input>,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        let mut zk_publics = Vec::new();
-        let mut total_funds_commit = pallas::Point::identity();
-
-        assert!(!self.inputs.is_empty(), "inputs length cannot be zero");
-        for input in &self.inputs {
-            total_funds_commit += input.value_commit;
-            let value_coords = input.value_commit.to_affine().coordinates().unwrap();
-
-            let (sig_x, sig_y) = input.signature_public.xy();
-
-            zk_publics.push((
-                "dao-propose-burn".to_string(),
-                vec![
-                    *value_coords.x(),
-                    *value_coords.y(),
-                    self.header.token_commit,
-                    input.merkle_root.inner(),
-                    sig_x,
-                    sig_y,
-                ],
-            ));
-        }
-
-        let total_funds_coords = total_funds_commit.to_affine().coordinates().unwrap();
-        zk_publics.push((
-            "dao-propose-main".to_string(),
-            vec![
-                self.header.token_commit,
-                self.header.dao_merkle_root.inner(),
-                self.header.proposal_bulla,
-                *total_funds_coords.x(),
-                *total_funds_coords.y(),
-            ],
-        ));
-
-        zk_publics
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        let mut signature_public_keys = vec![];
-        for input in self.inputs.clone() {
-            signature_public_keys.push(input.signature_public);
-        }
-        signature_public_keys
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct Header {
-    pub dao_merkle_root: MerkleNode,
-    pub token_commit: pallas::Base,
-    pub proposal_bulla: pallas::Base,
-    pub enc_note: EncryptedNote2,
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct Input {
-    pub value_commit: pallas::Point,
-    pub merkle_root: MerkleNode,
-    pub signature_public: PublicKey,
-}
-
-pub fn state_transition(
-    states: &StateRegistry,
-    func_call_index: usize,
-    parent_tx: &Transaction,
-) -> Result<Box<dyn UpdateBase + Send>> {
-    let func_call = &parent_tx.func_calls[func_call_index];
-    let call_data = func_call.call_data.as_any();
-
-    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
-    let call_data = call_data.downcast_ref::<CallData>();
-
-    // This will be inside wasm so unwrap is fine.
-    let call_data = call_data.unwrap();
-
-    // Check the merkle roots for the input coins are valid
-    for input in &call_data.inputs {
-        let money_state = states.lookup::<MoneyState>(*money::CONTRACT_ID).unwrap();
-        if !money_state.is_valid_merkle(&input.merkle_root) {
-            return Err(Error::InvalidInputMerkleRoot)
-        }
-    }
-
-    let state = states.lookup::<DaoState>(*dao::CONTRACT_ID).unwrap();
-
-    // Is the DAO bulla generated in the ZK proof valid
-    if !state.is_valid_dao_merkle(&call_data.header.dao_merkle_root) {
-        return Err(Error::InvalidDaoMerkleRoot)
-    }
-
-    // TODO: look at gov tokens avoid using already spent ones
-    // Need to spend original coin and generate 2 nullifiers?
-
-    Ok(Box::new(Update { proposal_bulla: call_data.header.proposal_bulla }))
-}
-
-#[derive(Clone)]
-pub struct Update {
-    pub proposal_bulla: pallas::Base,
-}
-
-impl UpdateBase for Update {
-    fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<DaoState>(*dao::CONTRACT_ID).unwrap();
-        state.add_proposal_bulla(self.proposal_bulla);
-    }
-}

+ 0 - 286
bin/dao/daod/src/contract/dao/propose/wallet.rs

@@ -1,286 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{
-    pedersen::pedersen_commitment_u64, poseidon_hash, MerkleNode, PublicKey, SecretKey, TokenId,
-};
-use darkfi_serial::{SerialDecodable, SerialEncodable};
-use halo2_proofs::circuit::Value;
-use incrementalmerkletree::Hashable;
-use pasta_curves::{
-    arithmetic::CurveAffine,
-    group::{ff::Field, Curve},
-    pallas,
-};
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::Proof,
-    zk::vm::{Witness, ZkCircuit},
-};
-
-use crate::{
-    contract::{
-        dao::{
-            mint::wallet::DaoParams,
-            propose::validate::{CallData, Header, Input},
-            CONTRACT_ID,
-        },
-        money,
-    },
-    note,
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
-};
-
-#[derive(SerialEncodable, SerialDecodable)]
-pub struct Note {
-    pub proposal: Proposal,
-}
-
-pub struct BuilderInput {
-    pub secret: SecretKey,
-    pub note: money::transfer::wallet::Note,
-    pub leaf_position: incrementalmerkletree::Position,
-    pub merkle_path: Vec<MerkleNode>,
-    pub signature_secret: SecretKey,
-}
-
-#[derive(SerialEncodable, SerialDecodable, Clone)]
-pub struct Proposal {
-    pub dest: PublicKey,
-    pub amount: u64,
-    pub serial: pallas::Base,
-    pub token_id: TokenId,
-    pub blind: pallas::Base,
-}
-
-pub struct Builder {
-    pub inputs: Vec<BuilderInput>,
-    pub proposal: Proposal,
-    pub dao: DaoParams,
-    pub dao_leaf_position: incrementalmerkletree::Position,
-    pub dao_merkle_path: Vec<MerkleNode>,
-    pub dao_merkle_root: MerkleNode,
-}
-
-impl Builder {
-    pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
-        let mut proofs = vec![];
-
-        let gov_token_blind = pallas::Base::random(&mut OsRng);
-
-        let mut inputs = vec![];
-        let mut total_funds = 0;
-        let mut total_funds_blinds = pallas::Scalar::from(0);
-
-        for input in self.inputs {
-            let funds_blind = pallas::Scalar::random(&mut OsRng);
-            total_funds += input.note.value;
-            total_funds_blinds += funds_blind;
-
-            let signature_public = PublicKey::from_secret(input.signature_secret);
-
-            let zk_info = zk_bins.lookup(&"dao-propose-burn".to_string()).unwrap();
-            let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-                info
-            } else {
-                panic!("Not binary info")
-            };
-            let zk_bin = zk_info.bincode.clone();
-
-            // Note from the previous output
-            let note = input.note;
-            let leaf_pos: u64 = input.leaf_position.into();
-
-            let prover_witnesses = vec![
-                Witness::Base(Value::known(input.secret.inner())),
-                Witness::Base(Value::known(note.serial)),
-                Witness::Base(Value::known(pallas::Base::from(0))),
-                Witness::Base(Value::known(pallas::Base::from(0))),
-                Witness::Base(Value::known(pallas::Base::from(note.value))),
-                Witness::Base(Value::known(note.token_id.inner())),
-                Witness::Base(Value::known(note.coin_blind)),
-                Witness::Scalar(Value::known(funds_blind)),
-                Witness::Base(Value::known(gov_token_blind)),
-                Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),
-                Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
-                Witness::Base(Value::known(input.signature_secret.inner())),
-            ];
-
-            let public_key = PublicKey::from_secret(input.secret);
-            let (pub_x, pub_y) = public_key.xy();
-
-            let coin = poseidon_hash::<8>([
-                pub_x,
-                pub_y,
-                pallas::Base::from(note.value),
-                note.token_id.inner(),
-                note.serial,
-                pallas::Base::from(0),
-                pallas::Base::from(0),
-                note.coin_blind,
-            ]);
-
-            let merkle_root = {
-                let position: u64 = input.leaf_position.into();
-                let mut current = MerkleNode::from(coin);
-                for (level, sibling) in input.merkle_path.iter().enumerate() {
-                    let level = level as u8;
-                    current = if position & (1 << level) == 0 {
-                        MerkleNode::combine(level.into(), &current, sibling)
-                    } else {
-                        MerkleNode::combine(level.into(), sibling, &current)
-                    };
-                }
-                current
-            };
-
-            let token_commit = poseidon_hash::<2>([note.token_id.inner(), gov_token_blind]);
-            assert_eq!(self.dao.gov_token_id, note.token_id);
-
-            let value_commit = pedersen_commitment_u64(note.value, funds_blind);
-            let value_coords = value_commit.to_affine().coordinates().unwrap();
-
-            let (sig_x, sig_y) = signature_public.xy();
-
-            let public_inputs = vec![
-                *value_coords.x(),
-                *value_coords.y(),
-                token_commit,
-                merkle_root.inner(),
-                sig_x,
-                sig_y,
-            ];
-            let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-
-            let proving_key = &zk_info.proving_key;
-            let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-                .expect("DAO::propose() proving error!");
-            proofs.push(input_proof);
-
-            let input = Input { value_commit, merkle_root, signature_public };
-            inputs.push(input);
-        }
-
-        let total_funds_commit = pedersen_commitment_u64(total_funds, total_funds_blinds);
-        let total_funds_coords = total_funds_commit.to_affine().coordinates().unwrap();
-        let total_funds = pallas::Base::from(total_funds);
-
-        let token_commit = poseidon_hash::<2>([self.dao.gov_token_id.inner(), gov_token_blind]);
-
-        let (proposal_dest_x, proposal_dest_y) = self.proposal.dest.xy();
-
-        let proposal_amount = pallas::Base::from(self.proposal.amount);
-
-        let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
-        let dao_quorum = pallas::Base::from(self.dao.quorum);
-        let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
-        let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
-
-        let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
-
-        let dao_bulla = poseidon_hash::<8>([
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            self.dao.gov_token_id.inner(),
-            dao_pub_x,
-            dao_pub_y,
-            self.dao.bulla_blind,
-        ]);
-
-        let dao_leaf_position: u64 = self.dao_leaf_position.into();
-
-        let proposal_bulla = poseidon_hash::<8>([
-            proposal_dest_x,
-            proposal_dest_y,
-            proposal_amount,
-            self.proposal.serial,
-            self.proposal.token_id.inner(),
-            dao_bulla,
-            self.proposal.blind,
-            // @tmp-workaround
-            self.proposal.blind,
-        ]);
-
-        let zk_info = zk_bins.lookup(&"dao-propose-main".to_string()).unwrap();
-        let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-            info
-        } else {
-            panic!("Not binary info")
-        };
-        let zk_bin = zk_info.bincode.clone();
-        let prover_witnesses = vec![
-            // Proposers total number of gov tokens
-            Witness::Base(Value::known(total_funds)),
-            Witness::Scalar(Value::known(total_funds_blinds)),
-            // Used for blinding exported gov token ID
-            Witness::Base(Value::known(gov_token_blind)),
-            // proposal params
-            Witness::Base(Value::known(proposal_dest_x)),
-            Witness::Base(Value::known(proposal_dest_y)),
-            Witness::Base(Value::known(proposal_amount)),
-            Witness::Base(Value::known(self.proposal.serial)),
-            Witness::Base(Value::known(self.proposal.token_id.inner())),
-            Witness::Base(Value::known(self.proposal.blind)),
-            // DAO params
-            Witness::Base(Value::known(dao_proposer_limit)),
-            Witness::Base(Value::known(dao_quorum)),
-            Witness::Base(Value::known(dao_approval_ratio_quot)),
-            Witness::Base(Value::known(dao_approval_ratio_base)),
-            Witness::Base(Value::known(self.dao.gov_token_id.inner())),
-            Witness::Base(Value::known(dao_pub_x)),
-            Witness::Base(Value::known(dao_pub_y)),
-            Witness::Base(Value::known(self.dao.bulla_blind)),
-            Witness::Uint32(Value::known(dao_leaf_position.try_into().unwrap())),
-            Witness::MerklePath(Value::known(self.dao_merkle_path.try_into().unwrap())),
-        ];
-        let public_inputs = vec![
-            token_commit,
-            self.dao_merkle_root.inner(),
-            proposal_bulla,
-            *total_funds_coords.x(),
-            *total_funds_coords.y(),
-        ];
-        let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-
-        let proving_key = &zk_info.proving_key;
-        let main_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-            .expect("DAO::propose() proving error!");
-        proofs.push(main_proof);
-
-        let note = Note { proposal: self.proposal };
-        let enc_note = note::encrypt(&note, &self.dao.public_key).unwrap();
-        let header = Header {
-            dao_merkle_root: self.dao_merkle_root,
-            proposal_bulla,
-            token_commit,
-            enc_note,
-        };
-
-        let call_data = CallData { header, inputs };
-
-        FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs,
-        }
-    }
-}

+ 0 - 115
bin/dao/daod/src/contract/dao/state.rs

@@ -1,115 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{any::Any, collections::HashMap};
-
-use darkfi_sdk::crypto::{constants::MERKLE_DEPTH, MerkleNode, Nullifier};
-use darkfi_serial::{SerialDecodable, SerialEncodable};
-use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
-use pasta_curves::{
-    group::{ff::PrimeField, Group},
-    pallas,
-};
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct DaoBulla(pub pallas::Base);
-
-type MerkleTree = BridgeTree<MerkleNode, MERKLE_DEPTH>;
-
-pub struct ProposalVotes {
-    // TODO: might be more logical to have 'yes_votes_commit' and 'no_votes_commit'
-    /// Weighted vote commit
-    pub yes_votes_commit: pallas::Point,
-    /// All value staked in the vote
-    pub all_votes_commit: pallas::Point,
-    /// Vote nullifiers
-    pub vote_nulls: Vec<Nullifier>,
-}
-
-impl ProposalVotes {
-    pub fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
-        self.vote_nulls.iter().any(|n| n == nullifier)
-    }
-}
-
-/// This DAO state is for all DAOs on the network. There should only be a single instance.
-pub struct State {
-    dao_bullas: Vec<DaoBulla>,
-    pub dao_tree: MerkleTree,
-    pub dao_roots: Vec<MerkleNode>,
-
-    //proposal_bullas: Vec<pallas::Base>,
-    pub proposal_tree: MerkleTree,
-    pub proposal_roots: Vec<MerkleNode>,
-    pub proposal_votes: HashMap<[u8; 32], ProposalVotes>,
-}
-
-impl State {
-    pub fn new() -> Box<dyn Any + Send> {
-        Box::new(Self {
-            dao_bullas: Vec::new(),
-            dao_tree: MerkleTree::new(100),
-            dao_roots: Vec::new(),
-            //proposal_bullas: Vec::new(),
-            proposal_tree: MerkleTree::new(100),
-            proposal_roots: Vec::new(),
-            proposal_votes: HashMap::new(),
-        })
-    }
-
-    pub fn add_dao_bulla(&mut self, bulla: DaoBulla) {
-        let node = MerkleNode::from(bulla.0);
-        self.dao_bullas.push(bulla);
-        self.dao_tree.append(&node);
-        self.dao_roots.push(self.dao_tree.root(0).unwrap());
-    }
-
-    pub fn add_proposal_bulla(&mut self, bulla: pallas::Base) {
-        let node = MerkleNode::from(bulla);
-        //self.proposal_bullas.push(bulla);
-        self.proposal_tree.append(&node);
-        self.proposal_roots.push(self.proposal_tree.root(0).unwrap());
-        self.proposal_votes.insert(
-            bulla.to_repr(),
-            ProposalVotes {
-                yes_votes_commit: pallas::Point::identity(),
-                all_votes_commit: pallas::Point::identity(),
-                vote_nulls: Vec::new(),
-            },
-        );
-    }
-
-    pub fn lookup_proposal_votes(&self, proposal_bulla: pallas::Base) -> Option<&ProposalVotes> {
-        self.proposal_votes.get(&proposal_bulla.to_repr())
-    }
-    pub fn lookup_proposal_votes_mut(
-        &mut self,
-        proposal_bulla: pallas::Base,
-    ) -> Option<&mut ProposalVotes> {
-        self.proposal_votes.get_mut(&proposal_bulla.to_repr())
-    }
-
-    pub fn is_valid_dao_merkle(&self, root: &MerkleNode) -> bool {
-        self.dao_roots.iter().any(|m| m == root)
-    }
-
-    // TODO: This never gets called.
-    pub fn _is_valid_proposal_merkle(&self, root: &MerkleNode) -> bool {
-        self.proposal_roots.iter().any(|m| m == root)
-    }
-}

+ 0 - 28
bin/dao/daod/src/contract/dao/vote/mod.rs

@@ -1,28 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-pub mod wallet;
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 219
bin/dao/daod/src/contract/dao/vote/validate.rs

@@ -1,219 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::{Any, TypeId};
-
-use darkfi_sdk::crypto::{MerkleNode, Nullifier, PublicKey};
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-use log::error;
-use pasta_curves::{
-    arithmetic::CurveAffine,
-    group::{Curve, Group},
-    pallas,
-};
-
-use darkfi::{crypto::types::DrkCircuitField, Error as DarkFiError};
-
-use crate::{
-    contract::{dao, dao::State as DaoState, money, money::state::State as MoneyState},
-    note::EncryptedNote2,
-    util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-};
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {
-    #[error("Invalid proposal")]
-    InvalidProposal,
-
-    #[error("Voting with already spent coinage")]
-    SpentCoin,
-
-    #[error("Double voting")]
-    DoubleVote,
-
-    #[error("Invalid input merkle root")]
-    InvalidInputMerkleRoot,
-
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-}
-type Result<T> = std::result::Result<T, Error>;
-
-impl From<DarkFiError> for Error {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    pub header: Header,
-    pub inputs: Vec<Input>,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        let mut zk_publics = Vec::new();
-        let mut all_votes_commit = pallas::Point::identity();
-
-        assert!(!self.inputs.is_empty(), "inputs length cannot be zero");
-        for input in &self.inputs {
-            all_votes_commit += input.vote_commit;
-            let value_coords = input.vote_commit.to_affine().coordinates().unwrap();
-
-            let (sig_x, sig_y) = input.signature_public.xy();
-
-            zk_publics.push((
-                "dao-vote-burn".to_string(),
-                vec![
-                    input.nullifier.inner(),
-                    *value_coords.x(),
-                    *value_coords.y(),
-                    self.header.token_commit,
-                    input.merkle_root.inner(),
-                    sig_x,
-                    sig_y,
-                ],
-            ));
-        }
-
-        let yes_vote_commit_coords = self.header.yes_vote_commit.to_affine().coordinates().unwrap();
-
-        let vote_commit_coords = all_votes_commit.to_affine().coordinates().unwrap();
-
-        zk_publics.push((
-            "dao-vote-main".to_string(),
-            vec![
-                self.header.token_commit,
-                self.header.proposal_bulla,
-                *yes_vote_commit_coords.x(),
-                *yes_vote_commit_coords.y(),
-                *vote_commit_coords.x(),
-                *vote_commit_coords.y(),
-            ],
-        ));
-
-        zk_publics
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        let mut signature_public_keys = vec![];
-        for input in self.inputs.clone() {
-            signature_public_keys.push(input.signature_public);
-        }
-        signature_public_keys
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct Header {
-    pub token_commit: pallas::Base,
-    pub proposal_bulla: pallas::Base,
-    pub yes_vote_commit: pallas::Point,
-    pub enc_note: EncryptedNote2,
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct Input {
-    pub nullifier: Nullifier,
-    pub vote_commit: pallas::Point,
-    pub merkle_root: MerkleNode,
-    pub signature_public: PublicKey,
-}
-
-pub fn state_transition(
-    states: &StateRegistry,
-    func_call_index: usize,
-    parent_tx: &Transaction,
-) -> Result<Box<dyn UpdateBase + Send>> {
-    let func_call = &parent_tx.func_calls[func_call_index];
-    let call_data = func_call.call_data.as_any();
-
-    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
-    let call_data = call_data.downcast_ref::<CallData>();
-
-    // This will be inside wasm so unwrap is fine.
-    let call_data = call_data.unwrap();
-
-    let dao_state = states.lookup::<DaoState>(*dao::CONTRACT_ID).unwrap();
-
-    // Check proposal_bulla exists
-    let votes_info = dao_state.lookup_proposal_votes(call_data.header.proposal_bulla);
-    if votes_info.is_none() {
-        return Err(Error::InvalidProposal)
-    }
-    let votes_info = votes_info.unwrap();
-
-    // Check the merkle roots for the input coins are valid
-    let mut vote_nulls = Vec::new();
-    let mut all_vote_commit = pallas::Point::identity();
-    for input in &call_data.inputs {
-        let money_state = states.lookup::<MoneyState>(*money::CONTRACT_ID).unwrap();
-        if !money_state.is_valid_merkle(&input.merkle_root) {
-            return Err(Error::InvalidInputMerkleRoot)
-        }
-
-        if money_state.nullifier_exists(&input.nullifier) {
-            return Err(Error::SpentCoin)
-        }
-
-        if votes_info.nullifier_exists(&input.nullifier) {
-            return Err(Error::DoubleVote)
-        }
-
-        all_vote_commit += input.vote_commit;
-
-        vote_nulls.push(input.nullifier);
-    }
-
-    Ok(Box::new(Update {
-        proposal_bulla: call_data.header.proposal_bulla,
-        vote_nulls,
-        yes_vote_commit: call_data.header.yes_vote_commit,
-        all_vote_commit,
-    }))
-}
-
-#[derive(Clone)]
-pub struct Update {
-    proposal_bulla: pallas::Base,
-    vote_nulls: Vec<Nullifier>,
-    pub yes_vote_commit: pallas::Point,
-    pub all_vote_commit: pallas::Point,
-}
-
-impl UpdateBase for Update {
-    fn apply(mut self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<DaoState>(*dao::CONTRACT_ID).unwrap();
-        let votes_info = state.lookup_proposal_votes_mut(self.proposal_bulla).unwrap();
-        votes_info.yes_votes_commit += self.yes_vote_commit;
-        votes_info.all_votes_commit += self.all_vote_commit;
-        votes_info.vote_nulls.append(&mut self.vote_nulls);
-    }
-}

+ 0 - 308
bin/dao/daod/src/contract/dao/vote/wallet.rs

@@ -1,308 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{
-    pedersen::pedersen_commitment_u64, poseidon_hash, Keypair, MerkleNode, Nullifier, PublicKey,
-    SecretKey,
-};
-use darkfi_serial::{SerialDecodable, SerialEncodable};
-use halo2_proofs::circuit::Value;
-use incrementalmerkletree::Hashable;
-use log::debug;
-use pasta_curves::{
-    arithmetic::CurveAffine,
-    group::{ff::Field, Curve},
-    pallas,
-};
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::Proof,
-    zk::vm::{Witness, ZkCircuit},
-};
-
-use crate::{
-    contract::{
-        dao::{
-            mint::wallet::DaoParams,
-            propose::wallet::Proposal,
-            vote::validate::{CallData, Header, Input},
-            CONTRACT_ID,
-        },
-        money,
-    },
-    note,
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
-};
-
-#[derive(SerialEncodable, SerialDecodable)]
-pub struct Note {
-    pub vote: Vote,
-    pub vote_value: u64,
-    pub vote_value_blind: pallas::Scalar,
-}
-
-#[derive(SerialEncodable, SerialDecodable)]
-pub struct Vote {
-    pub vote_option: bool,
-    pub vote_option_blind: pallas::Scalar,
-}
-
-pub struct BuilderInput {
-    pub secret: SecretKey,
-    pub note: money::transfer::wallet::Note,
-    pub leaf_position: incrementalmerkletree::Position,
-    pub merkle_path: Vec<MerkleNode>,
-    pub signature_secret: SecretKey,
-}
-
-// TODO: should be token locking voting?
-// Inside ZKproof, check proposal is correct.
-pub struct Builder {
-    pub inputs: Vec<BuilderInput>,
-    pub vote: Vote,
-    pub vote_keypair: Keypair,
-    pub proposal: Proposal,
-    pub dao: DaoParams,
-}
-
-impl Builder {
-    pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
-        debug!(target: "dao_contract::vote::wallet::Builder", "build()");
-        let mut proofs = vec![];
-
-        let gov_token_blind = pallas::Base::random(&mut OsRng);
-
-        let mut inputs = vec![];
-        let mut vote_value = 0;
-        let mut vote_value_blind = pallas::Scalar::from(0);
-
-        for input in self.inputs {
-            let value_blind = pallas::Scalar::random(&mut OsRng);
-
-            vote_value += input.note.value;
-            vote_value_blind += value_blind;
-
-            let signature_public = PublicKey::from_secret(input.signature_secret);
-
-            let zk_info = zk_bins.lookup(&"dao-vote-burn".to_string()).unwrap();
-
-            let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-                info
-            } else {
-                panic!("Not binary info")
-            };
-            let zk_bin = zk_info.bincode.clone();
-
-            // Note from the previous output
-            let note = input.note;
-            let leaf_pos: u64 = input.leaf_position.into();
-
-            let prover_witnesses = vec![
-                Witness::Base(Value::known(input.secret.inner())),
-                Witness::Base(Value::known(note.serial)),
-                Witness::Base(Value::known(pallas::Base::from(0))),
-                Witness::Base(Value::known(pallas::Base::from(0))),
-                Witness::Base(Value::known(pallas::Base::from(note.value))),
-                Witness::Base(Value::known(note.token_id.inner())),
-                Witness::Base(Value::known(note.coin_blind)),
-                Witness::Scalar(Value::known(vote_value_blind)),
-                Witness::Base(Value::known(gov_token_blind)),
-                Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),
-                Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
-                Witness::Base(Value::known(input.signature_secret.inner())),
-            ];
-
-            let public_key = PublicKey::from_secret(input.secret);
-            let (pub_x, pub_y) = public_key.xy();
-
-            let coin = poseidon_hash::<8>([
-                pub_x,
-                pub_y,
-                pallas::Base::from(note.value),
-                note.token_id.inner(),
-                note.serial,
-                pallas::Base::from(0),
-                pallas::Base::from(0),
-                note.coin_blind,
-            ]);
-
-            let merkle_root = {
-                let position: u64 = input.leaf_position.into();
-                let mut current = MerkleNode::from(coin);
-                for (level, sibling) in input.merkle_path.iter().enumerate() {
-                    let level = level as u8;
-                    current = if position & (1 << level) == 0 {
-                        MerkleNode::combine(level.into(), &current, sibling)
-                    } else {
-                        MerkleNode::combine(level.into(), sibling, &current)
-                    };
-                }
-                current
-            };
-
-            let token_commit = poseidon_hash::<2>([note.token_id.inner(), gov_token_blind]);
-            assert_eq!(self.dao.gov_token_id, note.token_id);
-
-            let nullifier = poseidon_hash::<2>([input.secret.inner(), note.serial]);
-
-            let vote_commit = pedersen_commitment_u64(note.value, vote_value_blind);
-            let vote_commit_coords = vote_commit.to_affine().coordinates().unwrap();
-
-            let (sig_x, sig_y) = signature_public.xy();
-
-            let public_inputs = vec![
-                nullifier,
-                *vote_commit_coords.x(),
-                *vote_commit_coords.y(),
-                token_commit,
-                merkle_root.inner(),
-                sig_x,
-                sig_y,
-            ];
-
-            let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-            let proving_key = &zk_info.proving_key;
-            debug!(target: "dao_contract::vote::wallet::Builder", "input_proof Proof::create()");
-            let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-                .expect("DAO::vote() proving error!");
-            proofs.push(input_proof);
-
-            let input = Input {
-                nullifier: Nullifier::from(nullifier),
-                vote_commit,
-                merkle_root,
-                signature_public,
-            };
-            inputs.push(input);
-        }
-
-        let token_commit = poseidon_hash::<2>([self.dao.gov_token_id.inner(), gov_token_blind]);
-
-        let (proposal_dest_x, proposal_dest_y) = self.proposal.dest.xy();
-
-        let proposal_amount = pallas::Base::from(self.proposal.amount);
-
-        let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
-        let dao_quorum = pallas::Base::from(self.dao.quorum);
-        let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
-        let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
-
-        let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
-
-        let dao_bulla = poseidon_hash::<8>([
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            self.dao.gov_token_id.inner(),
-            dao_pub_x,
-            dao_pub_y,
-            self.dao.bulla_blind,
-        ]);
-
-        let proposal_bulla = poseidon_hash::<8>([
-            proposal_dest_x,
-            proposal_dest_y,
-            proposal_amount,
-            self.proposal.serial,
-            self.proposal.token_id.inner(),
-            dao_bulla,
-            self.proposal.blind,
-            // @tmp-workaround
-            self.proposal.blind,
-        ]);
-
-        let vote_option = self.vote.vote_option as u64;
-        assert!(vote_option == 0 || vote_option == 1);
-
-        let yes_vote_commit =
-            pedersen_commitment_u64(vote_option * vote_value, self.vote.vote_option_blind);
-        let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap();
-
-        let all_vote_commit = pedersen_commitment_u64(vote_value, vote_value_blind);
-        let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
-
-        let zk_info = zk_bins.lookup(&"dao-vote-main".to_string()).unwrap();
-        let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-            info
-        } else {
-            panic!("Not binary info")
-        };
-        let zk_bin = zk_info.bincode.clone();
-
-        let prover_witnesses = vec![
-            // proposal params
-            Witness::Base(Value::known(proposal_dest_x)),
-            Witness::Base(Value::known(proposal_dest_y)),
-            Witness::Base(Value::known(proposal_amount)),
-            Witness::Base(Value::known(self.proposal.serial)),
-            Witness::Base(Value::known(self.proposal.token_id.inner())),
-            Witness::Base(Value::known(self.proposal.blind)),
-            // DAO params
-            Witness::Base(Value::known(dao_proposer_limit)),
-            Witness::Base(Value::known(dao_quorum)),
-            Witness::Base(Value::known(dao_approval_ratio_quot)),
-            Witness::Base(Value::known(dao_approval_ratio_base)),
-            Witness::Base(Value::known(self.dao.gov_token_id.inner())),
-            Witness::Base(Value::known(dao_pub_x)),
-            Witness::Base(Value::known(dao_pub_y)),
-            Witness::Base(Value::known(self.dao.bulla_blind)),
-            // Vote
-            Witness::Base(Value::known(pallas::Base::from(vote_option))),
-            Witness::Scalar(Value::known(self.vote.vote_option_blind)),
-            // Total number of gov tokens allocated
-            Witness::Base(Value::known(pallas::Base::from(vote_value))),
-            Witness::Scalar(Value::known(vote_value_blind)),
-            // gov token
-            Witness::Base(Value::known(gov_token_blind)),
-        ];
-
-        let public_inputs = vec![
-            token_commit,
-            proposal_bulla,
-            // this should be a value commit??
-            *yes_vote_commit_coords.x(),
-            *yes_vote_commit_coords.y(),
-            *all_vote_commit_coords.x(),
-            *all_vote_commit_coords.y(),
-        ];
-
-        let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-
-        let proving_key = &zk_info.proving_key;
-        debug!(target: "dao_contract::vote::wallet::Builder", "main_proof = Proof::create()");
-        let main_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-            .expect("DAO::vote() proving error!");
-        proofs.push(main_proof);
-
-        let note = Note { vote: self.vote, vote_value, vote_value_blind };
-        let enc_note = note::encrypt(&note, &self.vote_keypair.public).unwrap();
-
-        let header = Header { token_commit, proposal_bulla, yes_vote_commit, enc_note };
-
-        let call_data = CallData { header, inputs };
-
-        FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs,
-        }
-    }
-}

+ 0 - 28
bin/dao/daod/src/contract/example/foo/mod.rs

@@ -1,28 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-pub mod wallet;
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 108
bin/dao/daod/src/contract/example/foo/validate.rs

@@ -1,108 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::Any;
-
-use darkfi_sdk::crypto::PublicKey;
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-use pasta_curves::pallas;
-
-use darkfi::{crypto::types::DrkCircuitField, Error as DarkFiError};
-
-use crate::{
-    contract::example::{state::State, CONTRACT_ID},
-    util::{CallDataBase, StateRegistry, UpdateBase},
-};
-
-// type Result<T> = std::result::Result<T, Error>;
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {
-    // #[error("ValueExists")]
-    // ValueExists,
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-}
-
-impl From<DarkFiError> for Error {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    pub public_value: pallas::Base,
-    pub signature_public: PublicKey,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        vec![("example-foo".to_string(), vec![self.public_value])]
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        vec![self.signature_public]
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}
-
-// pub fn state_transition(
-//     states: &StateRegistry,
-//     func_call_index: usize,
-//     parent_tx: &Transaction,
-// ) -> Result<Box<dyn UpdateBase + Send>> {
-//     let func_call = &parent_tx.func_calls[func_call_index];
-//     let call_data = func_call.call_data.as_any();
-
-//     assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
-//     let call_data = call_data.downcast_ref::<CallData>();
-
-//     // This will be inside wasm so unwrap is fine.
-//     let call_data = call_data.unwrap();
-
-//     let example_state = states.lookup::<State>(*CONTRACT_ID).unwrap();
-
-//     if example_state.public_exists(&call_data.public_value) {
-//         return Err(Error::ValueExists)
-//     }
-
-//     Ok(Box::new(Update { public_value: call_data.public_value }))
-// }
-
-#[derive(Clone)]
-pub struct Update {
-    public_value: pallas::Base,
-}
-
-impl UpdateBase for Update {
-    fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        let example_state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
-        example_state.add_public_value(self.public_value);
-    }
-}

+ 0 - 92
bin/dao/daod/src/contract/example/foo/wallet.rs

@@ -1,92 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-// use log::debug;
-// use rand::rngs::OsRng;
-
-// use halo2_proofs::circuit::Value;
-// use pasta_curves::pallas;
-
-// use darkfi::{
-//     crypto::{
-//         keypair::{PublicKey, SecretKey},
-//         Proof,
-//     },
-//     zk::vm::{Witness, ZkCircuit},
-// };
-
-// use crate::{
-//     contract::example_contract::{foo::validate::CallData, CONTRACT_ID},
-//     util::{FuncCall, ZkContractInfo, ZkContractTable},
-// };
-
-// pub struct Foo {
-//     pub a: u64,
-//     pub b: u64,
-// }
-
-// pub struct Builder {
-//     pub foo: Foo,
-//     pub signature_secret: SecretKey,
-// }
-
-// impl Builder {
-//     pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
-//         debug!(target: "example_contract::foo::wallet::Builder", "build()");
-//         let mut proofs = vec![];
-
-//         let zk_info = zk_bins.lookup(&"example-foo".to_string()).unwrap();
-//         let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
-//             info
-//         } else {
-//             panic!("Not binary info")
-//         };
-
-//         let zk_bin = zk_info.bincode.clone();
-
-//         let prover_witnesses = vec![
-//             Witness::Base(Value::known(pallas::Base::from(self.foo.a))),
-//             Witness::Base(Value::known(pallas::Base::from(self.foo.b))),
-//         ];
-
-//         let a = pallas::Base::from(self.foo.a);
-//         let b = pallas::Base::from(self.foo.b);
-
-//         let c = a + b;
-
-//         let public_inputs = vec![c];
-
-//         let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
-//         debug!(target: "example_contract::foo::wallet::Builder", "input_proof Proof::create()");
-//         let proving_key = &zk_info.proving_key;
-//         let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
-//             .expect("Example::foo() proving error!)");
-//         proofs.push(input_proof);
-
-//         let signature_public = PublicKey::from_secret(self.signature_secret);
-
-//         let call_data = CallData { public_value: c, signature_public };
-
-//         FuncCall {
-//             contract_id: *CONTRACT_ID,
-//             func_id: *super::FUNC_ID,
-//             call_data: Box::new(call_data),
-//             proofs,
-//         }
-//     }
-// }

+ 0 - 30
bin/dao/daod/src/contract/example/mod.rs

@@ -1,30 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-// foo()
-pub mod foo;
-
-pub mod state;
-
-lazy_static! {
-    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 39
bin/dao/daod/src/contract/example/state.rs

@@ -1,39 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-// use std::any::Any;
-
-use pasta_curves::pallas;
-
-pub struct State {
-    pub public_values: Vec<pallas::Base>,
-}
-
-impl State {
-    // pub fn new() -> Box<dyn Any> {
-    //     Box::new(Self { public_values: Vec::new() })
-    // }
-
-    pub fn add_public_value(&mut self, public_value: pallas::Base) {
-        self.public_values.push(public_value)
-    }
-
-    // pub fn public_exists(&self, public_value: &pallas::Base) -> bool {
-    //     self.public_values.iter().any(|v| v == public_value)
-    // }
-}

+ 0 - 21
bin/dao/daod/src/contract/mod.rs

@@ -1,21 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-pub mod dao;
-pub mod example;
-pub mod money;

+ 0 - 31
bin/dao/daod/src/contract/money/mod.rs

@@ -1,31 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-// transfer()
-pub mod transfer;
-
-pub mod state;
-pub use state::State;
-
-lazy_static! {
-    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 129
bin/dao/daod/src/contract/money/state.rs

@@ -1,129 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{constants::MERKLE_DEPTH, MerkleNode, Nullifier, PublicKey, SecretKey};
-use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
-
-use darkfi::crypto::coin::Coin;
-
-use super::transfer;
-use crate::note::EncryptedNote2;
-
-type MerkleTree = BridgeTree<MerkleNode, MERKLE_DEPTH>;
-
-pub struct OwnCoin {
-    pub coin: Coin,
-    pub note: transfer::wallet::Note,
-    pub leaf_position: incrementalmerkletree::Position,
-}
-
-pub struct WalletCache {
-    // Normally this would be a HashMap, but SecretKey is not Hash-able
-    // TODO: This can be HashableBase
-    cache: Vec<(SecretKey, Vec<OwnCoin>)>,
-}
-
-impl WalletCache {
-    pub fn new() -> Self {
-        Self { cache: Vec::new() }
-    }
-
-    /// Must be called at the start to begin tracking received coins for this secret.
-    pub fn track(&mut self, secret: SecretKey) {
-        self.cache.push((secret, Vec::new()));
-    }
-
-    /// Get all coins received by this secret key
-    /// track() must be called on this secret before calling this or the function will panic.
-    pub fn get_received(&mut self, secret: &SecretKey) -> Vec<OwnCoin> {
-        for (other_secret, own_coins) in self.cache.iter_mut() {
-            if *secret == *other_secret {
-                // clear own_coins vec, and return current contents
-                return std::mem::take(own_coins)
-            }
-        }
-        panic!("you forget to track() this secret!");
-    }
-
-    pub fn try_decrypt_note(
-        &mut self,
-        coin: Coin,
-        ciphertext: EncryptedNote2,
-        tree: &mut MerkleTree,
-    ) {
-        // Loop through all our secret keys...
-        for (secret, own_coins) in self.cache.iter_mut() {
-            // .. attempt to decrypt the note ...
-            if let Ok(note) = ciphertext.decrypt(secret) {
-                let leaf_position = tree.witness().expect("coin should be in tree");
-                own_coins.push(OwnCoin { coin, note, leaf_position });
-            }
-        }
-    }
-}
-
-/// The state machine, held in memory.
-pub struct State {
-    /// The entire Merkle tree state
-    pub tree: MerkleTree,
-    /// List of all previous and the current Merkle roots.
-    /// This is the hashed value of all the children.
-    pub merkle_roots: Vec<MerkleNode>,
-    /// Nullifiers prevent double spending
-    pub nullifiers: Vec<Nullifier>,
-
-    /// Public key of the cashier
-    pub cashier_signature_public: PublicKey,
-
-    /// Public key of the faucet
-    pub faucet_signature_public: PublicKey,
-
-    pub wallet_cache: WalletCache,
-}
-
-impl State {
-    pub fn new(
-        cashier_signature_public: PublicKey,
-        faucet_signature_public: PublicKey,
-    ) -> Box<Self> {
-        Box::new(Self {
-            tree: MerkleTree::new(100),
-            merkle_roots: vec![],
-            nullifiers: vec![],
-            cashier_signature_public,
-            faucet_signature_public,
-            wallet_cache: WalletCache::new(),
-        })
-    }
-
-    pub fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
-        public == &self.cashier_signature_public
-    }
-
-    pub fn is_valid_faucet_public_key(&self, public: &PublicKey) -> bool {
-        public == &self.faucet_signature_public
-    }
-
-    pub fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
-        self.merkle_roots.iter().any(|m| m == merkle_root)
-    }
-
-    pub fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
-        self.nullifiers.iter().any(|n| n == nullifier)
-    }
-}

+ 0 - 29
bin/dao/daod/src/contract/money/transfer/mod.rs

@@ -1,29 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use lazy_static::lazy_static;
-use pasta_curves::{group::ff::Field, pallas};
-use rand::rngs::OsRng;
-
-pub mod validate;
-pub mod wallet;
-pub use wallet::{Builder, BuilderClearInputInfo, BuilderInputInfo, BuilderOutputInfo, Note};
-
-lazy_static! {
-    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
-}

+ 0 - 394
bin/dao/daod/src/contract/money/transfer/validate.rs

@@ -1,394 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::any::{Any, TypeId};
-
-use darkfi_sdk::crypto::{
-    pedersen::{pedersen_commitment_base, pedersen_commitment_u64},
-    MerkleNode, Nullifier, PublicKey, TokenId,
-};
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-use incrementalmerkletree::Tree;
-use log::{debug, error};
-use pasta_curves::{group::Group, pallas};
-
-use darkfi::{
-    crypto::{
-        coin::Coin,
-        types::{DrkCircuitField, DrkValueBlind, DrkValueCommit},
-        BurnRevealedValues, MintRevealedValues,
-    },
-    Error as DarkFiError,
-};
-
-use crate::{
-    contract::{
-        dao,
-        money::{state::State, CONTRACT_ID},
-    },
-    note::EncryptedNote2,
-    util::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-};
-
-const TARGET: &str = "money_contract::transfer::validate::state_transition()";
-
-/// A struct representing a state update.
-/// This gets applied on top of an existing state.
-#[derive(Clone)]
-pub struct Update {
-    /// All nullifiers in a transaction
-    pub nullifiers: Vec<Nullifier>,
-    /// All coins in a transaction
-    pub coins: Vec<Coin>,
-    /// All encrypted notes in a transaction
-    pub enc_notes: Vec<EncryptedNote2>,
-}
-
-impl UpdateBase for Update {
-    fn apply(mut self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
-
-        // Extend our list of nullifiers with the ones from the update
-        state.nullifiers.append(&mut self.nullifiers);
-
-        //// Update merkle tree and witnesses
-        for (coin, enc_note) in self.coins.into_iter().zip(self.enc_notes.into_iter()) {
-            // Add the new coins to the Merkle tree
-            let node = MerkleNode::from(coin.0);
-            state.tree.append(&node);
-
-            // Keep track of all Merkle roots that have existed
-            state.merkle_roots.push(state.tree.root(0).unwrap());
-
-            state.wallet_cache.try_decrypt_note(coin, enc_note, &mut state.tree);
-        }
-    }
-}
-
-pub fn state_transition(
-    states: &StateRegistry,
-    func_call_index: usize,
-    parent_tx: &Transaction,
-) -> Result<Box<dyn UpdateBase + Send>> {
-    // Check the public keys in the clear inputs to see if they're coming
-    // from a valid cashier or faucet.
-    debug!(target: TARGET, "Iterate clear_inputs");
-    let func_call = &parent_tx.func_calls[func_call_index];
-    let call_data = func_call.call_data.as_any();
-
-    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
-    let call_data = call_data.downcast_ref::<CallData>();
-
-    // This will be inside wasm so unwrap is fine.
-    let call_data = call_data.unwrap();
-
-    let state = states.lookup::<State>(*CONTRACT_ID).expect("Return type is not of type State");
-
-    // Code goes here
-    for (i, input) in call_data.clear_inputs.iter().enumerate() {
-        let pk = &input.signature_public;
-        // TODO: this depends on the token ID
-        if !state.is_valid_cashier_public_key(pk) && !state.is_valid_faucet_public_key(pk) {
-            error!(target: TARGET, "Invalid pubkey for clear input: {:?}", pk);
-            return Err(Error::VerifyFailed(VerifyFailed::InvalidCashierOrFaucetKey(i)))
-        }
-    }
-
-    // Nullifiers in the transaction
-    let mut nullifiers = Vec::with_capacity(call_data.inputs.len());
-
-    debug!(target: TARGET, "Iterate inputs");
-    for (i, input) in call_data.inputs.iter().enumerate() {
-        let merkle = &input.revealed.merkle_root;
-
-        // The Merkle root is used to know whether this is a coin that
-        // existed in a previous state.
-        if !state.is_valid_merkle(merkle) {
-            error!(target: TARGET, "Invalid Merkle root (input {})", i);
-            debug!(target: TARGET, "root: {:?}", merkle);
-            return Err(Error::VerifyFailed(VerifyFailed::InvalidMerkle(i)))
-        }
-
-        // Check the spend_hook is satisfied
-        // The spend_hook says a coin must invoke another contract function when being spent
-        // If the value is set, then we check the function call exists
-        let spend_hook = &input.revealed.spend_hook;
-        if spend_hook != &pallas::Base::from(0) {
-            // spend_hook is set so we enforce the rules
-            let mut is_found = false;
-            for (i, func_call) in parent_tx.func_calls.iter().enumerate() {
-                // Skip current func_call
-                if i == func_call_index {
-                    continue
-                }
-
-                // TODO: we need to change these to pallas::Base
-                // temporary workaround for now
-                // if func_call.func_id == spend_hook ...
-                if func_call.func_id == *dao::exec::FUNC_ID {
-                    is_found = true;
-                    break
-                }
-            }
-            if !is_found {
-                return Err(Error::VerifyFailed(VerifyFailed::SpendHookNotSatisfied))
-            }
-        }
-
-        // The nullifiers should not already exist.
-        // It is the double-spend protection.
-        let nullifier = &input.revealed.nullifier;
-        if state.nullifier_exists(nullifier) ||
-            (1..nullifiers.len()).any(|i| nullifiers[i..].contains(&nullifiers[i - 1]))
-        {
-            error!(target: TARGET, "Duplicate nullifier found (input {})", i);
-            debug!(target: TARGET, "nullifier: {:?}", nullifier);
-            return Err(Error::VerifyFailed(VerifyFailed::NullifierExists(i)))
-        }
-
-        nullifiers.push(input.revealed.nullifier);
-    }
-
-    debug!(target: TARGET, "Verifying call data");
-    match call_data.verify() {
-        Ok(()) => {
-            debug!(target: TARGET, "Verified successfully")
-        }
-        Err(e) => {
-            error!(target: TARGET, "Failed verifying zk proofs: {}", e);
-            return Err(Error::VerifyFailed(VerifyFailed::ProofVerifyFailed(e.to_string())))
-        }
-    }
-
-    // Newly created coins for this transaction
-    let mut coins = Vec::with_capacity(call_data.outputs.len());
-    let mut enc_notes = Vec::with_capacity(call_data.outputs.len());
-
-    for output in &call_data.outputs {
-        // Gather all the coins
-        coins.push(output.revealed.coin);
-        enc_notes.push(output.enc_note.clone());
-    }
-
-    Ok(Box::new(Update { nullifiers, coins, enc_notes }))
-}
-
-/// A DarkFi transaction
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct CallData {
-    /// Clear inputs
-    pub clear_inputs: Vec<ClearInput>,
-    /// Anonymous inputs
-    pub inputs: Vec<Input>,
-    /// Anonymous outputs
-    pub outputs: Vec<Output>,
-}
-
-impl CallDataBase for CallData {
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)> {
-        let mut public_values = Vec::new();
-        for input in &self.inputs {
-            public_values.push(("money-transfer-burn".to_string(), input.revealed.make_outputs()));
-        }
-        for output in &self.outputs {
-            public_values.push(("money-transfer-mint".to_string(), output.revealed.make_outputs()));
-        }
-        public_values
-    }
-
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn signature_public_keys(&self) -> Vec<PublicKey> {
-        let mut signature_public_keys = Vec::new();
-        for input in self.clear_inputs.clone() {
-            signature_public_keys.push(input.signature_public);
-        }
-        signature_public_keys
-    }
-
-    fn encode_bytes(
-        &self,
-        mut writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error> {
-        self.encode(&mut writer)
-    }
-}
-impl CallData {
-    /// Verify the transaction
-    pub fn verify(&self) -> VerifyResult<()> {
-        //  must have minimum 1 clear or anon input, and 1 output
-        if self.clear_inputs.len() + self.inputs.len() == 0 {
-            error!("tx::verify(): Missing inputs");
-            return Err(VerifyFailed::LackingInputs)
-        }
-        if self.outputs.is_empty() {
-            error!("tx::verify(): Missing outputs");
-            return Err(VerifyFailed::LackingOutputs)
-        }
-
-        // Accumulator for the value commitments
-        let mut valcom_total = DrkValueCommit::identity();
-
-        // Add values from the clear inputs
-        for input in &self.clear_inputs {
-            valcom_total += pedersen_commitment_u64(input.value, input.value_blind);
-        }
-        // Add values from the inputs
-        for input in &self.inputs {
-            valcom_total += &input.revealed.value_commit;
-        }
-        // Subtract values from the outputs
-        for output in &self.outputs {
-            valcom_total -= &output.revealed.value_commit;
-        }
-
-        // If the accumulator is not back in its initial state,
-        // there's a value mismatch.
-        if valcom_total != DrkValueCommit::identity() {
-            error!("tx::verify(): Missing funds");
-            return Err(VerifyFailed::MissingFunds)
-        }
-
-        // Verify that the token commitments match
-        if !self.verify_token_commitments() {
-            error!("tx::verify(): Token ID mismatch");
-            return Err(VerifyFailed::TokenMismatch)
-        }
-
-        Ok(())
-    }
-
-    fn verify_token_commitments(&self) -> bool {
-        assert_ne!(self.outputs.len(), 0);
-        let token_commit_value = self.outputs[0].revealed.token_commit;
-
-        let mut failed =
-            self.inputs.iter().any(|input| input.revealed.token_commit != token_commit_value);
-
-        failed = failed ||
-            self.outputs.iter().any(|output| output.revealed.token_commit != token_commit_value);
-
-        failed = failed ||
-            self.clear_inputs.iter().any(|input| {
-                pedersen_commitment_base(input.token_id.inner(), input.token_blind) !=
-                    token_commit_value
-            });
-        !failed
-    }
-}
-
-/// A transaction's clear input
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct ClearInput {
-    /// Input's value (amount)
-    pub value: u64,
-    /// Input's token ID
-    pub token_id: TokenId,
-    /// Blinding factor for `value`
-    pub value_blind: DrkValueBlind,
-    /// Blinding factor for `token_id`
-    pub token_blind: DrkValueBlind,
-    /// Public key for the signature
-    pub signature_public: PublicKey,
-}
-
-/// A transaction's anonymous input
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct Input {
-    /// Public inputs for the zero-knowledge proof
-    pub revealed: BurnRevealedValues,
-}
-
-/// A transaction's anonymous output
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct Output {
-    /// Public inputs for the zero-knowledge proof
-    pub revealed: MintRevealedValues,
-    /// The encrypted note
-    pub enc_note: EncryptedNote2,
-}
-
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum Error {
-    #[error(transparent)]
-    VerifyFailed(#[from] VerifyFailed),
-
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-}
-
-/// Transaction verification errors
-#[derive(Debug, Clone, thiserror::Error)]
-pub enum VerifyFailed {
-    #[error("Transaction has no inputs")]
-    LackingInputs,
-
-    #[error("Transaction has no outputs")]
-    LackingOutputs,
-
-    #[error("Invalid cashier/faucet public key for clear input {0}")]
-    InvalidCashierOrFaucetKey(usize),
-
-    #[error("Invalid Merkle root for input {0}")]
-    InvalidMerkle(usize),
-
-    #[error("Spend hook invoking function is not attached")]
-    SpendHookNotSatisfied,
-
-    #[error("Nullifier already exists for input {0}")]
-    NullifierExists(usize),
-
-    #[error("Token commitments in inputs or outputs to not match")]
-    TokenMismatch,
-
-    #[error("Money in does not match money out (value commitments)")]
-    MissingFunds,
-
-    #[error("Failed verifying zk proofs: {0}")]
-    ProofVerifyFailed(String),
-
-    #[error("Internal error: {0}")]
-    InternalError(String),
-
-    #[error("DarkFi error: {0}")]
-    DarkFiError(String),
-}
-
-type Result<T> = std::result::Result<T, Error>;
-
-impl From<Error> for VerifyFailed {
-    fn from(err: Error) -> Self {
-        Self::InternalError(err.to_string())
-    }
-}
-
-impl From<DarkFiError> for VerifyFailed {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-
-impl From<DarkFiError> for Error {
-    fn from(err: DarkFiError) -> Self {
-        Self::DarkFiError(err.to_string())
-    }
-}
-/// Result type used in transaction verifications
-pub type VerifyResult<T> = std::result::Result<T, VerifyFailed>;

+ 0 - 235
bin/dao/daod/src/contract/money/transfer/wallet.rs

@@ -1,235 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_sdk::crypto::{MerkleNode, PublicKey, SecretKey, TokenId};
-use darkfi_serial::{SerialDecodable, SerialEncodable};
-use pasta_curves::group::ff::Field;
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::{
-        burn_proof::create_burn_proof,
-        mint_proof::create_mint_proof,
-        types::{
-            DrkCoinBlind, DrkSerial, DrkSpendHook, DrkUserData, DrkUserDataBlind, DrkValueBlind,
-        },
-    },
-    Result,
-};
-
-use crate::{
-    contract::money::{
-        transfer::validate::{CallData, ClearInput, Input, Output},
-        CONTRACT_ID,
-    },
-    note,
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
-};
-
-#[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct Note {
-    pub serial: DrkSerial,
-    pub value: u64,
-    pub token_id: TokenId,
-    pub spend_hook: DrkSpendHook,
-    pub user_data: DrkUserData,
-    pub coin_blind: DrkCoinBlind,
-    pub value_blind: DrkValueBlind,
-    pub token_blind: DrkValueBlind,
-}
-
-pub struct Builder {
-    pub clear_inputs: Vec<BuilderClearInputInfo>,
-    pub inputs: Vec<BuilderInputInfo>,
-    pub outputs: Vec<BuilderOutputInfo>,
-}
-
-pub struct BuilderClearInputInfo {
-    pub value: u64,
-    pub token_id: TokenId,
-    pub signature_secret: SecretKey,
-}
-
-pub struct BuilderInputInfo {
-    pub leaf_position: incrementalmerkletree::Position,
-    pub merkle_path: Vec<MerkleNode>,
-    pub secret: SecretKey,
-    pub note: Note,
-    pub user_data_blind: DrkUserDataBlind,
-    pub value_blind: DrkValueBlind,
-    pub signature_secret: SecretKey,
-}
-
-pub struct BuilderOutputInfo {
-    pub value: u64,
-    pub token_id: TokenId,
-    pub public: PublicKey,
-    pub serial: DrkSerial,
-    pub coin_blind: DrkCoinBlind,
-    pub spend_hook: DrkSpendHook,
-    pub user_data: DrkUserData,
-}
-
-impl Builder {
-    fn compute_remainder_blind(
-        clear_inputs: &[ClearInput],
-        input_blinds: &[DrkValueBlind],
-        output_blinds: &[DrkValueBlind],
-    ) -> DrkValueBlind {
-        let mut total = DrkValueBlind::zero();
-
-        for input in clear_inputs {
-            total += input.value_blind;
-        }
-
-        for input_blind in input_blinds {
-            total += input_blind;
-        }
-
-        for output_blind in output_blinds {
-            total -= output_blind;
-        }
-
-        total
-    }
-
-    pub fn build(self, zk_bins: &ZkContractTable) -> Result<FuncCall> {
-        assert!(self.clear_inputs.len() + self.inputs.len() > 0);
-
-        let mut clear_inputs = vec![];
-        let token_blind = DrkValueBlind::random(&mut OsRng);
-        for input in &self.clear_inputs {
-            let signature_public = PublicKey::from_secret(input.signature_secret);
-            let value_blind = DrkValueBlind::random(&mut OsRng);
-
-            let clear_input = ClearInput {
-                value: input.value,
-                token_id: input.token_id,
-                value_blind,
-                token_blind,
-                signature_public,
-            };
-            clear_inputs.push(clear_input);
-        }
-
-        let mut proofs = vec![];
-        let mut inputs = vec![];
-        let mut input_blinds = vec![];
-
-        for input in self.inputs {
-            let value_blind = input.value_blind;
-            input_blinds.push(value_blind);
-
-            let zk_info = zk_bins.lookup(&"money-transfer-burn".to_string()).unwrap();
-            let zk_info = if let ZkContractInfo::Native(info) = zk_info {
-                info
-            } else {
-                panic!("Not native info")
-            };
-            let burn_pk = &zk_info.proving_key;
-
-            // Note from the previous output
-            let note = input.note.clone();
-
-            let (burn_proof, revealed) = create_burn_proof(
-                burn_pk,
-                note.value,
-                note.token_id,
-                value_blind,
-                token_blind,
-                note.serial,
-                note.spend_hook,
-                note.user_data,
-                input.user_data_blind,
-                note.coin_blind,
-                input.secret,
-                input.leaf_position,
-                input.merkle_path.clone(),
-                input.signature_secret,
-            )?;
-            proofs.push(burn_proof);
-
-            let input = Input { revealed };
-            inputs.push(input);
-        }
-
-        let mut outputs = vec![];
-        let mut output_blinds = vec![];
-        // This value_blind calc assumes there will always be at least a single output
-        assert!(!self.outputs.is_empty());
-
-        for (i, output) in self.outputs.iter().enumerate() {
-            let value_blind = if i == self.outputs.len() - 1 {
-                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds)
-            } else {
-                DrkValueBlind::random(&mut OsRng)
-            };
-            output_blinds.push(value_blind);
-
-            let serial = output.serial;
-            let coin_blind = output.coin_blind;
-
-            let zk_info = zk_bins.lookup(&"money-transfer-mint".to_string()).unwrap();
-            let zk_info = if let ZkContractInfo::Native(info) = zk_info {
-                info
-            } else {
-                panic!("Not native info")
-            };
-            let mint_pk = &zk_info.proving_key;
-
-            let (mint_proof, revealed) = create_mint_proof(
-                mint_pk,
-                output.value,
-                output.token_id,
-                value_blind,
-                token_blind,
-                serial,
-                output.spend_hook,
-                output.user_data,
-                coin_blind,
-                output.public,
-            )?;
-            proofs.push(mint_proof);
-
-            let note = Note {
-                serial,
-                value: output.value,
-                token_id: output.token_id,
-                spend_hook: output.spend_hook,
-                user_data: output.user_data,
-                coin_blind,
-                value_blind,
-                token_blind,
-            };
-
-            let encrypted_note = note::encrypt(&note, &output.public)?;
-
-            let output = Output { revealed, enc_note: encrypted_note };
-            outputs.push(output);
-        }
-
-        let call_data = CallData { clear_inputs, inputs, outputs };
-
-        Ok(FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs,
-        })
-    }
-}

+ 0 - 74
bin/dao/daod/src/error.rs

@@ -1,74 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use serde_json::Value;
-
-use darkfi::rpc::jsonrpc::{ErrorCode::ServerError, JsonError, JsonResult};
-
-#[derive(Debug, thiserror::Error)]
-pub enum DaoError {
-    #[error("No Proposals found")]
-    NoProposals,
-    #[error("No DAO params found")]
-    DaoNotConfigured,
-    #[error("State transition failed: '{0}'")]
-    StateTransitionFailed(String),
-    #[error("Wallet does not exist")]
-    NoWalletFound,
-    #[error("State not found")]
-    StateNotFound,
-    #[error("InternalError")]
-    Darkfi(#[from] darkfi::error::Error),
-    #[error("Verify proof failed: '{0}', '{0}'")]
-    VerifyProofFailed(usize, String),
-}
-
-pub type DaoResult<T> = std::result::Result<T, DaoError>;
-
-pub enum RpcError {
-    Vote = -32101,
-    Propose = -32102,
-    Exec = -32103,
-    Airdrop = -32104,
-    Mint = -32105,
-    Keygen = -32106,
-    Create = -32107,
-    Parse = -32108,
-    Balance = -32109,
-}
-
-fn to_tuple(e: RpcError) -> (i64, String) {
-    let msg = match e {
-        RpcError::Vote => "Failed to cast a Vote",
-        RpcError::Propose => "Failed to generate a Proposal",
-        RpcError::Airdrop => "Failed to transfer an airdrop",
-        RpcError::Keygen => "Failed to generate keypair",
-        RpcError::Create => "Failed to create DAO",
-        RpcError::Exec => "Failed to execute Proposal",
-        RpcError::Mint => "Failed to mint DAO treasury",
-        RpcError::Parse => "Generic parsing error",
-        RpcError::Balance => "Failed to get balance",
-    };
-
-    (e as i64, msg.to_string())
-}
-
-pub fn server_error(e: RpcError, id: Value) -> JsonResult {
-    let (code, msg) = to_tuple(e);
-    JsonError::new(ServerError(code), Some(msg), id).into()
-}

+ 0 - 1204
bin/dao/daod/src/main.rs

@@ -1,1204 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{collections::HashMap, sync::Arc, time::Instant};
-
-use log::debug;
-use rand::rngs::OsRng;
-use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode};
-use url::Url;
-
-use darkfi::{
-    crypto::{
-        proof::{ProvingKey, VerifyingKey},
-        types::{DrkSpendHook, DrkUserData, DrkValue},
-    },
-    rpc::server::listen_and_serve,
-    zk::circuit::{BurnContract, MintContract},
-    zkas::ZkBinary,
-    Error, Result,
-};
-use darkfi_sdk::crypto::{
-    pedersen::pedersen_commitment_u64, poseidon_hash, Keypair, MerkleNode, PublicKey, SecretKey,
-    TokenId,
-};
-use incrementalmerkletree::{Position, Tree};
-use pasta_curves::{
-    group::{ff::Field, Group},
-    pallas,
-};
-
-mod contract;
-mod error;
-mod note;
-mod rpc;
-mod util;
-
-use crate::{
-    contract::{
-        dao::{self, mint::wallet::DaoParams, propose::wallet::Proposal, DaoBulla},
-        money::{self, state::OwnCoin},
-    },
-    error::{DaoError, DaoResult},
-    rpc::JsonRpcInterface,
-    util::{sign, StateRegistry, Transaction, ZkContractTable, DRK_ID, GOV_ID},
-};
-
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-//// dao-demo 0.1
-////
-//// This is a very early prototype intended to demonstrate the underlying
-//// crypto of fully anonymous DAOs. DAO participants can own and operate
-//// a collective treasury according to rules set by the DAO. Communities
-//// can coordinate financially in the cover of a protective darkness,
-//// free from surveillance and persecution.
-////
-//// The following information is completely hidden:
-////
-//// * DAO treasury
-//// * DAO parameters
-//// * DAO participants
-//// * Proposals
-//// * Votes
-////
-//// The DAO enables participants to make proposals, cast votes, and spend
-//// money from the DAO treasury if a proposal passes. The basic operation
-//// involves transferring money from a treasury to a public key specified
-//// in a Proposal. This operation can only happen if several conditions are
-//// met.
-////
-//// At its basis, the DAO is a treasury that is owned by everyone who holds
-//// the DAO governance token. These constraints, also known as DAO parameters,
-//// are configured by DAO participants and enforced by ZK cryptography.
-////
-//// In this demo, the constraints are:
-////
-//// 1. DAO quorum: the number of governance tokens that must be allocated
-////    to a proposal in order for a proposal to pass.
-//// 2. Proposer limit: the number of governance tokens required to make a
-////    proposal.
-//// 3. DAO approval ratio: The ratio of yes/ no votes required for a
-////    proposal to pass.
-////
-//// In addition, DAO participants must prove ownership of governance tokens
-//// order to vote. Their vote is weighted according to the number of governance
-//// tokens in their wallet. In this current implementation, users do not spend
-//// or lock up these coins in order to vote- they simply prove ownership of them.
-////
-//// In the current prototype, the following information is exposed:
-////
-//// * Encrypted votes are publicly linked to the proposal identifier hash,
-////   meaning that it is possible to see that there is voting activity associated
-////   with a particular proposal identifier, but the contents of the proposal,
-////   how one has voted, and the associated DAO is fully private.
-//// * In the burn phase of casting a vote, we reveal a public value called a
-////   nullifier. The same public value is revealed when we spend the coins we
-////   used to vote, meaning you can link a vote with a user when they spend
-////   governance tokens. This is bad but is easily fixable. We will update the
-////   code to use different values in the vote (by creating an intermediate Coin
-////   used for voting).
-//// * Votes are currently encrypted to the DAO public key. This means that
-////   any DAO participant can decrypt votes as they come in. In the future,
-////   we can delay the decryption so that you cannot read votes until the final
-////   tally.
-////
-//// Additionally, the dao-demo app shown below is highly limited. Namely, we use
-//// a single God daemon to operate all the wallets. In the next version, every user
-//// wallet will be a seperate daemon connecting over a network and running on a
-//// blockchain.
-////
-//// /////////////////////////////////////////////////////////////////////
-////
-//// dao-demo 0.1 TODOs:
-////
-//// High priority:
-////
-//// 5. vote() should pass a ProposalBulla
-////
-//// Less priority:
-////
-//// 1. Better document CLI/ CLI help.
-////
-//// 2. Token id is hardcoded rn. Change this so users can specify token_id
-////    as either xdrk or gdrk. In dao-cli we run a match statement to link to
-////    the corresponding static values XDRK_ID and GDRK_ID. Note: xdrk is used
-////    only for the DAO treasury. gdrk is the governance token used to operate
-////    the DAO.
-////
-//// 3. Implement money transfer between MoneyWallets so users can send tokens to
-////    eachother.
-////
-//// 4. Make CLI usage more interactive. Example: when I cast a vote, output:
-////   "You voted {} with value {}." where value is the number of gDRK in a users
-////    wallet (and the same for making a proposal etc).
-////
-//// 5. Currently, DaoWallet stores DaoParams, DaoBulla's and Proposal's in a
-////    Vector. We retrieve values through indexing, meaning that we
-////    cannot currently support multiple DAOs and multiple proposals.
-////
-////    Instead, dao_wallet.create_dao() should create a struct called Dao
-////    which stores dao_info: HashMap<DaoBulla, DaoParams> and proposals:
-////    HashMap<ProposalBulla, Proposal>. Users pass the DaoBulla and
-////    ProposalBulla and we lookup the corresponding data. struct Dao should
-////    be owned by DaoWallet.
-////
-//// 6. Error handling :)
-////
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-
-pub struct Client {
-    dao_wallet: DaoWallet,
-    money_wallets: HashMap<[u8; 32], MoneyWallet>,
-    cashier_wallet: CashierWallet,
-    states: StateRegistry,
-    zk_bins: ZkContractTable,
-}
-
-impl Client {
-    fn new() -> Self {
-        // For this early demo we store all wallets in a single Client.
-        let dao_wallet = DaoWallet::new();
-        let money_wallets = HashMap::new();
-        let cashier_wallet = CashierWallet::new();
-
-        // Lookup table for smart contract states
-        let states = StateRegistry::new();
-
-        // Initialize ZK binary table
-        let zk_bins = ZkContractTable::new();
-
-        Self { dao_wallet, money_wallets, cashier_wallet, states, zk_bins }
-    }
-
-    // Load ZK contracts into the ZkContractTable and initialize the StateRegistry.
-    fn init(&mut self) -> Result<()> {
-        //We use these to initialize the money state.
-        let faucet_signature_secret = SecretKey::random(&mut OsRng);
-        let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
-
-        debug!(target: "demo", "Loading dao-mint.zk");
-        let zk_dao_mint_bincode = include_bytes!("../proof/dao-mint.zk.bin");
-        let zk_dao_mint_bin = ZkBinary::decode(zk_dao_mint_bincode)?;
-        self.zk_bins.add_contract("dao-mint".to_string(), zk_dao_mint_bin, 13);
-
-        debug!(target: "demo", "Loading money-transfer contracts");
-        let start = Instant::now();
-        let mint_pk = ProvingKey::build(11, &MintContract::default());
-        debug!("Mint PK: [{:?}]", start.elapsed());
-        let start = Instant::now();
-        let burn_pk = ProvingKey::build(11, &BurnContract::default());
-        debug!("Burn PK: [{:?}]", start.elapsed());
-        let start = Instant::now();
-        let mint_vk = VerifyingKey::build(11, &MintContract::default());
-        debug!("Mint VK: [{:?}]", start.elapsed());
-        let start = Instant::now();
-        let burn_vk = VerifyingKey::build(11, &BurnContract::default());
-        debug!("Burn VK: [{:?}]", start.elapsed());
-
-        self.zk_bins.add_native("money-transfer-mint".to_string(), mint_pk, mint_vk);
-        self.zk_bins.add_native("money-transfer-burn".to_string(), burn_pk, burn_vk);
-        debug!(target: "demo", "Loading dao-propose-main.zk");
-        let zk_dao_propose_main_bincode = include_bytes!("../proof/dao-propose-main.zk.bin");
-        let zk_dao_propose_main_bin = ZkBinary::decode(zk_dao_propose_main_bincode)?;
-        self.zk_bins.add_contract("dao-propose-main".to_string(), zk_dao_propose_main_bin, 13);
-        debug!(target: "demo", "Loading dao-propose-burn.zk");
-        let zk_dao_propose_burn_bincode = include_bytes!("../proof/dao-propose-burn.zk.bin");
-        let zk_dao_propose_burn_bin = ZkBinary::decode(zk_dao_propose_burn_bincode)?;
-        self.zk_bins.add_contract("dao-propose-burn".to_string(), zk_dao_propose_burn_bin, 13);
-        debug!(target: "demo", "Loading dao-vote-main.zk");
-        let zk_dao_vote_main_bincode = include_bytes!("../proof/dao-vote-main.zk.bin");
-        let zk_dao_vote_main_bin = ZkBinary::decode(zk_dao_vote_main_bincode)?;
-        self.zk_bins.add_contract("dao-vote-main".to_string(), zk_dao_vote_main_bin, 13);
-        debug!(target: "demo", "Loading dao-vote-burn.zk");
-        let zk_dao_vote_burn_bincode = include_bytes!("../proof/dao-vote-burn.zk.bin");
-        let zk_dao_vote_burn_bin = ZkBinary::decode(zk_dao_vote_burn_bincode)?;
-        self.zk_bins.add_contract("dao-vote-burn".to_string(), zk_dao_vote_burn_bin, 13);
-        let zk_dao_exec_bincode = include_bytes!("../proof/dao-exec.zk.bin");
-        let zk_dao_exec_bin = ZkBinary::decode(zk_dao_exec_bincode)?;
-        self.zk_bins.add_contract("dao-exec".to_string(), zk_dao_exec_bin, 13);
-
-        let cashier_signature_public = self.cashier_wallet.signature_public();
-
-        let money_state =
-            money::state::State::new(cashier_signature_public, faucet_signature_public);
-        self.states.register(*money::CONTRACT_ID, money_state);
-
-        let dao_state = dao::State::new();
-        self.states.register(*dao::CONTRACT_ID, dao_state);
-
-        Ok(())
-    }
-
-    fn create_dao(
-        &mut self,
-        dao_proposer_limit: u64,
-        dao_quorum: u64,
-        dao_approval_ratio_quot: u64,
-        dao_approval_ratio_base: u64,
-        token_id: TokenId,
-    ) -> DaoResult<pallas::Base> {
-        let tx = self.dao_wallet.mint_tx(
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            token_id,
-            &self.zk_bins,
-        );
-
-        self.validate(&tx)?;
-        // Only witness the value once the transaction is confirmed.
-        self.dao_wallet.update_witness(&mut self.states)?;
-
-        // Retrieve DAO bulla from the state.
-        let dao_bulla = {
-            let func_call = &tx.func_calls[0];
-            let call_data = func_call.call_data.as_any();
-            let call_data = call_data.downcast_ref::<dao::mint::validate::CallData>().unwrap();
-            call_data.dao_bulla.clone()
-        };
-
-        debug!(target: "demo", "Create DAO bulla: {:?}", dao_bulla.0);
-
-        // We store these values in a vector we can easily retrieve DAO values for the demo.
-        let dao_params = DaoParams {
-            proposer_limit: dao_proposer_limit,
-            quorum: dao_quorum,
-            approval_ratio_quot: dao_approval_ratio_quot,
-            approval_ratio_base: dao_approval_ratio_base,
-            gov_token_id: token_id,
-            public_key: self.dao_wallet.keypair.public,
-            bulla_blind: self.dao_wallet.bulla_blind,
-        };
-
-        self.dao_wallet.params.push(dao_params);
-        self.dao_wallet.bullas.push(dao_bulla.clone());
-
-        Ok(dao_bulla.0)
-    }
-
-    fn mint_treasury(
-        &mut self,
-        token_id: TokenId,
-        token_supply: u64,
-        recipient: PublicKey,
-    ) -> DaoResult<()> {
-        self.dao_wallet.track(&mut self.states)?;
-
-        let tx = self.cashier_wallet.mint(
-            token_id,
-            token_supply,
-            self.dao_wallet.bullas[0].0,
-            recipient,
-            &self.zk_bins,
-        )?;
-
-        self.validate(&tx)?;
-        self.update_wallets()?;
-
-        Ok(())
-    }
-
-    fn airdrop_user(&mut self, value: u64, token_id: TokenId, addr: PublicKey) -> DaoResult<()> {
-        // let wallet = self.money_wallets.get(&nym).unwrap();
-        // let addr = wallet.get_public_key();
-
-        let tx = self.cashier_wallet.airdrop(value, token_id, addr, &self.zk_bins)?;
-        self.validate(&tx)?;
-        self.update_wallets()?;
-
-        Ok(())
-    }
-
-    fn validate(&mut self, tx: &Transaction) -> DaoResult<()> {
-        debug!(target: "dao_demo::client::validate()", "commencing validate sequence");
-        let mut updates = vec![];
-
-        // Validate all function calls in the tx
-        for (idx, func_call) in tx.func_calls.iter().enumerate() {
-            // So then the verifier will lookup the corresponding state_transition and apply
-            // functions based off the func_id
-
-            if func_call.func_id == *money::transfer::FUNC_ID {
-                debug!("money_contract::transfer::state_transition()");
-                match money::transfer::validate::state_transition(&self.states, idx, tx) {
-                    Ok(update) => {
-                        updates.push(update);
-                    }
-                    Err(e) => return Err(DaoError::StateTransitionFailed(e.to_string())),
-                }
-            } else if func_call.func_id == *dao::mint::FUNC_ID {
-                debug!("dao_contract::mint::state_transition()");
-                match dao::mint::validate::state_transition(&self.states, idx, tx) {
-                    Ok(update) => {
-                        updates.push(update);
-                    }
-                    Err(e) => return Err(DaoError::StateTransitionFailed(e.to_string())),
-                }
-            } else if func_call.func_id == *dao::propose::FUNC_ID {
-                debug!(target: "demo", "dao_contract::propose::state_transition()");
-                match dao::propose::validate::state_transition(&self.states, idx, tx) {
-                    Ok(update) => {
-                        updates.push(update);
-                    }
-                    Err(e) => return Err(DaoError::StateTransitionFailed(e.to_string())),
-                }
-            } else if func_call.func_id == *dao::vote::FUNC_ID {
-                debug!(target: "demo", "dao_contract::vote::state_transition()");
-                match dao::vote::validate::state_transition(&self.states, idx, tx) {
-                    Ok(update) => {
-                        updates.push(update);
-                    }
-                    Err(e) => return Err(DaoError::StateTransitionFailed(e.to_string())),
-                }
-            } else if func_call.func_id == *dao::exec::FUNC_ID {
-                debug!("dao_contract::exec::state_transition()");
-                match dao::exec::validate::state_transition(&self.states, idx, tx) {
-                    Ok(update) => {
-                        updates.push(update);
-                    }
-                    Err(e) => return Err(DaoError::StateTransitionFailed(e.to_string())),
-                }
-            }
-        }
-
-        // Atomically apply all changes
-        for update in updates {
-            update.apply(&mut self.states);
-        }
-
-        tx.zk_verify(&self.zk_bins)?;
-        tx.verify_sigs();
-
-        Ok(())
-    }
-
-    fn update_wallets(&mut self) -> DaoResult<()> {
-        let state = self
-            .states
-            .lookup_mut::<money::State>(*money::CONTRACT_ID)
-            .ok_or(DaoError::StateNotFound)?;
-
-        let dao_coins = state.wallet_cache.get_received(&self.dao_wallet.keypair.secret);
-        for coin in dao_coins {
-            let note = coin.note.clone();
-            let (pub_x, pub_y) = self.dao_wallet.keypair.public.xy();
-
-            let coin_hash = poseidon_hash::<8>([
-                pub_x,
-                pub_y,
-                DrkValue::from(note.value),
-                note.token_id.inner(),
-                note.serial,
-                note.spend_hook,
-                note.user_data,
-                note.coin_blind,
-            ]);
-
-            assert_eq!(coin_hash, coin.coin.0);
-            assert_eq!(note.spend_hook, *dao::exec::FUNC_ID);
-            assert_eq!(note.user_data, self.dao_wallet.bullas[0].0);
-
-            self.dao_wallet.own_coins.push((coin, false));
-            debug!("DAO received a coin worth {} xDRK", note.value);
-        }
-
-        for wallet in self.money_wallets.values_mut() {
-            let coins = state.wallet_cache.get_received(&wallet.keypair.secret);
-            for coin in coins {
-                let note = coin.note.clone();
-                let (pub_x, pub_y) = wallet.keypair.public.xy();
-
-                let coin_hash = poseidon_hash::<8>([
-                    pub_x,
-                    pub_y,
-                    DrkValue::from(note.value),
-                    note.token_id.inner(),
-                    note.serial,
-                    note.spend_hook,
-                    note.user_data,
-                    note.coin_blind,
-                ]);
-
-                assert_eq!(coin_hash, coin.coin.0);
-                wallet.own_coins.push((coin, false));
-            }
-        }
-
-        Ok(())
-    }
-
-    fn propose(
-        &mut self,
-        recipient: PublicKey,
-        token_id: TokenId,
-        amount: u64,
-        sender: PublicKey,
-    ) -> DaoResult<pallas::Base> {
-        let params = self.dao_wallet.params[0].clone();
-
-        let dao_leaf_position = self.dao_wallet.leaf_position;
-
-        // To be able to make a proposal, we must prove we have ownership
-        // of governance tokens, and that the quantity of governance
-        // tokens is within the accepted proposer limit.
-        let sender_wallet = self.money_wallets.get_mut(&sender.to_bytes());
-        if sender_wallet.is_none() {
-            return Err(DaoError::NoWalletFound)
-        }
-        let sender_wallet = sender_wallet.unwrap();
-
-        let tx = sender_wallet.propose_tx(
-            params,
-            recipient,
-            token_id,
-            amount,
-            dao_leaf_position,
-            &self.zk_bins,
-            &mut self.states,
-        )?;
-
-        self.validate(&tx)?;
-        self.update_wallets()?;
-
-        let proposal_bulla = self.dao_wallet.store_proposal(&tx)?;
-
-        Ok(proposal_bulla)
-    }
-
-    fn cast_vote(&mut self, pubkey: PublicKey, vote: bool) -> DaoResult<()> {
-        let dao_key = self.dao_wallet.keypair;
-        if self.dao_wallet.proposals.is_empty() {
-            return Err(DaoError::NoProposals)
-        }
-        let proposal = self.dao_wallet.proposals[0].clone();
-
-        if self.dao_wallet.params.is_empty() {
-            return Err(DaoError::DaoNotConfigured)
-        }
-        let dao_params = self.dao_wallet.params[0].clone();
-        let dao_keypair = self.dao_wallet.keypair;
-
-        let voter_wallet = self.money_wallets.get_mut(&pubkey.to_bytes());
-        if voter_wallet.is_none() {
-            return Err(DaoError::NoWalletFound)
-        }
-        let voter_wallet = voter_wallet.unwrap();
-
-        let tx = voter_wallet.vote_tx(
-            vote,
-            dao_key,
-            proposal,
-            dao_params,
-            dao_keypair,
-            &self.zk_bins,
-            &mut self.states,
-        )?;
-
-        self.validate(&tx)?;
-        self.update_wallets()?;
-
-        self.dao_wallet.store_vote(&tx)?;
-
-        Ok(())
-    }
-
-    fn exec_proposal(&mut self, bulla: pallas::Base) -> DaoResult<()> {
-        if self.dao_wallet.proposals.is_empty() {
-            return Err(DaoError::NoProposals)
-        }
-        let proposal = self.dao_wallet.proposals[0].clone();
-
-        if self.dao_wallet.params.is_empty() {
-            return Err(DaoError::DaoNotConfigured)
-        }
-        let dao_params = self.dao_wallet.params[0].clone();
-
-        let tx = self.dao_wallet.exec_tx(
-            proposal,
-            bulla,
-            dao_params,
-            &self.zk_bins,
-            &mut self.states,
-        )?;
-
-        self.validate(&tx)?;
-        self.update_wallets()?;
-
-        Ok(())
-    }
-}
-
-struct DaoWallet {
-    keypair: Keypair,
-    signature_secret: SecretKey,
-    bulla_blind: pallas::Base,
-    leaf_position: Position,
-    proposal_bullas: Vec<pallas::Base>,
-    bullas: Vec<DaoBulla>,
-    params: Vec<DaoParams>,
-    own_coins: Vec<(OwnCoin, bool)>,
-    proposals: Vec<Proposal>,
-    vote_notes: Vec<dao::vote::wallet::Note>,
-}
-impl DaoWallet {
-    fn new() -> Self {
-        let keypair = Keypair::random(&mut OsRng);
-        let signature_secret = SecretKey::random(&mut OsRng);
-        let bulla_blind = pallas::Base::random(&mut OsRng);
-        let leaf_position = Position::zero();
-        let proposal_bullas = Vec::new();
-        let bullas = Vec::new();
-        let params = Vec::new();
-        let own_coins: Vec<(OwnCoin, bool)> = Vec::new();
-        let proposals: Vec<Proposal> = Vec::new();
-        let vote_notes = Vec::new();
-
-        Self {
-            keypair,
-            signature_secret,
-            bulla_blind,
-            leaf_position,
-            proposal_bullas,
-            bullas,
-            params,
-            own_coins,
-            proposals,
-            vote_notes,
-        }
-    }
-
-    fn get_public_key(&self) -> PublicKey {
-        self.keypair.public
-    }
-
-    fn track(&self, states: &mut StateRegistry) -> DaoResult<()> {
-        let state = states
-            .lookup_mut::<money::State>(*money::CONTRACT_ID)
-            .ok_or(DaoError::StateNotFound)?;
-
-        state.wallet_cache.track(self.keypair.secret);
-        Ok(())
-    }
-
-    // Mint the DAO bulla.
-    fn mint_tx(
-        &mut self,
-        dao_proposer_limit: u64,
-        dao_quorum: u64,
-        dao_approval_ratio_quot: u64,
-        dao_approval_ratio_base: u64,
-        token_id: TokenId,
-        zk_bins: &ZkContractTable,
-    ) -> Transaction {
-        debug!(target: "dao-demo::dao::mint_tx()", "START");
-        let builder = dao::mint::wallet::Builder {
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            gov_token_id: token_id,
-            dao_pubkey: self.keypair.public,
-            dao_bulla_blind: self.bulla_blind,
-            _signature_secret: self.signature_secret,
-        };
-        let func_call = builder.build(zk_bins);
-        let func_calls = vec![func_call];
-
-        let mut signatures = vec![];
-        for func_call in &func_calls {
-            let sig = sign(vec![self.signature_secret], func_call);
-            signatures.push(sig);
-        }
-
-        Transaction { func_calls, signatures }
-    }
-
-    fn update_witness(&mut self, states: &mut StateRegistry) -> DaoResult<()> {
-        let state =
-            states.lookup_mut::<dao::State>(*dao::CONTRACT_ID).ok_or(DaoError::StateNotFound)?;
-
-        let path =
-            state.dao_tree.witness().ok_or_else(|| Error::Custom("Tree is empty".to_owned()))?;
-        self.leaf_position = path;
-        Ok(())
-    }
-
-    fn balances(&self) -> Result<HashMap<String, u64>> {
-        let mut ret: HashMap<String, u64> = HashMap::new();
-        for (coin, is_spent) in &self.own_coins {
-            if *is_spent {}
-            if coin.note.token_id == *DRK_ID || coin.note.token_id == *GOV_ID {
-                let token_id = format!("{}", coin.note.token_id);
-                ret.insert(token_id, coin.note.value);
-            }
-        }
-        Ok(ret)
-    }
-
-    fn store_proposal(&mut self, tx: &Transaction) -> Result<pallas::Base> {
-        let (proposal, proposal_bulla) = {
-            let func_call = &tx.func_calls[0];
-            let call_data = func_call.call_data.as_any();
-            let call_data = call_data.downcast_ref::<dao::propose::validate::CallData>().unwrap();
-
-            let header = &call_data.header;
-            let note: dao::propose::wallet::Note = header.enc_note.decrypt(&self.keypair.secret)?;
-
-            // Return the proposal info
-            (note.proposal, call_data.header.proposal_bulla)
-        };
-        debug!(target: "demo", "Proposal now active!");
-        debug!(target: "demo", "  destination: {:?}", proposal.dest);
-        debug!(target: "demo", "  amount: {}", proposal.amount);
-        debug!(target: "demo", "  token_id: {:?}", proposal.token_id);
-        debug!(target: "demo", "Proposal bulla: {:?}", proposal_bulla);
-
-        self.proposals.push(proposal);
-        self.proposal_bullas.push(proposal_bulla);
-
-        Ok(proposal_bulla)
-    }
-
-    // We decrypt the votes in a transaction and add it to the wallet.
-    fn store_vote(&mut self, tx: &Transaction) -> Result<()> {
-        let vote_note = {
-            let func_call = &tx.func_calls[0];
-            let call_data = func_call.call_data.as_any();
-            let call_data = call_data.downcast_ref::<dao::vote::validate::CallData>().unwrap();
-
-            let header = &call_data.header;
-            let note: dao::vote::wallet::Note = header.enc_note.decrypt(&self.keypair.secret)?;
-            note
-        };
-
-        self.vote_notes.push(vote_note);
-
-        Ok(())
-    }
-
-    fn get_proposals(&self) -> &Vec<Proposal> {
-        &self.proposals
-    }
-
-    fn get_votes(&self) -> &Vec<dao::vote::wallet::Note> {
-        &self.vote_notes
-    }
-
-    fn get_treasury_path(
-        &self,
-        own_coin: &OwnCoin,
-        states: &StateRegistry,
-    ) -> DaoResult<(Position, Vec<MerkleNode>)> {
-        let (money_leaf_position, money_merkle_path) = {
-            let state = states
-                .lookup::<money::State>(*money::CONTRACT_ID)
-                .ok_or(DaoError::StateNotFound)?;
-
-            let tree = &state.tree;
-            let leaf_position = own_coin.leaf_position;
-            let root = tree.root(0).ok_or_else(|| {
-                Error::Custom(
-                    "Not enough checkpoints available to reach the requested checkpoint depth."
-                        .to_owned(),
-                )
-            })?;
-            let merkle_path = tree
-                .authentication_path(leaf_position, &root)
-                .ok_or_else(|| Error::Custom("No available authentication path to that position or if the root does not correspond to a checkpointed root of the tree".to_owned()))?;
-            (leaf_position, merkle_path)
-        };
-
-        Ok((money_leaf_position, money_merkle_path))
-    }
-
-    fn exec_tx(
-        &self,
-        proposal: Proposal,
-        _proposal_bulla: pallas::Base,
-        dao_params: DaoParams,
-        zk_bins: &ZkContractTable,
-        states: &mut StateRegistry,
-    ) -> DaoResult<Transaction> {
-        let dao_bulla = self.bullas[0].clone();
-
-        let mut inputs = Vec::new();
-        let mut total_input_value = 0;
-
-        let tx_signature_secret = SecretKey::random(&mut OsRng);
-        let exec_signature_secret = SecretKey::random(&mut OsRng);
-
-        let user_serial = pallas::Base::random(&mut OsRng);
-        let user_coin_blind = pallas::Base::random(&mut OsRng);
-        let user_data_blind = pallas::Base::random(&mut OsRng);
-        let input_value_blind = pallas::Scalar::random(&mut OsRng);
-        let dao_serial = pallas::Base::random(&mut OsRng);
-        let dao_coin_blind = pallas::Base::random(&mut OsRng);
-        // disabled
-        let user_spend_hook = pallas::Base::from(0);
-        let user_data = pallas::Base::from(0);
-
-        for (coin, is_spent) in &self.own_coins {
-            let is_spent = *is_spent;
-            if is_spent {
-                continue
-            }
-            let (treasury_leaf_position, treasury_merkle_path) =
-                self.get_treasury_path(coin, states)?;
-
-            let input_value = coin.note.value;
-
-            let input = {
-                money::transfer::wallet::BuilderInputInfo {
-                    leaf_position: treasury_leaf_position,
-                    merkle_path: treasury_merkle_path,
-                    secret: self.keypair.secret,
-                    note: coin.note.clone(),
-                    user_data_blind,
-                    value_blind: input_value_blind,
-                    signature_secret: tx_signature_secret,
-                }
-            };
-            total_input_value += input_value;
-            inputs.push(input);
-        }
-
-        let builder = {
-            money::transfer::wallet::Builder {
-                clear_inputs: vec![],
-                inputs,
-                outputs: vec![
-                    // Sending money
-                    money::transfer::wallet::BuilderOutputInfo {
-                        value: proposal.amount,
-                        token_id: proposal.token_id,
-                        public: proposal.dest,
-                        serial: proposal.serial,
-                        coin_blind: proposal.blind,
-                        spend_hook: user_spend_hook,
-                        user_data,
-                    },
-                    // Change back to DAO
-                    money::transfer::wallet::BuilderOutputInfo {
-                        value: total_input_value - proposal.amount,
-                        token_id: *DRK_ID,
-                        public: self.keypair.public,
-                        serial: dao_serial,
-                        coin_blind: dao_coin_blind,
-                        spend_hook: *dao::exec::FUNC_ID,
-                        user_data: dao_bulla.0,
-                    },
-                ],
-            }
-        };
-
-        let transfer_func_call = builder.build(zk_bins)?;
-
-        let mut yes_votes_value = 0;
-        let mut yes_votes_blind = pallas::Scalar::from(0);
-        let mut yes_votes_commit = pallas::Point::identity();
-
-        let mut all_votes_value = 0;
-        let mut all_votes_blind = pallas::Scalar::from(0);
-        let mut all_votes_commit = pallas::Point::identity();
-
-        for (i, note) in self.vote_notes.iter().enumerate() {
-            let vote_commit = pedersen_commitment_u64(note.vote_value, note.vote_value_blind);
-
-            all_votes_commit += vote_commit;
-            all_votes_blind += note.vote_value_blind;
-
-            let yes_vote_commit = pedersen_commitment_u64(
-                note.vote.vote_option as u64 * note.vote_value,
-                note.vote.vote_option_blind,
-            );
-
-            yes_votes_commit += yes_vote_commit;
-            yes_votes_blind += note.vote.vote_option_blind;
-
-            let vote_option = note.vote.vote_option;
-
-            if vote_option {
-                yes_votes_value += note.vote_value;
-            }
-            all_votes_value += note.vote_value;
-            let vote_result: String =
-                if vote_option { "yes".to_string() } else { "no".to_string() };
-
-            debug!("Voter {} voted {}", i, vote_result);
-        }
-
-        debug!("Outcome = {} / {}", yes_votes_value, all_votes_value);
-
-        assert!(all_votes_commit == pedersen_commitment_u64(all_votes_value, all_votes_blind));
-        assert!(yes_votes_commit == pedersen_commitment_u64(yes_votes_value, yes_votes_blind));
-
-        let builder = {
-            dao::exec::wallet::Builder {
-                proposal,
-                dao: dao_params,
-                yes_votes_value,
-                all_votes_value,
-                yes_votes_blind,
-                all_votes_blind,
-                user_serial,
-                user_coin_blind,
-                dao_serial,
-                dao_coin_blind,
-                input_value: total_input_value,
-                input_value_blind,
-                hook_dao_exec: *dao::exec::FUNC_ID,
-                signature_secret: exec_signature_secret,
-            }
-        };
-
-        let exec_func_call = builder.build(zk_bins);
-        let func_calls = vec![transfer_func_call, exec_func_call];
-
-        let mut signatures = vec![];
-        for func_call in &func_calls {
-            let sig = sign(vec![self.signature_secret], func_call);
-            signatures.push(sig);
-        }
-
-        Ok(Transaction { func_calls, signatures })
-    }
-}
-
-// Stores governance tokens and related secret values.
-struct MoneyWallet {
-    keypair: Keypair,
-    signature_secret: SecretKey,
-    own_coins: Vec<(OwnCoin, bool)>,
-}
-
-impl MoneyWallet {
-    // fn signature_public(&self) -> PublicKey {
-    //     PublicKey::from_secret(self.signature_secret)
-    // }
-
-    // fn get_public_key(&self) -> PublicKey {
-    //     self.keypair.public
-    // }
-
-    fn track(&self, states: &mut StateRegistry) -> DaoResult<()> {
-        let state = states
-            .lookup_mut::<money::State>(*money::CONTRACT_ID)
-            .ok_or(DaoError::StateNotFound)?;
-
-        state.wallet_cache.track(self.keypair.secret);
-        Ok(())
-    }
-
-    fn balances(&self) -> Result<HashMap<String, u64>> {
-        let mut ret: HashMap<String, u64> = HashMap::new();
-        for (coin, is_spent) in &self.own_coins {
-            if *is_spent {}
-            if coin.note.token_id == *DRK_ID || coin.note.token_id == *GOV_ID {
-                let token_id = format!("{}", coin.note.token_id);
-                ret.insert(token_id, coin.note.value);
-            }
-        }
-        Ok(ret)
-    }
-
-    fn propose_tx(
-        &mut self,
-        params: DaoParams,
-        recipient: PublicKey,
-        token_id: TokenId,
-        amount: u64,
-        dao_leaf_position: Position,
-        zk_bins: &ZkContractTable,
-        states: &mut StateRegistry,
-    ) -> DaoResult<Transaction> {
-        let mut inputs = Vec::new();
-
-        for (coin, is_spent) in &self.own_coins {
-            let is_spent = *is_spent;
-            if is_spent {
-                continue
-            }
-            let (money_leaf_position, money_merkle_path) = self.get_path(states, coin).unwrap();
-
-            let input = {
-                dao::propose::wallet::BuilderInput {
-                    secret: self.keypair.secret,
-                    note: coin.note.clone(),
-                    leaf_position: money_leaf_position,
-                    merkle_path: money_merkle_path,
-                    signature_secret: self.signature_secret,
-                }
-            };
-            inputs.push(input);
-        }
-
-        let (dao_merkle_path, dao_merkle_root) = {
-            let state =
-                states.lookup::<dao::State>(*dao::CONTRACT_ID).ok_or(DaoError::StateNotFound)?;
-            let tree = &state.dao_tree;
-            let root = tree.root(0).ok_or_else(|| {
-                Error::Custom(
-                    "Not enough checkpoints available to reach the requested checkpoint depth."
-                        .to_owned(),
-                )
-            })?;
-            let merkle_path = tree.authentication_path(dao_leaf_position, &root)
-            .ok_or_else(|| Error::Custom(
-                "No available authentication path to that position or if the root does not correspond to a checkpointed root of the tree"
-                .to_owned()
-            ))?;
-            (merkle_path, root)
-        };
-
-        let proposal = {
-            dao::propose::wallet::Proposal {
-                dest: recipient,
-                amount,
-                serial: pallas::Base::random(&mut OsRng),
-                token_id,
-                blind: pallas::Base::random(&mut OsRng),
-            }
-        };
-
-        let builder = dao::propose::wallet::Builder {
-            inputs,
-            proposal,
-            dao: params,
-            dao_leaf_position,
-            dao_merkle_path,
-            dao_merkle_root,
-        };
-
-        let func_call = builder.build(zk_bins);
-        let func_calls = vec![func_call];
-
-        let mut signatures = vec![];
-        for func_call in &func_calls {
-            let sig = sign(vec![self.signature_secret], func_call);
-            signatures.push(sig);
-        }
-
-        Ok(Transaction { func_calls, signatures })
-    }
-
-    fn get_path(
-        &self,
-        states: &StateRegistry,
-        own_coin: &OwnCoin,
-    ) -> DaoResult<(Position, Vec<MerkleNode>)> {
-        let (money_leaf_position, money_merkle_path) = {
-            let state = states
-                .lookup::<money::State>(*money::CONTRACT_ID)
-                .ok_or(DaoError::StateNotFound)?;
-
-            let tree = &state.tree;
-            let leaf_position = own_coin.leaf_position;
-            let root = tree.root(0).ok_or_else(|| {
-                Error::Custom(
-                    "Not enough checkpoints available to reach the requested checkpoint depth."
-                        .to_owned(),
-                )
-            })?;
-            let merkle_path = tree.authentication_path(leaf_position, &root).ok_or_else(|| Error::Custom(
-                "No available authentication path to that position or the root does not correspond to a checkpointed root of the tree"
-                .to_owned()
-            ))?;
-            (leaf_position, merkle_path)
-        };
-
-        Ok((money_leaf_position, money_merkle_path))
-    }
-
-    fn vote_tx(
-        &mut self,
-        vote_option: bool,
-        _dao_key: Keypair,
-        proposal: Proposal,
-        dao_params: DaoParams,
-        dao_keypair: Keypair,
-        zk_bins: &ZkContractTable,
-        states: &mut StateRegistry,
-    ) -> Result<Transaction> {
-        let mut inputs = Vec::new();
-
-        // We must prove we have sufficient governance tokens in order to vote.
-        for (coin, _is_spent) in &self.own_coins {
-            let (money_leaf_position, money_merkle_path) = self.get_path(states, coin).unwrap();
-
-            let input = {
-                dao::vote::wallet::BuilderInput {
-                    secret: self.keypair.secret,
-                    note: coin.note.clone(),
-                    leaf_position: money_leaf_position,
-                    merkle_path: money_merkle_path,
-                    signature_secret: self.signature_secret,
-                }
-            };
-            inputs.push(input);
-        }
-
-        let builder = {
-            dao::vote::wallet::Builder {
-                inputs,
-                vote: dao::vote::wallet::Vote {
-                    vote_option,
-                    vote_option_blind: pallas::Scalar::random(&mut OsRng),
-                },
-                // For this demo votes are encrypted for the DAO.
-                vote_keypair: dao_keypair,
-                proposal,
-                dao: dao_params,
-            }
-        };
-
-        let func_call = builder.build(zk_bins);
-        let func_calls = vec![func_call];
-
-        let mut signatures = vec![];
-        for func_call in &func_calls {
-            let sig = sign(vec![self.signature_secret], func_call);
-            signatures.push(sig);
-        }
-
-        Ok(Transaction { func_calls, signatures })
-    }
-}
-
-async fn start_rpc(client: Client) -> Result<()> {
-    let rpc_addr = Url::parse("tcp://127.0.0.1:7777")?;
-
-    let rpc_client = JsonRpcInterface::new(client);
-
-    let rpc_interface = Arc::new(rpc_client);
-
-    listen_and_serve(rpc_addr, rpc_interface).await?;
-    Ok(())
-}
-
-// Mint authority that mints the DAO treasury and airdrops governance tokens.
-#[derive(Clone)]
-struct CashierWallet {
-    // keypair: Keypair,
-    signature_secret: SecretKey,
-}
-
-impl CashierWallet {
-    fn new() -> Self {
-        // let keypair = Keypair::random(&mut OsRng);
-        let signature_secret = SecretKey::random(&mut OsRng);
-        // Self { keypair, signature_secret }
-        Self { signature_secret }
-    }
-
-    fn signature_public(&self) -> PublicKey {
-        PublicKey::from_secret(self.signature_secret)
-    }
-
-    fn mint(
-        &mut self,
-        token_id: TokenId,
-        token_supply: u64,
-        dao_bulla: pallas::Base,
-        recipient: PublicKey,
-        zk_bins: &ZkContractTable,
-    ) -> Result<Transaction> {
-        let spend_hook = *dao::exec::FUNC_ID;
-        let user_data = dao_bulla;
-        let value = token_supply;
-
-        let tx = self.transfer_tx(value, token_id, spend_hook, user_data, recipient, zk_bins)?;
-
-        Ok(tx)
-    }
-
-    fn transfer_tx(
-        &self,
-        value: u64,
-        token_id: TokenId,
-        spend_hook: pallas::Base,
-        user_data: pallas::Base,
-        recipient: PublicKey,
-        zk_bins: &ZkContractTable,
-    ) -> Result<Transaction> {
-        let builder = {
-            money::transfer::wallet::Builder {
-                clear_inputs: vec![money::transfer::wallet::BuilderClearInputInfo {
-                    value,
-                    token_id,
-                    signature_secret: self.signature_secret,
-                }],
-                inputs: vec![],
-                outputs: vec![money::transfer::wallet::BuilderOutputInfo {
-                    value,
-                    token_id,
-                    public: recipient,
-                    serial: pallas::Base::random(&mut OsRng),
-                    coin_blind: pallas::Base::random(&mut OsRng),
-                    spend_hook,
-                    user_data,
-                }],
-            }
-        };
-        let func_call = builder.build(zk_bins)?;
-        let func_calls = vec![func_call];
-
-        let mut signatures = vec![];
-        for func_call in &func_calls {
-            let sig = sign(vec![self.signature_secret], func_call);
-            signatures.push(sig);
-        }
-
-        Ok(Transaction { func_calls, signatures })
-    }
-
-    fn airdrop(
-        &mut self,
-        value: u64,
-        token_id: TokenId,
-        recipient: PublicKey,
-        zk_bins: &ZkContractTable,
-    ) -> Result<Transaction> {
-        // Spend hook and user data disabled
-        let spend_hook = DrkSpendHook::from(0);
-        let user_data = DrkUserData::from(0);
-
-        let tx = self.transfer_tx(value, token_id, spend_hook, user_data, recipient, zk_bins)?;
-
-        Ok(tx)
-    }
-}
-
-#[async_std::main]
-async fn main() -> Result<()> {
-    TermLogger::init(
-        LevelFilter::Debug,
-        simplelog::Config::default(),
-        TerminalMode::Mixed,
-        ColorChoice::Auto,
-    )?;
-
-    let mut client = Client::new();
-    client.init()?;
-
-    start_rpc(client).await?;
-
-    Ok(())
-}

+ 0 - 122
bin/dao/daod/src/note.rs

@@ -1,122 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, KeyInit};
-use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::diffie_hellman::{kdf_sapling, sapling_ka_agree},
-    Error, Result,
-};
-use darkfi_sdk::{
-    crypto::{PublicKey, SecretKey},
-    pasta::pallas,
-};
-
-pub const AEAD_TAG_SIZE: usize = 16;
-
-pub fn encrypt<T: Encodable>(note: &T, public: &PublicKey) -> Result<EncryptedNote2> {
-    let ephem_secret = SecretKey::random(&mut OsRng);
-    let ephem_public = PublicKey::from_secret(ephem_secret);
-    let shared_secret = sapling_ka_agree(&ephem_secret, public);
-    let key = kdf_sapling(&shared_secret, &ephem_public);
-
-    let mut input = Vec::new();
-    note.encode(&mut input)?;
-    let input_len = input.len();
-
-    let mut ciphertext = vec![0_u8; input_len + AEAD_TAG_SIZE];
-    ciphertext[..input_len].copy_from_slice(&input);
-
-    ChaCha20Poly1305::new(key.as_ref().into())
-        .encrypt_in_place([0u8; 12][..].into(), &[], &mut ciphertext)
-        .unwrap();
-
-    Ok(EncryptedNote2 { ciphertext, ephem_public })
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct EncryptedNote2 {
-    ciphertext: Vec<u8>,
-    ephem_public: PublicKey,
-}
-
-impl EncryptedNote2 {
-    pub fn decrypt<T: Decodable>(&self, secret: &SecretKey) -> Result<T> {
-        let shared_secret = sapling_ka_agree(secret, &self.ephem_public);
-        let key = kdf_sapling(&shared_secret, &self.ephem_public);
-
-        let ciphertext_len = self.ciphertext.len();
-        let mut plaintext = vec![0_u8; ciphertext_len];
-        plaintext.copy_from_slice(&self.ciphertext);
-
-        match ChaCha20Poly1305::new(key.as_ref().into()).decrypt_in_place(
-            [0u8; 12][..].into(),
-            &[],
-            &mut plaintext,
-        ) {
-            Ok(()) => {
-                Ok(T::decode(&plaintext[..ciphertext_len - AEAD_TAG_SIZE]).map_err(Error::from)?)
-            }
-            Err(e) => Err(Error::NoteDecryptionFailed(e.to_string())),
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use darkfi::crypto::types::{DrkCoinBlind, DrkSerial, DrkValueBlind};
-    use darkfi_sdk::{
-        crypto::{Keypair, TokenId},
-        pasta::group::ff::Field,
-    };
-
-    #[test]
-    fn test_note_encdec() {
-        #[derive(SerialEncodable, SerialDecodable)]
-        struct MyNote {
-            serial: DrkSerial,
-            value: u64,
-            token_id: TokenId,
-            coin_blind: DrkCoinBlind,
-            value_blind: DrkValueBlind,
-            token_blind: DrkValueBlind,
-            memo: Vec<u8>,
-        }
-        let note = MyNote {
-            serial: DrkSerial::random(&mut OsRng),
-            value: 110,
-            token_id: TokenId::from(pallas::Base::random(&mut OsRng)),
-            coin_blind: DrkCoinBlind::random(&mut OsRng),
-            value_blind: DrkValueBlind::random(&mut OsRng),
-            token_blind: DrkValueBlind::random(&mut OsRng),
-            memo: vec![32, 223, 231, 3, 1, 1],
-        };
-
-        let keypair = Keypair::random(&mut OsRng);
-
-        let encrypted_note = encrypt(&note, &keypair.public).unwrap();
-        let note2: MyNote = encrypted_note.decrypt(&keypair.secret).unwrap();
-        assert_eq!(note.value, note2.value);
-        assert_eq!(note.token_id, note2.token_id);
-        assert_eq!(note.token_blind, note2.token_blind);
-        assert_eq!(note.memo, note2.memo);
-    }
-}

+ 0 - 453
bin/dao/daod/src/rpc.rs

@@ -1,453 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{str::FromStr, sync::Arc};
-
-use async_std::sync::Mutex;
-use async_trait::async_trait;
-use darkfi_sdk::{
-    crypto::{Keypair, PublicKey, SecretKey},
-    pasta::group::ff::PrimeField,
-};
-use log::{debug, error};
-use rand::rngs::OsRng;
-use serde_json::{json, Value};
-
-use darkfi::rpc::{
-    jsonrpc::{ErrorCode::*, JsonError, JsonRequest, JsonResponse, JsonResult},
-    server::RequestHandler,
-};
-
-use crate::{
-    contract::money::state::OwnCoin,
-    error::{server_error, RpcError},
-    util::{parse_b58, DRK_ID, GOV_ID},
-    Client, MoneyWallet,
-};
-
-pub struct JsonRpcInterface {
-    client: Arc<Mutex<Client>>,
-}
-
-#[async_trait]
-impl RequestHandler for JsonRpcInterface {
-    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        if !req.params.is_array() {
-            return JsonError::new(InvalidParams, None, req.id).into()
-        }
-
-        let params = req.params.as_array().unwrap();
-
-        debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
-
-        match req.method.as_str() {
-            Some("create") => return self.create_dao(req.id, params).await,
-            Some("get_dao_addr") => return self.get_dao_addr(req.id, params).await,
-            Some("get_votes") => return self.get_votes(req.id, params).await,
-            Some("get_proposals") => return self.get_proposals(req.id, params).await,
-            Some("dao_balance") => return self.dao_balance(req.id, params).await,
-            Some("dao_bulla") => return self.dao_bulla(req.id, params).await,
-            Some("user_balance") => return self.user_balance(req.id, params).await,
-            Some("mint") => return self.mint_treasury(req.id, params).await,
-            Some("keygen") => return self.keygen(req.id, params).await,
-            Some("airdrop") => return self.airdrop_tokens(req.id, params).await,
-            Some("propose") => return self.create_proposal(req.id, params).await,
-            Some("vote") => return self.vote(req.id, params).await,
-            Some("exec") => return self.execute(req.id, params).await,
-            Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
-        }
-    }
-}
-
-impl JsonRpcInterface {
-    pub fn new(client: Client) -> Self {
-        let client = Arc::new(Mutex::new(client));
-        Self { client }
-    }
-
-    // --> {"method": "create", "params": []}
-    // <-- {"result": "creating dao..."}
-    async fn create_dao(&self, id: Value, params: &[Value]) -> JsonResult {
-        let dao_proposer_limit = params[0].as_u64();
-        if dao_proposer_limit.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let dao_proposer_limit = dao_proposer_limit.unwrap();
-
-        let dao_quorum = params[1].as_u64();
-        if dao_quorum.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let dao_quorum = dao_quorum.unwrap();
-
-        let dao_approval_ratio_quot = params[2].as_u64();
-        if dao_approval_ratio_quot.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let dao_approval_ratio_quot = dao_approval_ratio_quot.unwrap();
-
-        let dao_approval_ratio_base = params[3].as_u64();
-        if dao_approval_ratio_base.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let dao_approval_ratio_base = dao_approval_ratio_base.unwrap();
-
-        let mut client = self.client.lock().await;
-
-        match client.create_dao(
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            *GOV_ID,
-        ) {
-            Ok(bulla) => {
-                let bulla: String = bs58::encode(bulla.to_repr()).into_string();
-                JsonResponse::new(json!(bulla), id).into()
-            }
-            Err(e) => {
-                error!("Failed to create DAO: {}", e);
-                server_error(RpcError::Create, id)
-            }
-        }
-    }
-
-    // --> {"method": "get_dao_addr", "params": []}
-    // <-- {"result": "getting dao public addr..."}
-    async fn get_dao_addr(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let pubkey = client.dao_wallet.get_public_key();
-        //let addr: String = bs58::encode(pubkey.to_bytes()).into_string();
-        let addr: String = pubkey.to_string();
-        JsonResponse::new(json!(addr), id).into()
-    }
-
-    // --> {"method": "get_dao_addr", "params": []}
-    // <-- {"result": "getting dao public addr..."}
-    async fn get_votes(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let vote_notes = client.dao_wallet.get_votes();
-        let mut vote_data = vec![];
-
-        for note in vote_notes {
-            let vote_option = note.vote.vote_option;
-            let vote_value = note.vote_value;
-            vote_data.push((vote_option, vote_value));
-        }
-
-        JsonResponse::new(json!(vote_data), id).into()
-    }
-
-    // --> {"method": "get_dao_addr", "params": []}
-    // <-- {"result": "getting dao public addr..."}
-    async fn get_proposals(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let proposals = client.dao_wallet.get_proposals();
-        let mut proposal_data = vec![];
-
-        for proposal in proposals {
-            let dest = proposal.dest;
-            let amount = proposal.amount;
-            let token_id = format!("{}", proposal.token_id);
-            //let dest: String = bs58::encode(dest.to_bytes()).into_string();
-            let dest = dest.to_string();
-            proposal_data.push((dest, amount, token_id));
-        }
-
-        JsonResponse::new(json!(proposal_data), id).into()
-    }
-
-    async fn dao_balance(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let balance = client.dao_wallet.balances().unwrap();
-        JsonResponse::new(json!(balance), id).into()
-    }
-
-    async fn dao_bulla(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let dao_bullas = client.dao_wallet.bullas.clone();
-        let mut bulla_vec = Vec::new();
-
-        for bulla in dao_bullas {
-            let dao_bulla: String = bs58::encode(bulla.0.to_repr()).into_string();
-            bulla_vec.push(dao_bulla);
-        }
-
-        JsonResponse::new(json!(bulla_vec), id).into()
-    }
-
-    async fn user_balance(&self, id: Value, params: &[Value]) -> JsonResult {
-        let client = self.client.lock().await;
-        let nym = params[0].as_str();
-        if nym.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let nym = nym.unwrap();
-
-        match PublicKey::from_str(nym) {
-            Ok(key) => match client.money_wallets.get(&key.to_bytes()) {
-                Some(wallet) => {
-                    let balance = wallet.balances().unwrap();
-                    JsonResponse::new(json!(balance), id).into()
-                }
-                None => {
-                    error!("No wallet found for provided key");
-                    server_error(RpcError::Balance, id)
-                }
-            },
-            Err(_) => {
-                error!("Could not parse PublicKey from string");
-                server_error(RpcError::Parse, id)
-            }
-        }
-    }
-
-    // --> {"method": "mint_treasury", "params": []}
-    // <-- {"result": "minting treasury..."}
-    async fn mint_treasury(&self, id: Value, params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-
-        let token_supply = params[0].as_u64();
-        if token_supply.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let token_supply = token_supply.unwrap();
-
-        let addr = params[1].as_str();
-        if addr.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let addr = addr.unwrap();
-
-        match PublicKey::from_str(addr) {
-            Ok(dao_addr) => match client.mint_treasury(*DRK_ID, token_supply, dao_addr) {
-                Ok(_) => JsonResponse::new(json!("DAO treasury minted successfully."), id).into(),
-                Err(e) => {
-                    error!("Failed to mint treasury: {}", e);
-                    server_error(RpcError::Mint, id)
-                }
-            },
-            Err(_) => {
-                error!("Failed to parse PublicKey from String");
-                server_error(RpcError::Parse, id)
-            }
-        }
-    }
-
-    // Create a new wallet for governance tokens.
-    async fn keygen(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-        // let nym = params[0].as_str().unwrap().to_string();
-
-        let keypair = Keypair::random(&mut OsRng);
-        let signature_secret = SecretKey::random(&mut OsRng);
-        let own_coins: Vec<(OwnCoin, bool)> = Vec::new();
-        let money_wallet = MoneyWallet { keypair, signature_secret, own_coins };
-
-        match money_wallet.track(&mut client.states) {
-            Ok(_) => {
-                client.money_wallets.insert(keypair.public.to_bytes(), money_wallet);
-                //let addr: String = bs58::encode(keypair.public.to_bytes()).into_string();
-                let addr: String = keypair.public.to_string();
-                JsonResponse::new(json!(addr), id).into()
-            }
-            Err(e) => {
-                error!("Failed to airdrop tokens: {}", e);
-                server_error(RpcError::Keygen, id)
-            }
-        }
-    }
-
-    // --> {"method": "airdrop_tokens", "params": []}
-    // <-- {"result": "airdropping tokens..."}
-    async fn airdrop_tokens(&self, id: Value, params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-        // let zk_bins = &client.zk_bins;
-
-        let addr = params[0].as_str();
-        if addr.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let addr = addr.unwrap();
-
-        let value = params[1].as_u64();
-        if value.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let value = value.unwrap();
-
-        match PublicKey::from_str(addr) {
-            Ok(key) => match client.airdrop_user(value, *GOV_ID, key) {
-                Ok(_) => JsonResponse::new(json!("Tokens airdropped successfully."), id).into(),
-                Err(e) => {
-                    error!("Failed to airdrop tokens: {}", e);
-                    server_error(RpcError::Airdrop, id)
-                }
-            },
-            Err(_) => {
-                error!("Failed parsing PublicKey from String");
-                server_error(RpcError::Parse, id)
-            }
-        }
-    }
-    // --> {"method": "create_proposal", "params": []}
-    // <-- {"result": "creating proposal..."}
-    async fn create_proposal(&self, id: Value, params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-
-        if params.is_empty() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-
-        let sender = params[0].as_str();
-        if sender.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let sender = sender.unwrap();
-
-        let recipient = params[1].as_str();
-        if recipient.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let recipient = recipient.unwrap();
-
-        let amount = params[2].as_u64();
-        if amount.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let amount = amount.unwrap();
-
-        let recv_addr = PublicKey::from_str(recipient);
-        if recv_addr.is_err() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let recv_addr = recv_addr.unwrap();
-
-        let sndr_addr = PublicKey::from_str(sender);
-        if sndr_addr.is_err() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let sndr_addr = sndr_addr.unwrap();
-
-        match client.propose(recv_addr, *DRK_ID, amount, sndr_addr) {
-            Ok(bulla) => {
-                let bulla: String = bs58::encode(bulla.to_repr()).into_string();
-
-                JsonResponse::new(json!(bulla), id).into()
-            }
-            Err(e) => {
-                error!("Failed to make Proposal: {}", e);
-                server_error(RpcError::Propose, id)
-            }
-        }
-    }
-    // --> {"method": "vote", "params": []}
-    // <-- {"result": "voting..."}
-    async fn vote(&self, id: Value, params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-        let mut vote_bool = true;
-
-        let addr = params[0].as_str();
-        if addr.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let addr = addr.unwrap();
-
-        let balance = match PublicKey::from_str(addr) {
-            Ok(key) => match client.money_wallets.get(&key.to_bytes()) {
-                Some(wallet) => {
-                    let balance = wallet.balances().unwrap();
-                    let token_id = format!("{}", *GOV_ID);
-                    if balance.get(&token_id).is_some() {
-                        *balance.get(&token_id).unwrap()
-                    } else {
-                        error!("Balance is empty");
-                        0
-                    }
-                }
-                None => {
-                    error!("No wallet found for provided key");
-                    0
-                }
-            },
-            Err(_) => {
-                error!("Could not parse PublicKey from string");
-                0
-            }
-        };
-
-        let vote_str = params[1].as_str();
-        if vote_str.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let vote_str = vote_str.unwrap();
-
-        match vote_str {
-            "yes" => {}
-            "no" => vote_bool = false,
-            _ => return JsonError::new(InvalidParams, None, id).into(),
-        }
-
-        match PublicKey::from_str(addr) {
-            Ok(key) => match client.cast_vote(key, vote_bool) {
-                Ok(_) => {
-                    let rep = format!(
-                        "Vote cast successfully, you voted {} with value {} GOV.",
-                        vote_str, balance
-                    );
-                    JsonResponse::new(json!(rep), id).into()
-                }
-                Err(e) => {
-                    error!("Failed casting vote: {}", e);
-                    server_error(RpcError::Vote, id)
-                }
-            },
-            Err(_) => {
-                error!("Failed parsing PublicKey from String");
-                server_error(RpcError::Parse, id)
-            }
-        }
-    }
-    // --> {"method": "execute", "params": []}
-    // <-- {"result": "executing..."}
-    async fn execute(&self, id: Value, params: &[Value]) -> JsonResult {
-        let mut client = self.client.lock().await;
-
-        let bulla_str = params[0].as_str();
-        if bulla_str.is_none() {
-            return JsonError::new(InvalidParams, None, id).into()
-        }
-        let bulla_str = bulla_str.unwrap();
-
-        let bulla = parse_b58(bulla_str);
-        match bulla {
-            Ok(bulla) => match client.exec_proposal(bulla) {
-                Ok(_) => JsonResponse::new(json!("Proposal executed successfully."), id).into(),
-                Err(e) => {
-                    // Reject proposal instead of returning error?
-                    error!("Failed executing proposal: {}", e);
-                    server_error(RpcError::Exec, id)
-                }
-            },
-            Err(e) => {
-                error!("Failed parsing bulla: {}", e);
-                server_error(RpcError::Parse, id)
-            }
-        }
-    }
-}

+ 0 - 280
bin/dao/daod/src/util.rs

@@ -1,280 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{any::Any, collections::HashMap};
-
-use darkfi_sdk::crypto::{
-    schnorr::{SchnorrPublic, SchnorrSecret, Signature},
-    PublicKey, SecretKey, TokenId,
-};
-use darkfi_serial::Encodable;
-use lazy_static::lazy_static;
-use log::debug;
-use pasta_curves::{
-    group::ff::{Field, PrimeField},
-    pallas,
-};
-use rand::rngs::OsRng;
-
-use darkfi::{
-    crypto::{
-        proof::{ProvingKey, VerifyingKey},
-        types::DrkCircuitField,
-        Proof,
-    },
-    zk::{vm::ZkCircuit, vm_stack::empty_witnesses},
-    zkas::decoder::ZkBinary,
-    Error,
-};
-
-use crate::error::{DaoError, DaoResult};
-
-/// Parse pallas::Base from a base58-encoded string
-pub fn parse_b58(s: &str) -> std::result::Result<pallas::Base, darkfi::Error> {
-    let bytes = bs58::decode(s).into_vec()?;
-    if bytes.len() != 32 {
-        return Err(Error::ParseFailed("Failed parsing DrkTokenId from base58 string"))
-    }
-
-    let ret = pallas::Base::from_repr(bytes.try_into().unwrap());
-    if ret.is_some().unwrap_u8() == 1 {
-        return Ok(ret.unwrap())
-    }
-
-    Err(Error::ParseFailed("Failed parsing DrkTokenId from base58 string"))
-}
-
-// The token of the DAO treasury.
-lazy_static! {
-    pub static ref DRK_ID: TokenId = TokenId::from(pallas::Base::random(&mut OsRng));
-}
-
-// Governance tokens that are airdropped to users to operate the DAO.
-lazy_static! {
-    pub static ref GOV_ID: TokenId = TokenId::from(pallas::Base::random(&mut OsRng));
-}
-
-#[derive(Clone)]
-pub struct ZkBinaryContractInfo {
-    pub k_param: u32,
-    pub bincode: ZkBinary,
-    pub proving_key: ProvingKey,
-    pub verifying_key: VerifyingKey,
-}
-
-#[derive(Clone)]
-pub struct ZkNativeContractInfo {
-    pub proving_key: ProvingKey,
-    pub verifying_key: VerifyingKey,
-}
-
-#[derive(Clone)]
-pub enum ZkContractInfo {
-    Binary(ZkBinaryContractInfo),
-    Native(ZkNativeContractInfo),
-}
-
-#[derive(Clone)]
-pub struct ZkContractTable {
-    // Key will be a hash of zk binary contract on chain
-    table: HashMap<String, ZkContractInfo>,
-}
-
-impl ZkContractTable {
-    pub fn new() -> Self {
-        Self { table: HashMap::new() }
-    }
-
-    pub fn add_contract(&mut self, key: String, bincode: ZkBinary, k_param: u32) {
-        let witnesses = empty_witnesses(&bincode);
-        let circuit = ZkCircuit::new(witnesses, bincode.clone());
-        let proving_key = ProvingKey::build(k_param, &circuit);
-        let verifying_key = VerifyingKey::build(k_param, &circuit);
-        let info = ZkContractInfo::Binary(ZkBinaryContractInfo {
-            k_param,
-            bincode,
-            proving_key,
-            verifying_key,
-        });
-        self.table.insert(key, info);
-    }
-
-    pub fn add_native(
-        &mut self,
-        key: String,
-        proving_key: ProvingKey,
-        verifying_key: VerifyingKey,
-    ) {
-        self.table.insert(
-            key,
-            ZkContractInfo::Native(ZkNativeContractInfo { proving_key, verifying_key }),
-        );
-    }
-
-    pub fn lookup(&self, key: &String) -> Option<&ZkContractInfo> {
-        self.table.get(key)
-    }
-}
-
-// ANCHOR: transaction
-pub struct Transaction {
-    pub func_calls: Vec<FuncCall>,
-    pub signatures: Vec<Vec<Signature>>,
-    // pub proofs: Vec<Proof>,
-}
-// ANCHOR_END: transaction
-
-impl Transaction {
-    /// Verify ZK contracts for the entire tx
-    /// In real code, we could parallelize this for loop
-    /// TODO: fix use of unwrap with Result type stuff
-    pub fn zk_verify(&self, zk_bins: &ZkContractTable) -> DaoResult<()> {
-        for func_call in &self.func_calls {
-            let proofs_public_vals = &func_call.call_data.zk_public_values();
-
-            assert_eq!(
-                proofs_public_vals.len(),
-                func_call.proofs.len(),
-                "proof_public_vals.len()={} and func_call.proofs.len()={} do not match",
-                proofs_public_vals.len(),
-                func_call.proofs.len()
-            );
-            for (i, (proof, (key, public_vals))) in
-                func_call.proofs.iter().zip(proofs_public_vals.iter()).enumerate()
-            {
-                match zk_bins.lookup(key).unwrap() {
-                    ZkContractInfo::Binary(info) => {
-                        let verifying_key = &info.verifying_key;
-                        let verify_result = proof.verify(verifying_key, public_vals);
-                        if verify_result.is_err() {
-                            return Err(DaoError::VerifyProofFailed(i, key.to_string()))
-                        }
-                        //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
-                    }
-                    ZkContractInfo::Native(info) => {
-                        let verifying_key = &info.verifying_key;
-                        let verify_result = proof.verify(verifying_key, public_vals);
-                        if verify_result.is_err() {
-                            return Err(DaoError::VerifyProofFailed(i, key.to_string()))
-                        }
-                        //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
-                    }
-                };
-                debug!(target: "demo", "zk_verify({}) passed [i={}]", key, i);
-            }
-        }
-        Ok(())
-    }
-
-    pub fn verify_sigs(&self) {
-        let mut unsigned_tx_data = vec![];
-        for (i, (func_call, signatures)) in
-            self.func_calls.iter().zip(self.signatures.clone()).enumerate()
-        {
-            func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
-            let signature_pub_keys = func_call.call_data.signature_public_keys();
-            for (signature_pub_key, signature) in signature_pub_keys.iter().zip(signatures) {
-                let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
-                assert!(verify_result, "verify sigs[{}] failed", i);
-            }
-            debug!(target: "demo", "verify_sigs({}) passed", i);
-        }
-    }
-}
-
-pub fn sign(signature_secrets: Vec<SecretKey>, func_call: &FuncCall) -> Vec<Signature> {
-    let mut signatures = vec![];
-    let mut unsigned_tx_data = vec![];
-    for signature_secret in signature_secrets {
-        func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
-        let signature = signature_secret.sign(&mut OsRng, &unsigned_tx_data[..]);
-        signatures.push(signature);
-    }
-    signatures
-}
-
-type ContractId = pallas::Base;
-type FuncId = pallas::Base;
-
-// ANCHOR: funccall
-pub struct FuncCall {
-    pub contract_id: ContractId,
-    pub func_id: FuncId,
-    pub call_data: Box<dyn CallDataBase + Send + Sync>,
-    pub proofs: Vec<Proof>,
-}
-// ANCHOR_END: funccall
-
-impl Encodable for FuncCall {
-    fn encode<W: std::io::Write>(&self, mut w: W) -> std::result::Result<usize, std::io::Error> {
-        let mut len = 0;
-        len += self.contract_id.encode(&mut w)?;
-        len += self.func_id.encode(&mut w)?;
-        len += self.proofs.encode(&mut w)?;
-        len += self.call_data.encode_bytes(&mut w)?;
-        Ok(len)
-    }
-}
-
-// ANCHOR: calldatabase_trait
-pub trait CallDataBase {
-    // Public values for verifying the proofs
-    // Needed so we can convert internal types so they can be used in Proof::verify()
-    fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)>;
-
-    // For upcasting to CallData itself so it can be read in state_transition()
-    fn as_any(&self) -> &dyn Any;
-
-    // Public keys we will use to verify transaction signatures.
-    fn signature_public_keys(&self) -> Vec<PublicKey>;
-
-    fn encode_bytes(
-        &self,
-        writer: &mut dyn std::io::Write,
-    ) -> std::result::Result<usize, std::io::Error>;
-}
-// ANCHOR_END: calldatabase_trait
-
-type GenericContractState = Box<dyn Any + Send>;
-
-pub struct StateRegistry {
-    pub states: HashMap<[u8; 32], GenericContractState>,
-}
-
-impl StateRegistry {
-    pub fn new() -> Self {
-        Self { states: HashMap::new() }
-    }
-
-    pub fn register(&mut self, contract_id: ContractId, state: GenericContractState) {
-        debug!(target: "StateRegistry::register()", "contract_id: {:?}", contract_id);
-        self.states.insert(contract_id.to_repr(), state);
-    }
-
-    pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
-        self.states.get_mut(&contract_id.to_repr()).and_then(|state| state.downcast_mut())
-    }
-
-    pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
-        self.states.get(&contract_id.to_repr()).and_then(|state| state.downcast_ref())
-    }
-}
-
-pub trait UpdateBase {
-    fn apply(self: Box<Self>, states: &mut StateRegistry);
-}