mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
contract/dao: Initial integration tests setup.
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -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]]
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
|
||||
140
src/contract/dao/src/client.rs
Normal file
140
src/contract/dao/src/client.rs
Normal file
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<pallas::Base> {
|
||||
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<Proof>)> {
|
||||
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]))
|
||||
}
|
||||
@@ -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<pallas::Base>)> = vec![];
|
||||
// TODO: Why no signatures? Should it be signed with the DAO keypair?
|
||||
let signature_pubkeys: Vec<PublicKey> = 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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
129
src/contract/dao/tests.unused/harness.rs
Normal file
129
src/contract/dao/tests.unused/harness.rs
Normal file
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Self> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
94
src/contract/dao/tests.unused/integration.rs
Normal file
94
src/contract/dao/tests.unused/integration.rs
Normal file
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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(())
|
||||
}
|
||||
@@ -696,7 +696,7 @@ pub fn build_transfer_tx(
|
||||
burn_pk: &ProvingKey,
|
||||
clear_input: bool,
|
||||
) -> Result<(MoneyTransferParams, Vec<Proof>, Vec<SecretKey>, Vec<OwnCoin>)> {
|
||||
debug!("Building money contract transaction");
|
||||
debug!("Building money contract transfer transaction");
|
||||
assert!(value != 0);
|
||||
if !clear_input {
|
||||
assert!(!coins.is_empty());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user