diff --git a/bin/drk/src/dao.rs b/bin/drk/src/dao.rs index 392ebd8e1..87f5d3b89 100644 --- a/bin/drk/src/dao.rs +++ b/bin/drk/src/dao.rs @@ -58,6 +58,7 @@ use darkfi_money_contract::{ use darkfi_sdk::{ bridgetree, crypto::{ + keypair::{Address, StandardAddress}, pasta_prelude::PrimeField, poseidon_hash, smt::{MemoryStorageFp, PoseidonFp, SmtMemoryFp, EMPTY_NODES_FP}, @@ -1587,8 +1588,6 @@ impl Drk { /// Import given DAO vote into the wallet. pub async fn put_dao_vote(&self, vote: &VoteRecord) -> WalletDbResult<()> { - println!("Importing DAO vote into wallet"); - // Create an SQL `INSERT OR REPLACE` query let query = format!( "INSERT INTO {} ({}, {}, {}, {}, {}, {}, {}, {}, {}) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9);", @@ -1620,8 +1619,6 @@ impl Drk { // Execute the query self.wallet.exec_sql(&query, params)?; - println!("DAO vote added to wallet"); - Ok(()) } @@ -1872,6 +1869,9 @@ impl Drk { if let Some(name) = name { let dao = self.get_dao_by_name(name).await?; output.push(format!("{dao}")); + let address: Address = + StandardAddress::from_public(self.network, dao.params.dao.notes_public_key).into(); + output.push(format!("Wallet Address: {address}")); return Ok(()); } @@ -2521,10 +2521,8 @@ impl Drk { inputs.push(input); } - // Now create the parameters for the proposal tx - let signature_secret = SecretKey::random(&mut OsRng); - - // Fetch the daos Merkle tree to compute the DAO Merkle path and root + // Now create the parameters for the proposal tx. + // Fetch the daos Merkle tree to compute the DAO Merkle path and root. let (daos_tree, _) = self.get_dao_trees().await?; let (dao_merkle_path, dao_merkle_root) = { let root = daos_tree.root(0).unwrap(); @@ -2546,10 +2544,9 @@ impl Drk { dao_leaf_position: dao.leaf_position.unwrap(), dao_merkle_path, dao_merkle_root, - signature_secret, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( &dao.params.proposer_secret_key.unwrap(), &propose_burn_zkbin, &propose_burn_pk, @@ -2568,8 +2565,8 @@ impl Drk { // We first have to execute the fee-less tx to gather its used gas, and then we feed // it into the fee-creating function. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let tree = self.get_money_tree().await?; let (fee_call, fee_proofs, fee_secrets) = @@ -2580,7 +2577,7 @@ impl Drk { // Now build the actual transaction and sign it with all necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; + let sigs = tx.create_sigs(&signature_secrets)?; tx.signatures.push(sigs); let sigs = tx.create_sigs(&fee_secrets)?; tx.signatures.push(sigs); @@ -2704,10 +2701,8 @@ impl Drk { inputs.push(input); } - // Now create the parameters for the proposal tx - let signature_secret = SecretKey::random(&mut OsRng); - - // Fetch the daos Merkle tree to compute the DAO Merkle path and root + // Now create the parameters for the proposal tx. + // Fetch the daos Merkle tree to compute the DAO Merkle path and root. let (daos_tree, _) = self.get_dao_trees().await?; let (dao_merkle_path, dao_merkle_root) = { let root = daos_tree.root(0).unwrap(); @@ -2729,10 +2724,9 @@ impl Drk { dao_leaf_position: dao.leaf_position.unwrap(), dao_merkle_path, dao_merkle_root, - signature_secret, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( &dao.params.proposer_secret_key.unwrap(), &propose_burn_zkbin, &propose_burn_pk, @@ -2751,8 +2745,8 @@ impl Drk { // We first have to execute the fee-less tx to gather its used gas, and then we feed // it into the fee-creating function. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let tree = self.get_money_tree().await?; let (fee_call, fee_proofs, fee_secrets) = @@ -2763,7 +2757,7 @@ impl Drk { // Now build the actual transaction and sign it with all necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; + let sigs = tx.create_sigs(&signature_secrets)?; tx.signatures.push(sigs); let sigs = tx.create_sigs(&fee_secrets)?; tx.signatures.push(sigs); @@ -2891,7 +2885,6 @@ impl Drk { let dao_vote_main_pk = ProvingKey::build(dao_vote_main_zkbin.k, &dao_vote_main_circuit); // Now create the parameters for the vote tx - let signature_secret = SecretKey::random(&mut OsRng); let mut inputs = Vec::with_capacity(gov_owncoins_to_use.len()); for gov_owncoin in gov_owncoins_to_use { // Skip governance coins that are not part of the snapshot @@ -2915,7 +2908,6 @@ impl Drk { note: gov_owncoin.note.clone(), leaf_position: gov_owncoin.leaf_position, merkle_path, - signature_secret, }; inputs.push(input); } @@ -2946,7 +2938,7 @@ impl Drk { current_blockwindow, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( &dao_vote_burn_zkbin, &dao_vote_burn_pk, &dao_vote_main_zkbin, @@ -2964,8 +2956,8 @@ impl Drk { // We first have to execute the fee-less tx to gather its used gas, and then we feed // it into the fee-creating function. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let tree = self.get_money_tree().await?; let (fee_call, fee_proofs, fee_secrets) = @@ -2976,7 +2968,7 @@ impl Drk { // Now build the actual transaction and sign it with all necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; + let sigs = tx.create_sigs(&signature_secrets)?; tx.signatures.push(sigs); let sigs = tx.create_sigs(&fee_secrets)?; tx.signatures.push(sigs); diff --git a/doc/src/testnet/dao.md b/doc/src/testnet/dao.md index 765dfcfcd..c3deb03c2 100644 --- a/doc/src/testnet/dao.md +++ b/doc/src/testnet/dao.md @@ -135,6 +135,7 @@ Bulla blind: 6TVkmM...Jjd5zC Leaf position: None Transaction hash: None Call index: None +Wallet Address: DX7N6v...5Lz8Pp ``` ## Minting @@ -186,13 +187,14 @@ Leaf position: Position(0) Mint height: 10 Transaction hash: 2e7931f200c1485ea7752076e199708b011a504d71e69d60ed606817c5ff4bd5 Call index: 0 +Wallet Address: DX7N6v...5Lz8Pp ``` ## Sending money to the treasury Let's send some tokens to the DAO's treasury so we're able to make -a proposal to send those somewhere. First, find the DAO bulla, the -dao contract spend hook and the DAO notes public key. +a proposal to send those somewhere. First, find the DAO wallet address, +the DAO bulla and the dao contract spend hook. Then create a transfer transaction as follows: @@ -231,10 +233,11 @@ Leaf position: Position(0) Mint height: 10 Transaction hash: 2e7931f200c1485ea7752076e199708b011a504d71e69d60ed606817c5ff4bd5 Call index: 0 +Wallet Address: DX7N6v...5Lz8Pp ``` ```shell -drk> transfer 10 DAWN {DAO_NOTES_PUBLIC_KEY} {DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} | broadcast +drk> transfer 10 DAWN {DAO_WALLET_ADDRESS} {DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} | broadcast [mark_tx_spend] Processing transaction: a4db439f75de88457cadd849131394ae37723c943ea5c088b218d6dc0f7982f1 [mark_tx_spend] Found Money contract in call 0 @@ -565,7 +568,7 @@ instead of transfering some to the DAO, we will mint them directly into it: ```shell -drk> token mint ANON 20 {DAO_NOTES_PUBLIC_KEY} {DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} | broadcast +drk> token mint ANON 20 {DAO_WALLET_ADDRESS} {DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} | broadcast [mark_tx_spend] Processing transaction: 781632eb1d0e4566582c1bb34f4a99516d62357761659d4e5e965ac9d199b581 [mark_tx_spend] Found Money contract in call 0 @@ -638,10 +641,11 @@ Leaf position: Position(3) Mint height: 23 Transaction hash: cfc31bee7d198d7d59e9f40f76a98e93230320ec6dd8c606af32d9bee28fcf0e Call index: 0 +Wallet Address: Ui5C2e...1IO4Aa ``` ```shell -drk> dao propose-transfer AnonDAO 1 6.9 ANON {DAWN_DAO_NOTES_PUBLIC_KEY} {DAO_CONTRACT_SPEND_HOOK} {DAWN_DAO_BULLA} +drk> dao propose-transfer AnonDAO 1 6.9 ANON {DAWN_DAO_WALLET_ADDRESS} {DAO_CONTRACT_SPEND_HOOK} {DAWN_DAO_BULLA} Generated proposal: {PROPOSAL_BULLA} ``` diff --git a/src/contract/dao/src/client/propose.rs b/src/contract/dao/src/client/propose.rs index 37cb91c2b..60e666963 100644 --- a/src/contract/dao/src/client/propose.rs +++ b/src/contract/dao/src/client/propose.rs @@ -59,7 +59,6 @@ pub struct DaoProposeCall<'a, T: StorageAdapter> { pub dao_leaf_position: bridgetree::Position, pub dao_merkle_path: Vec, pub dao_merkle_root: MerkleNode, - pub signature_secret: SecretKey, } impl> DaoProposeCall<'_, T> { @@ -70,14 +69,12 @@ impl> DaoProposeCall<'_, T> { burn_pk: &ProvingKey, main_zkbin: &ZkBinary, main_pk: &ProvingKey, - ) -> Result<(DaoProposeParams, Vec)> { + ) -> Result<(DaoProposeParams, Vec, Vec)> { let mut proofs = vec![]; + let mut signature_secrets = vec![]; let gov_token_blind = Blind::random(&mut OsRng); - let smt_null_root = self.money_null_smt.root(); - let signature_public = PublicKey::from_secret(self.signature_secret); - let (sig_x, sig_y) = signature_public.xy(); let mut inputs = vec![]; let mut total_funds = 0; @@ -111,6 +108,10 @@ impl> DaoProposeCall<'_, T> { ) } + let signature_secret = SecretKey::random(&mut OsRng); + let signature_public = PublicKey::from_secret(signature_secret); + let (sig_x, sig_y) = signature_public.xy(); + let prover_witnesses = vec![ Witness::Base(Value::known(input.secret.inner())), Witness::Base(Value::known(pallas::Base::from(note.value))), @@ -123,7 +124,7 @@ impl> DaoProposeCall<'_, T> { Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())), Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())), Witness::SparseMerklePath(Value::known(smt_null_path.path)), - Witness::Base(Value::known(self.signature_secret.inner())), + Witness::Base(Value::known(signature_secret.inner())), ]; // TODO: We need a generic ZkSet widget to avoid doing this all the time @@ -165,6 +166,7 @@ impl> DaoProposeCall<'_, T> { let proving_key = &burn_pk; let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)?; proofs.push(input_proof); + signature_secrets.push(signature_secret); let input = DaoProposeParamsInput { value_commit, @@ -258,6 +260,6 @@ impl> DaoProposeCall<'_, T> { inputs, }; - Ok((params, proofs)) + Ok((params, proofs, signature_secrets)) } } diff --git a/src/contract/dao/src/client/vote.rs b/src/contract/dao/src/client/vote.rs index 58205a83d..5550d965a 100644 --- a/src/contract/dao/src/client/vote.rs +++ b/src/contract/dao/src/client/vote.rs @@ -49,7 +49,6 @@ pub struct DaoVoteInput { pub note: darkfi_money_contract::client::MoneyNote, pub leaf_position: bridgetree::Position, pub merkle_path: Vec, - pub signature_secret: SecretKey, } // Inside ZK proof, check proposal is correct. @@ -70,7 +69,7 @@ impl> DaoVoteCall<'_, T> { burn_pk: &ProvingKey, main_zkbin: &ZkBinary, main_pk: &ProvingKey, - ) -> Result<(DaoVoteParams, Vec)> { + ) -> Result<(DaoVoteParams, Vec, Vec)> { debug!(target: "contract::dao::client::vote", "make()"); if self.dao.to_bulla() != self.proposal.dao_bulla { @@ -79,6 +78,7 @@ impl> DaoVoteCall<'_, T> { let proposal_bulla = self.proposal.to_bulla(); let mut proofs = vec![]; + let mut signature_secrets = vec![]; let gov_token_blind = pallas::Base::random(&mut OsRng); @@ -113,7 +113,8 @@ impl> DaoVoteCall<'_, T> { all_vote_value += input.note.value; all_vote_blind += value_blind; - let signature_public = PublicKey::from_secret(input.signature_secret); + let signature_secret = SecretKey::random(&mut OsRng); + let signature_public = PublicKey::from_secret(signature_secret); // Note from the previous output let note = input.note; @@ -152,7 +153,7 @@ impl> DaoVoteCall<'_, T> { Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())), Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())), Witness::SparseMerklePath(Value::known(smt_null_path.path)), - Witness::Base(Value::known(input.signature_secret.inner())), + Witness::Base(Value::known(signature_secret.inner())), ]; let merkle_root = { @@ -199,6 +200,7 @@ impl> DaoVoteCall<'_, T> { debug!(target: "contract::dao::client::vote", "input_proof Proof::create()"); let input_proof = Proof::create(burn_pk, &[circuit], &public_inputs, &mut OsRng)?; proofs.push(input_proof); + signature_secrets.push(signature_secret); let input = DaoVoteParamsInput { vote_commit, @@ -327,6 +329,6 @@ impl> DaoVoteCall<'_, T> { let params = DaoVoteParams { token_commit, proposal_bulla, yes_vote_commit, note: enc_note, inputs }; - Ok((params, proofs)) + Ok((params, proofs, signature_secrets)) } } diff --git a/src/contract/test-harness/src/dao_propose.rs b/src/contract/test-harness/src/dao_propose.rs index 785bb3beb..38a226c52 100644 --- a/src/contract/test-harness/src/dao_propose.rs +++ b/src/contract/test-harness/src/dao_propose.rs @@ -130,7 +130,6 @@ impl TestHarness { blind: Blind::random(&mut OsRng), }; - let signature_secret = SecretKey::random(&mut OsRng); let dao_bulla = dao.to_bulla(); let call = DaoProposeCall { @@ -144,10 +143,9 @@ impl TestHarness { .witness(*wallet.dao_leafs.get(&dao_bulla).unwrap(), 0) .unwrap(), dao_merkle_root: wallet.dao_merkle_tree.root(0).unwrap(), - signature_secret, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( dao_proposer_secret_key, dao_propose_burn_zkbin, dao_propose_burn_pk, @@ -166,8 +164,8 @@ impl TestHarness { let mut fee_signature_secrets = None; if self.verify_fees { let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let (fee_call, fee_proofs, fee_secrets, _spent_fee_coins, fee_call_params) = self.append_fee_call(proposer, tx, block_height, &[]).await?; @@ -180,8 +178,8 @@ impl TestHarness { // Now build the actual transaction and sign it with necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); if let Some(fee_signature_secrets) = fee_signature_secrets { let sigs = tx.create_sigs(&fee_signature_secrets)?; tx.signatures.push(sigs); @@ -250,7 +248,6 @@ impl TestHarness { blind: Blind::random(&mut OsRng), }; - let signature_secret = SecretKey::random(&mut OsRng); let dao_bulla = dao.to_bulla(); let call = DaoProposeCall { @@ -264,10 +261,9 @@ impl TestHarness { .witness(*wallet.dao_leafs.get(&dao_bulla).unwrap(), 0) .unwrap(), dao_merkle_root: wallet.dao_merkle_tree.root(0).unwrap(), - signature_secret, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( dao_proposer_secret_key, dao_propose_burn_zkbin, dao_propose_burn_pk, @@ -286,8 +282,8 @@ impl TestHarness { let mut fee_signature_secrets = None; if self.verify_fees { let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let (fee_call, fee_proofs, fee_secrets, _spent_fee_coins, fee_call_params) = self.append_fee_call(proposer, tx, block_height, &[]).await?; @@ -300,8 +296,8 @@ impl TestHarness { // Now build the actual transaction and sign it with necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); if let Some(fee_signature_secrets) = fee_signature_secrets { let sigs = tx.create_sigs(&fee_signature_secrets)?; tx.signatures.push(sigs); diff --git a/src/contract/test-harness/src/dao_vote.rs b/src/contract/test-harness/src/dao_vote.rs index 5cce1ecf3..f1582393f 100644 --- a/src/contract/test-harness/src/dao_vote.rs +++ b/src/contract/test-harness/src/dao_vote.rs @@ -31,11 +31,10 @@ use darkfi_money_contract::{ model::MoneyFeeParamsV1, }; use darkfi_sdk::{ - crypto::{contract_id::DAO_CONTRACT_ID, MerkleNode, SecretKey}, + crypto::{contract_id::DAO_CONTRACT_ID, MerkleNode}, ContractCall, }; use darkfi_serial::AsyncEncodable; -use rand::rngs::OsRng; use tracing::debug; use super::{Holder, TestHarness}; @@ -68,14 +67,11 @@ impl TestHarness { .unwrap() .clone(); - let signature_secret = SecretKey::random(&mut OsRng); - let input = DaoVoteInput { secret: wallet.keypair.secret, note: vote_owncoin.note.clone(), leaf_position: vote_owncoin.leaf_position, merkle_path: snapshot_money_merkle_tree.witness(vote_owncoin.leaf_position, 0).unwrap(), - signature_secret, }; let block_target = wallet.validator.consensus.module.read().await.target; @@ -89,7 +85,7 @@ impl TestHarness { current_blockwindow, }; - let (params, proofs) = call.make( + let (params, proofs, signature_secrets) = call.make( dao_vote_burn_zkbin, dao_vote_burn_pk, dao_vote_main_zkbin, @@ -107,8 +103,8 @@ impl TestHarness { let mut fee_signature_secrets = None; if self.verify_fees { let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); let (fee_call, fee_proofs, fee_secrets, _spent_fee_coins, fee_call_params) = self.append_fee_call(voter, tx, block_height, &[]).await?; @@ -121,8 +117,8 @@ impl TestHarness { // Now build the actual transaction and sign it with necessary keys. let mut tx = tx_builder.build()?; - let sigs = tx.create_sigs(&[signature_secret])?; - tx.signatures = vec![sigs]; + let sigs = tx.create_sigs(&signature_secrets)?; + tx.signatures.push(sigs); if let Some(fee_signature_secrets) = fee_signature_secrets { let sigs = tx.create_sigs(&fee_signature_secrets)?; tx.signatures.push(sigs);