diff --git a/Cargo.lock b/Cargo.lock
index cd0855a87..d0b2fea7c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1171,10 +1171,18 @@ dependencies = [
name = "darkfi-dao-contract"
version = "0.3.0"
dependencies = [
+ "async-std",
+ "darkfi",
"darkfi-money-contract",
"darkfi-sdk",
"darkfi-serial",
"getrandom 0.2.8",
+ "halo2_proofs",
+ "log",
+ "rand",
+ "simplelog",
+ "sled",
+ "sqlx",
]
[[package]]
diff --git a/src/consensus/validator.rs b/src/consensus/validator.rs
index 9509e86dc..d44ebf93a 100644
--- a/src/consensus/validator.rs
+++ b/src/consensus/validator.rs
@@ -23,8 +23,10 @@ use darkfi_sdk::{
crypto::{
constants::MERKLE_DEPTH,
contract_id::MONEY_CONTRACT_ID,
+ //contract_id::{DAO_CONTRACT_ID, MONEY_CONTRACT_ID},
schnorr::{SchnorrPublic, SchnorrSecret},
- MerkleNode, PublicKey,
+ MerkleNode,
+ PublicKey,
},
db::SMART_CONTRACT_ZKAS_DB_NAME,
incrementalmerkletree::{bridgetree::BridgeTree, Tree},
@@ -154,12 +156,14 @@ impl ValidatorState {
include_bytes!("../contract/money/money_contract.wasm").to_vec(),
money_contract_deploy_payload,
),
- //(
- // "DAO Contract",
- // *DAO_CONTRACT_ID,
- // include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
- // dao_contract_deploy_payload,
- //),
+ /*
+ (
+ "DAO Contract",
+ *DAO_CONTRACT_ID,
+ include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
+ dao_contract_deploy_payload,
+ ),
+ */
];
info!("Deploying native wasm contracts");
diff --git a/src/contract/dao/Cargo.toml b/src/contract/dao/Cargo.toml
index 333d2f9ec..ce04860ae 100644
--- a/src/contract/dao/Cargo.toml
+++ b/src/contract/dao/Cargo.toml
@@ -13,6 +13,21 @@ darkfi-sdk = { path = "../../sdk" }
darkfi-serial = { path = "../../serial", features = ["derive", "crypto"] }
darkfi-money-contract = { path = "../money", features = ["no-entrypoint"] }
+# The following dependencies are used for the client API and
+# probably shouldn't be in WASM
+darkfi = { path = "../../../", features = ["zk", "rpc"], optional = true }
+halo2_proofs = { version = "0.2.0", optional = true }
+log = { version = "0.4.17", optional = true }
+rand = { version = "0.8.5", optional = true }
+
+# These are used just for the integration tests
+[dev-dependencies]
+async-std = {version = "1.12.0", features = ["attributes"]}
+darkfi = {path = "../../../", features = ["tx", "blockchain"]}
+simplelog = "0.12.0"
+sled = "0.34.7"
+sqlx = {version = "0.6.2", features = ["runtime-async-std-native-tls", "sqlite"]}
+
# We need to disable random using "custom" which makes the crate a noop
# so the wasm32-unknown-unknown target is enabled.
[target.'cfg(target_arch = "wasm32")'.dependencies]
@@ -21,4 +36,9 @@ getrandom = { version = "0.2.8", features = ["custom"] }
[features]
default = []
no-entrypoint = []
-client = []
+client = [
+ "darkfi",
+ "rand",
+ "log",
+ "halo2_proofs",
+]
diff --git a/src/contract/dao/Makefile b/src/contract/dao/Makefile
index 31b5a13fa..22c26a764 100644
--- a/src/contract/dao/Makefile
+++ b/src/contract/dao/Makefile
@@ -28,8 +28,12 @@ $(WASM_BIN): $(WASM_SRC) $(PROOFS_BIN)
$(PROOFS_BIN): $(ZKAS) $(PROOFS_SRC)
$(ZKAS) $(basename $@) -o $@
-test: all
- $(CARGO) test --release --features=no-entrypoint,client --package darkfi-dao-contract
+test-integration: all
+ $(CARGO) test --release --features=no-entrypoint,client \
+ --package darkfi-dao-contract \
+ --test integration
+
+test:
clean:
rm -f $(PROOFS_BIN) $(WASM_BIN)
diff --git a/src/contract/dao/src/client.rs b/src/contract/dao/src/client.rs
new file mode 100644
index 000000000..ec55a1afb
--- /dev/null
+++ b/src/contract/dao/src/client.rs
@@ -0,0 +1,140 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2022 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 .
+ */
+
+use darkfi::{
+ zk::{proof::ProvingKey, vm::ZkCircuit, vm_stack::Witness, Proof},
+ zkas::ZkBinary,
+ Result,
+};
+use darkfi_sdk::{
+ crypto::{poseidon_hash, PublicKey, SecretKey, TokenId},
+ pasta::pallas,
+};
+use halo2_proofs::circuit::Value;
+use log::debug;
+use rand::rngs::OsRng;
+
+use crate::state::{DaoBulla, DaoMintParams};
+
+struct DaoMintRevealed {
+ pub bulla: DaoBulla,
+}
+
+impl DaoMintRevealed {
+ pub fn compute(
+ dao_proposer_limit: pallas::Base,
+ dao_quorum: pallas::Base,
+ dao_approval_ratio_quot: pallas::Base,
+ dao_approval_ratio_base: pallas::Base,
+ gov_token_id: TokenId,
+ dao_pubkey: &PublicKey,
+ dao_bulla_blind: pallas::Base,
+ ) -> Self {
+ let (pub_x, pub_y) = dao_pubkey.xy();
+
+ let dao_bulla = poseidon_hash([
+ dao_proposer_limit,
+ dao_quorum,
+ dao_approval_ratio_quot,
+ dao_approval_ratio_base,
+ gov_token_id.inner(),
+ pub_x,
+ pub_y,
+ dao_bulla_blind,
+ ]);
+
+ Self { bulla: DaoBulla::from(dao_bulla) }
+ }
+
+ pub fn to_vec(&self) -> Vec {
+ vec![self.bulla.inner()]
+ }
+}
+
+fn create_dao_mint_proof(
+ zkbin: &ZkBinary,
+ pk: &ProvingKey,
+ dao_proposer_limit: pallas::Base,
+ dao_quorum: pallas::Base,
+ dao_approval_ratio_quot: pallas::Base,
+ dao_approval_ratio_base: pallas::Base,
+ gov_token_id: TokenId,
+ dao_pubkey: &PublicKey,
+ dao_bulla_blind: pallas::Base,
+) -> Result<(Proof, DaoMintRevealed)> {
+ let revealed = DaoMintRevealed::compute(
+ dao_proposer_limit,
+ dao_quorum,
+ dao_approval_ratio_quot,
+ dao_approval_ratio_base,
+ gov_token_id,
+ dao_pubkey,
+ dao_bulla_blind,
+ );
+
+ let (pub_x, pub_y) = dao_pubkey.xy();
+
+ // NOTE: It's important to keep these in the same order as the zkas code.
+ 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(gov_token_id.inner())),
+ Witness::Base(Value::known(pub_x)),
+ Witness::Base(Value::known(pub_y)),
+ Witness::Base(Value::known(dao_bulla_blind)),
+ ];
+
+ let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
+ let proof = Proof::create(pk, &[circuit], &revealed.to_vec(), &mut OsRng)?;
+
+ Ok((proof, revealed))
+}
+
+pub fn build_dao_mint_tx(
+ dao_proposer_limit: u64,
+ dao_quorum: u64,
+ dao_approval_ratio_quot: u64,
+ dao_approval_ratio_base: u64,
+ gov_token_id: TokenId,
+ dao_pubkey: &PublicKey,
+ dao_bulla_blind: pallas::Base,
+ signature_secret: &SecretKey,
+ dao_mint_zkbin: &ZkBinary,
+ dao_mint_pk: &ProvingKey,
+) -> Result<(DaoMintParams, Vec)> {
+ debug!("Building DAO contract mint transaction");
+
+ let (proof, revealed) = create_dao_mint_proof(
+ dao_mint_zkbin,
+ dao_mint_pk,
+ pallas::Base::from(dao_proposer_limit),
+ pallas::Base::from(dao_quorum),
+ pallas::Base::from(dao_approval_ratio_quot),
+ pallas::Base::from(dao_approval_ratio_base),
+ gov_token_id,
+ dao_pubkey,
+ dao_bulla_blind,
+ )?;
+
+ let dao_bulla = revealed.bulla;
+ let dao_mint_params = DaoMintParams { dao_bulla };
+
+ Ok((dao_mint_params, vec![proof]))
+}
diff --git a/src/contract/dao/src/entrypoint.rs b/src/contract/dao/src/entrypoint.rs
index 01d2a6c99..c7d539eb7 100644
--- a/src/contract/dao/src/entrypoint.rs
+++ b/src/contract/dao/src/entrypoint.rs
@@ -42,7 +42,9 @@ use crate::{
DaoExecParams, DaoExecUpdate, DaoMintParams, DaoMintUpdate, DaoProposeParams,
DaoProposeUpdate, DaoVoteParams, DaoVoteUpdate, ProposalVotes,
},
- DaoFunction,
+ DaoFunction, DAO_CONTRACT_ZKAS_DAO_EXEC_NS, DAO_CONTRACT_ZKAS_DAO_MINT_NS,
+ DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS,
+ DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
};
darkfi_sdk::define_contract!(
@@ -63,15 +65,7 @@ pub const DAO_PROPOSAL_VOTES_TREE: &str = "dao_proposal_votes";
pub const DAO_MERKLE_TREE: &str = "dao_merkle_tree";
pub const DAO_PROPOSAL_MERKLE_TREE: &str = "dao_proposals_merkle_tree";
-// These are zkas circuit namespaces
-pub const ZKAS_DAO_EXEC_NS: &str = "DaoExec";
-pub const ZKAS_DAO_MINT_NS: &str = "DaoMint";
-pub const ZKAS_DAO_VOTE_BURN_NS: &str = "DaoVoteInput";
-pub const ZKAS_DAO_VOTE_MAIN_NS: &str = "DaoVoteMain";
-pub const ZKAS_DAO_PROPOSE_BURN_NS: &str = "DaoProposeInput";
-pub const ZKAS_DAO_PROPOSE_MAIN_NS: &str = "DaoProposeMain";
-
-fn init_contract(cid: ContractId, ix: &[u8]) -> ContractResult {
+fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
// The zkas circuits can simply be embedded in the wasm and set up by
// the initialization. Note that the tree should then be called "zkas".
// The lookups can then be done by `contract_id+_zkas+namespace`.
@@ -86,12 +80,12 @@ fn init_contract(cid: ContractId, ix: &[u8]) -> ContractResult {
let dao_propose_burn_bin = include_bytes!("../proof/dao-propose-burn.zk.bin");
let dao_propose_main_bin = include_bytes!("../proof/dao-propose-main.zk.bin");
- db_set(zkas_db, &serialize(&ZKAS_DAO_EXEC_NS), &dao_exec_bin[..])?;
- db_set(zkas_db, &serialize(&ZKAS_DAO_MINT_NS), &dao_mint_bin[..])?;
- db_set(zkas_db, &serialize(&ZKAS_DAO_VOTE_BURN_NS), &dao_vote_burn_bin[..])?;
- db_set(zkas_db, &serialize(&ZKAS_DAO_VOTE_MAIN_NS), &dao_vote_main_bin[..])?;
- db_set(zkas_db, &serialize(&ZKAS_DAO_PROPOSE_BURN_NS), &dao_propose_burn_bin[..])?;
- db_set(zkas_db, &serialize(&ZKAS_DAO_PROPOSE_MAIN_NS), &dao_propose_main_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_EXEC_NS), &dao_exec_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_MINT_NS), &dao_mint_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS), &dao_vote_burn_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS), &dao_vote_main_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS), &dao_propose_burn_bin[..])?;
+ db_set(zkas_db, &serialize(&DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS), &dao_propose_main_bin[..])?;
// Set up a database tree to hold the Merkle tree for DAO bullas
let dao_bulla_db = match db_lookup(cid, DAO_BULLA_TREE) {
@@ -108,7 +102,11 @@ fn init_contract(cid: ContractId, ix: &[u8]) -> ContractResult {
None => {
// We didn't find a tree, so just make a new one.
let tree = MerkleTree::new(100);
- db_set(dao_bulla_db, &serialize(&DAO_MERKLE_TREE), &serialize(&tree))?;
+ let mut tree_data = vec![];
+
+ tree_data.write_u32(0)?;
+ tree.encode(&mut tree_data)?;
+ db_set(dao_bulla_db, &serialize(&DAO_MERKLE_TREE), &tree_data)?;
}
};
@@ -133,7 +131,11 @@ fn init_contract(cid: ContractId, ix: &[u8]) -> ContractResult {
None => {
// We didn't find a tree, so just make a new one.
let tree = MerkleTree::new(100);
- db_set(dao_proposal_db, &serialize(&DAO_PROPOSAL_MERKLE_TREE), &serialize(&tree))?;
+ let mut tree_data = vec![];
+
+ tree_data.write_u32(0)?;
+ tree.encode(&mut tree_data)?;
+ db_set(dao_proposal_db, &serialize(&DAO_PROPOSAL_MERKLE_TREE), &tree_data)?;
}
};
@@ -163,6 +165,7 @@ fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
let params: DaoMintParams = deserialize(&self_.data[1..])?;
// No checks in Mint, just return the update.
+ // TODO: Should it check that there isn't an existing one?
let update = DaoMintUpdate { dao_bulla: params.dao_bulla };
let mut update_data = vec![];
update_data.write_u8(DaoFunction::Mint as u8)?;
@@ -396,9 +399,11 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let params: DaoMintParams = deserialize(&self_.data[1..])?;
let mut zk_public_values: Vec<(String, Vec)> = vec![];
+ // TODO: Why no signatures? Should it be signed with the DAO keypair?
let signature_pubkeys: Vec = vec![];
- zk_public_values.push((ZKAS_DAO_MINT_NS.to_string(), vec![params.dao_bulla.inner()]));
+ zk_public_values
+ .push((DAO_CONTRACT_ZKAS_DAO_MINT_NS.to_string(), vec![params.dao_bulla.inner()]));
let mut metadata = vec![];
zk_public_values.encode(&mut metadata)?;
@@ -426,7 +431,7 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let (sig_x, sig_y) = input.signature_public.xy();
zk_public_values.push((
- ZKAS_DAO_PROPOSE_BURN_NS.to_string(),
+ DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS.to_string(),
vec![
*value_coords.x(),
*value_coords.y(),
@@ -440,7 +445,7 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let total_funds_coords = total_funds_commit.to_affine().coordinates().unwrap();
zk_public_values.push((
- ZKAS_DAO_PROPOSE_MAIN_NS.to_string(),
+ DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS.to_string(),
vec![
params.token_commit,
params.dao_merkle_root.inner(),
@@ -476,7 +481,7 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let (sig_x, sig_y) = input.signature_public.xy();
zk_public_values.push((
- ZKAS_DAO_VOTE_BURN_NS.to_string(),
+ DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS.to_string(),
vec![
input.nullifier.inner(),
*value_coords.x(),
@@ -493,7 +498,7 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let all_vote_commit_coords = all_votes_commit.to_affine().coordinates().unwrap();
zk_public_values.push((
- ZKAS_DAO_VOTE_MAIN_NS.to_string(),
+ DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS.to_string(),
vec![
params.token_commit,
params.proposal_bulla,
@@ -524,7 +529,7 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
let input_value_coords = params.input_value_commit.to_affine().coordinates().unwrap();
zk_public_values.push((
- ZKAS_DAO_EXEC_NS.to_string(),
+ DAO_CONTRACT_ZKAS_DAO_EXEC_NS.to_string(),
vec![
params.proposal,
params.coin_0,
diff --git a/src/contract/dao/src/lib.rs b/src/contract/dao/src/lib.rs
index 64dbe98b9..736800a6e 100644
--- a/src/contract/dao/src/lib.rs
+++ b/src/contract/dao/src/lib.rs
@@ -23,6 +23,18 @@ pub mod entrypoint;
pub mod state;
+#[cfg(feature = "client")]
+/// Transaction building API for clients interacting with this contract
+pub mod client;
+
+// These are the zkas circuit namespaces
+pub const DAO_CONTRACT_ZKAS_DAO_MINT_NS: &str = "DaoMint";
+pub const DAO_CONTRACT_ZKAS_DAO_EXEC_NS: &str = "DaoExec";
+pub const DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS: &str = "DaoVoteInput";
+pub const DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS: &str = "DaoVoteMain";
+pub const DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS: &str = "DaoProposeInput";
+pub const DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS: &str = "DaoProposeMain";
+
#[repr(u8)]
pub enum DaoFunction {
Mint = 0x00,
diff --git a/src/contract/dao/tests.unused/harness.rs b/src/contract/dao/tests.unused/harness.rs
new file mode 100644
index 000000000..46dd1b3cc
--- /dev/null
+++ b/src/contract/dao/tests.unused/harness.rs
@@ -0,0 +1,129 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2022 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 .
+ */
+use std::collections::HashMap;
+
+use darkfi::{
+ consensus::{
+ constants::{TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP},
+ ValidatorState, ValidatorStatePtr,
+ },
+ wallet::WalletDb,
+ zk::{proof::ProvingKey, vm::ZkCircuit, vm_stack::empty_witnesses},
+ zkas::ZkBinary,
+ Result,
+};
+use darkfi_sdk::{
+ crypto::{
+ contract_id::{DAO_CONTRACT_ID, MONEY_CONTRACT_ID},
+ ContractId, Keypair, MerkleTree,
+ },
+ db::SMART_CONTRACT_ZKAS_DB_NAME,
+ pasta::group::ff::PrimeField,
+};
+use darkfi_serial::serialize;
+use log::{info, warn};
+use rand::rngs::OsRng;
+
+use darkfi_dao_contract::DAO_CONTRACT_ZKAS_DAO_MINT_NS;
+
+pub fn init_logger() -> Result<()> {
+ let mut cfg = simplelog::ConfigBuilder::new();
+ cfg.add_filter_ignore("sled".to_string());
+ if let Err(_) = simplelog::TermLogger::init(
+ //simplelog::LevelFilter::Info,
+ simplelog::LevelFilter::Debug,
+ //simplelog::LevelFilter::Trace,
+ cfg.build(),
+ simplelog::TerminalMode::Mixed,
+ simplelog::ColorChoice::Auto,
+ ) {
+ warn!("Logger already initialized");
+ }
+
+ Ok(())
+}
+
+pub struct DaoTestHarness {
+ pub alice_kp: Keypair,
+ pub dao_kp: Keypair,
+ pub alice_state: ValidatorStatePtr,
+ pub alice_dao_merkle_tree: MerkleTree,
+ pub money_contract_id: ContractId,
+ pub dao_contract_id: ContractId,
+ pub proving_keys: HashMap<[u8; 32], Vec<(&'static str, ProvingKey)>>,
+ pub dao_mint_zkbin: ZkBinary,
+ pub dao_mint_pk: ProvingKey,
+}
+
+impl DaoTestHarness {
+ pub async fn new() -> Result {
+ let alice_kp = Keypair::random(&mut OsRng);
+ let dao_kp = Keypair::random(&mut OsRng);
+
+ let alice_wallet = WalletDb::new("sqlite::memory:", "foo").await?;
+
+ let alice_sled_db = sled::Config::new().temporary(true).open()?;
+
+ let alice_state = ValidatorState::new(
+ &alice_sled_db,
+ *TESTNET_GENESIS_TIMESTAMP,
+ *TESTNET_GENESIS_HASH_BYTES,
+ alice_wallet,
+ vec![],
+ false,
+ )
+ .await?;
+
+ let alice_dao_merkle_tree = MerkleTree::new(100);
+
+ let money_contract_id = *MONEY_CONTRACT_ID;
+ let dao_contract_id = *DAO_CONTRACT_ID;
+
+ let alice_sled = alice_state.read().await.blockchain.sled_db.clone();
+ let db_handle = alice_state.read().await.blockchain.contracts.lookup(
+ &alice_sled,
+ &dao_contract_id,
+ SMART_CONTRACT_ZKAS_DB_NAME,
+ )?;
+
+ let dao_mint_zkbin = db_handle.get(&serialize(&DAO_CONTRACT_ZKAS_DAO_MINT_NS))?.unwrap();
+ info!("Decoding bincode");
+ let dao_mint_zkbin = ZkBinary::decode(&dao_mint_zkbin)?;
+ let dao_mint_witnesses = empty_witnesses(&dao_mint_zkbin);
+ let dao_mint_circuit = ZkCircuit::new(dao_mint_witnesses, dao_mint_zkbin.clone());
+
+ info!("Creating zk proving keys");
+ let k = 13;
+ let mut proving_keys = HashMap::<[u8; 32], Vec<(&str, ProvingKey)>>::new();
+ let dao_mint_pk = ProvingKey::build(k, &dao_mint_circuit);
+ let pks = vec![(DAO_CONTRACT_ZKAS_DAO_MINT_NS, dao_mint_pk.clone())];
+ proving_keys.insert(dao_contract_id.inner().to_repr(), pks);
+
+ Ok(Self {
+ alice_kp,
+ dao_kp,
+ alice_state,
+ alice_dao_merkle_tree,
+ money_contract_id,
+ dao_contract_id,
+ proving_keys,
+ dao_mint_zkbin,
+ dao_mint_pk,
+ })
+ }
+}
diff --git a/src/contract/dao/tests.unused/integration.rs b/src/contract/dao/tests.unused/integration.rs
new file mode 100644
index 000000000..21849774f
--- /dev/null
+++ b/src/contract/dao/tests.unused/integration.rs
@@ -0,0 +1,94 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2022 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 .
+ */
+
+use darkfi::{tx::Transaction, Result};
+use darkfi_sdk::{
+ crypto::TokenId,
+ pasta::{group::ff::Field, pallas},
+ tx::ContractCall,
+};
+use darkfi_serial::Encodable;
+use log::info;
+use rand::rngs::OsRng;
+
+use darkfi_dao_contract::{client::build_dao_mint_tx, DaoFunction};
+
+mod harness;
+use harness::{init_logger, DaoTestHarness};
+
+#[async_std::test]
+async fn integration_test() -> Result<()> {
+ init_logger()?;
+
+ let mut th = DaoTestHarness::new().await?;
+
+ // Money parameters
+ //let xdrk_supply = 1_000_000;
+ //let xrdk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
+
+ // Governance token parameters
+ //let gdrk_supply = 1_000_000;
+ let gdrk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
+
+ // DAO parameters
+ let dao_proposer_limit = 110;
+ let dao_quorum = 110;
+ let dao_approval_ratio_quot = 1;
+ let dao_approval_ratio_base = 2;
+
+ // =================
+ // DaoFunction::Mint
+ // =================
+
+ let dao_bulla_blind = pallas::Base::random(&mut OsRng);
+
+ info!("[Alice] =========================");
+ info!("[Alice] Building Dao::Mint params");
+ info!("[Alice] =========================");
+ let (params, proofs) = build_dao_mint_tx(
+ dao_proposer_limit,
+ dao_quorum,
+ dao_approval_ratio_quot,
+ dao_approval_ratio_base,
+ gdrk_token_id,
+ &th.dao_kp.public,
+ dao_bulla_blind,
+ &th.dao_kp.secret,
+ &th.dao_mint_zkbin,
+ &th.dao_mint_pk,
+ )?;
+
+ info!("[Alice] ==========================================");
+ info!("[Alice] Building Dao::Mint transaction with params");
+ info!("[Alice] ==========================================");
+ let mut data = vec![DaoFunction::Mint as u8];
+ params.encode(&mut data)?;
+ let calls = vec![ContractCall { contract_id: th.dao_contract_id, data }];
+ let proofs = vec![proofs];
+ let mut tx = Transaction { calls, proofs, signatures: vec![] };
+ let sigs = tx.create_sigs(&mut OsRng, &[])?;
+ tx.signatures = vec![sigs];
+
+ info!("[Alice] ===============================");
+ info!("[Alice] Executing Dao::Mint transaction");
+ info!("[Alice] ===============================");
+ th.alice_state.read().await.verify_transactions(&[tx.clone()], true).await?;
+ // TODO: Witness and add to wallet merkle tree?
+
+ Ok(())
+}
diff --git a/src/contract/money/src/client.rs b/src/contract/money/src/client.rs
index 831a420e0..22262f4e8 100644
--- a/src/contract/money/src/client.rs
+++ b/src/contract/money/src/client.rs
@@ -696,7 +696,7 @@ pub fn build_transfer_tx(
burn_pk: &ProvingKey,
clear_input: bool,
) -> Result<(MoneyTransferParams, Vec, Vec, Vec)> {
- debug!("Building money contract transaction");
+ debug!("Building money contract transfer transaction");
assert!(value != 0);
if !clear_input {
assert!(!coins.is_empty());
diff --git a/src/contract/money/tests/drop_pay_swap.rs b/src/contract/money/tests/drop_pay_swap.rs
index be54faa97..711adaee3 100644
--- a/src/contract/money/tests/drop_pay_swap.rs
+++ b/src/contract/money/tests/drop_pay_swap.rs
@@ -45,19 +45,11 @@ use darkfi_money_contract::{
};
mod harness;
-use harness::MoneyTestHarness;
+use harness::{init_logger, MoneyTestHarness};
#[async_std::test]
async fn money_contract_transfer() -> Result<()> {
- let mut cfg = simplelog::ConfigBuilder::new();
- cfg.add_filter_ignore("sled".to_string());
- simplelog::TermLogger::init(
- //simplelog::LevelFilter::Debug,
- simplelog::LevelFilter::Info,
- cfg.build(),
- simplelog::TerminalMode::Mixed,
- simplelog::ColorChoice::Auto,
- )?;
+ init_logger()?;
// Some numbers we want to assert
const ALICE_INITIAL: u64 = 100;
diff --git a/tests/zkvm_opcodes.rs b/tests/zkvm_opcodes.rs
index 54238e91d..056d59513 100644
--- a/tests/zkvm_opcodes.rs
+++ b/tests/zkvm_opcodes.rs
@@ -45,7 +45,7 @@ use darkfi::{
#[test]
fn zkvm_opcodes() -> Result<()> {
- TermLogger::init(LevelFilter::Debug, Config::default(), TerminalMode::Mixed, ColorChoice::Auto)
+ TermLogger::init(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto)
.unwrap();
let bincode = include_bytes!("../proof/opcodes.zk.bin");