diff --git a/src/contract/dao/src/client/exec.rs b/src/contract/dao/src/client/exec.rs index c268e782d..09c58b36f 100644 --- a/src/contract/dao/src/client/exec.rs +++ b/src/contract/dao/src/client/exec.rs @@ -29,10 +29,13 @@ use rand::rngs::OsRng; use darkfi::{ zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit}, zkas::ZkBinary, - Result, + ClientFailed, Result, }; -use crate::model::{Dao, DaoBlindAggregateVote, DaoExecParams, DaoProposal, VecAuthCallCommit}; +use crate::{ + error::DaoError, + model::{Dao, DaoBlindAggregateVote, DaoExecParams, DaoProposal, VecAuthCallCommit}, +}; pub struct DaoExecCall { pub proposal: DaoProposal, @@ -54,7 +57,7 @@ impl DaoExecCall { exec_zkbin: &ZkBinary, exec_pk: &ProvingKey, ) -> Result<(DaoExecParams, Vec)> { - debug!(target: "dao", "build()"); + debug!(target: "contract::dao::client::exec", "build()"); let mut proofs = vec![]; let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit); @@ -65,7 +68,9 @@ impl DaoExecCall { let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy(); let dao_bulla = self.dao.to_bulla(); - assert_eq!(dao_bulla, self.proposal.dao_bulla); + if dao_bulla != self.proposal.dao_bulla { + return Err(ClientFailed::VerifyError(DaoError::InvalidCalls.to_string()).into()) + } let proposal_bulla = self.proposal.to_bulla(); let yes_vote_commit = pedersen_commitment_u64(self.yes_vote_value, self.yes_vote_blind); @@ -103,7 +108,7 @@ impl DaoExecCall { Witness::Base(Value::known(self.signature_secret.inner())), ]; - debug!(target: "dao", "proposal_bulla: {:?}", proposal_bulla); + debug!(target: "contract::dao::client::exec", "proposal_bulla: {:?}", proposal_bulla); let public_inputs = vec![ proposal_bulla.inner(), proposal_auth_calls_commit, diff --git a/src/contract/dao/src/client/mint.rs b/src/contract/dao/src/client/mint.rs index 95db1c566..2aab53930 100644 --- a/src/contract/dao/src/client/mint.rs +++ b/src/contract/dao/src/client/mint.rs @@ -49,7 +49,7 @@ pub fn make_mint_call( dao_mint_zkbin: &ZkBinary, dao_mint_pk: &ProvingKey, ) -> Result<(DaoMintParams, Vec)> { - debug!(target: "dao", "Building DAO contract mint transaction"); + debug!(target: "contract::dao::client::mint", "Building DAO contract mint transaction"); let dao_proposer_limit = pallas::Base::from(dao.proposer_limit); let dao_quorum = pallas::Base::from(dao.quorum); diff --git a/src/contract/dao/src/client/propose.rs b/src/contract/dao/src/client/propose.rs index ae66cce88..03bd2f800 100644 --- a/src/contract/dao/src/client/propose.rs +++ b/src/contract/dao/src/client/propose.rs @@ -32,10 +32,13 @@ use rand::rngs::OsRng; use darkfi::{ zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit}, zkas::ZkBinary, - Result, + ClientFailed, Result, }; -use crate::model::{Dao, DaoProposal, DaoProposeParams, DaoProposeParamsInput, VecAuthCallCommit}; +use crate::{ + error::DaoError, + model::{Dao, DaoProposal, DaoProposeParams, DaoProposeParamsInput, VecAuthCallCommit}, +}; pub struct DaoProposeStakeInput<'a> { pub secret: SecretKey, @@ -96,7 +99,11 @@ impl<'a> DaoProposeCall<'a> { let smt_null_root = input.money_null_smt.root(); let smt_null_path = input.money_null_smt.prove_membership(&nullifier); - assert!(smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier)); + if !smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier) { + return Err( + ClientFailed::VerifyError(DaoError::InvalidInputMerkleRoot.to_string()).into() + ) + } let prover_witnesses = vec![ Witness::Base(Value::known(input.secret.inner())), @@ -130,7 +137,9 @@ impl<'a> DaoProposeCall<'a> { }; let token_commit = poseidon_hash([note.token_id.inner(), gov_token_blind.inner()]); - assert_eq!(self.dao.gov_token_id, note.token_id); + if note.token_id != self.dao.gov_token_id { + return Err(ClientFailed::InvalidTokenId(note.token_id.to_string()).into()) + } let value_commit = pedersen_commitment_u64(note.value, funds_blind); let value_coords = value_commit.to_affine().coordinates().unwrap(); @@ -176,7 +185,9 @@ impl<'a> DaoProposeCall<'a> { let dao_leaf_position: u64 = self.dao_leaf_position.into(); - assert_eq!(self.dao.to_bulla(), self.proposal.dao_bulla); + if self.dao.to_bulla() != self.proposal.dao_bulla { + return Err(ClientFailed::VerifyError(DaoError::InvalidCalls.to_string()).into()) + } let proposal_bulla = self.proposal.to_bulla(); let prover_witnesses = vec![ diff --git a/src/contract/dao/src/client/vote.rs b/src/contract/dao/src/client/vote.rs index 5f453f060..c23c2c671 100644 --- a/src/contract/dao/src/client/vote.rs +++ b/src/contract/dao/src/client/vote.rs @@ -33,10 +33,13 @@ use rand::rngs::OsRng; use darkfi::{ zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit}, zkas::ZkBinary, - Result, + ClientFailed, Result, }; -use crate::model::{Dao, DaoProposal, DaoVoteParams, DaoVoteParamsInput, VecAuthCallCommit}; +use crate::{ + error::DaoError, + model::{Dao, DaoProposal, DaoVoteParams, DaoVoteParamsInput, VecAuthCallCommit}, +}; pub struct DaoVoteInput { pub secret: SecretKey, @@ -65,9 +68,11 @@ impl<'a> DaoVoteCall<'a> { main_zkbin: &ZkBinary, main_pk: &ProvingKey, ) -> Result<(DaoVoteParams, Vec)> { - debug!(target: "dao", "build()"); + debug!(target: "contract::dao::client::vote", "build()"); - assert_eq!(self.dao.to_bulla(), self.proposal.dao_bulla); + if self.dao.to_bulla() != self.proposal.dao_bulla { + return Err(ClientFailed::VerifyError(DaoError::InvalidCalls.to_string()).into()) + } let proposal_bulla = self.proposal.to_bulla(); let mut proofs = vec![]; @@ -125,7 +130,11 @@ impl<'a> DaoVoteCall<'a> { let smt_null_root = self.money_null_smt.root(); let smt_null_path = self.money_null_smt.prove_membership(&nullifier); - assert!(smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier)); + if !smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier) { + return Err( + ClientFailed::VerifyError(DaoError::InvalidInputMerkleRoot.to_string()).into() + ) + } let prover_witnesses = vec![ Witness::Base(Value::known(input.secret.inner())), @@ -158,7 +167,9 @@ impl<'a> DaoVoteCall<'a> { }; let token_commit = poseidon_hash([note.token_id.inner(), gov_token_blind]); - assert_eq!(self.dao.gov_token_id, note.token_id); + if note.token_id != self.dao.gov_token_id { + return Err(ClientFailed::InvalidTokenId(note.token_id.to_string()).into()) + } let vote_commit = pedersen_commitment_u64(note.value, Blind(value_blind)); let vote_commit_coords = vote_commit.to_affine().coordinates().unwrap(); @@ -203,7 +214,9 @@ impl<'a> DaoVoteCall<'a> { let dao_public_key = self.dao.public_key.inner(); let vote_option = self.vote_option as u64; - assert!(vote_option == 0 || vote_option == 1); + if vote_option != 0 && vote_option != 1 { + return Err(ClientFailed::VerifyError(DaoError::VoteInputsEmpty.to_string()).into()) + } // Create a random blind b โˆˆ ๐”ฝแตฅ, such that b โˆˆ ๐”ฝโ‚š let yes_vote_blind = loop { @@ -217,7 +230,9 @@ impl<'a> DaoVoteCall<'a> { let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap(); let all_vote_commit = pedersen_commitment_u64(all_vote_value, Blind(all_vote_blind)); - assert_eq!(all_vote_commit, inputs.iter().map(|i| i.vote_commit).sum()); + if all_vote_commit != inputs.iter().map(|i| i.vote_commit).sum() { + return Err(ClientFailed::VerifyError(DaoError::VoteCommitMismatch.to_string()).into()) + } let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap(); // Convert blinds to ๐”ฝโ‚š, which should work fine since we selected them diff --git a/src/contract/dao/src/entrypoint/auth_xfer.rs b/src/contract/dao/src/entrypoint/auth_xfer.rs index d4559ef6c..d0e3db2aa 100644 --- a/src/contract/dao/src/entrypoint/auth_xfer.rs +++ b/src/contract/dao/src/entrypoint/auth_xfer.rs @@ -17,6 +17,7 @@ */ use darkfi_money_contract::{ + error::MoneyError, model::{Coin, MoneyTransferParamsV1}, MoneyFunction, }; @@ -54,8 +55,15 @@ pub(crate) fn dao_authxfer_get_metadata( let exec_callnode = &calls[parent_idx]; let exec_params: DaoExecParams = deserialize(&exec_callnode.data.data[1..])?; - assert!(!xfer_params.inputs.is_empty()); - assert!(!xfer_params.outputs.is_empty()); + if xfer_params.inputs.is_empty() { + msg!("[Dao::AuthXfer] Error: Transfer inputs are missing"); + return Err(MoneyError::TransferMissingInputs.into()) + } + + if xfer_params.outputs.len() <= 1 { + msg!("[Dao::AuthXfer] Error: Transfer outputs are missing"); + return Err(MoneyError::TransferMissingOutputs.into()) + } let mut zk_public_inputs: Vec<(String, Vec)> = vec![]; let signature_pubkeys: Vec = vec![]; @@ -153,9 +161,16 @@ pub(crate) fn dao_authxfer_process_instruction( /////////////////////////////////////////////////// let xfer_params: MoneyTransferParamsV1 = deserialize(&xfer_call.data[1..])?; - assert!(!xfer_params.inputs.is_empty()); + if xfer_params.inputs.is_empty() { + msg!("[Dao::AuthXfer] Error: Transfer inputs are missing"); + return Err(MoneyError::TransferMissingInputs.into()) + } + // We need the last output to be the change - assert!(xfer_params.outputs.len() > 1); + if xfer_params.outputs.len() <= 1 { + msg!("[Dao::AuthXfer] Error: Transfer outputs are missing"); + return Err(MoneyError::TransferMissingOutputs.into()) + } // MoneyTransfer should all have the same user_data set. // We check this by ensuring that user_data_enc is also the same for all inputs. diff --git a/src/contract/dao/src/entrypoint/propose.rs b/src/contract/dao/src/entrypoint/propose.rs index 218fbb6b6..26bd0d23c 100644 --- a/src/contract/dao/src/entrypoint/propose.rs +++ b/src/contract/dao/src/entrypoint/propose.rs @@ -17,8 +17,9 @@ */ use darkfi_money_contract::{ - MONEY_CONTRACT_COIN_ROOTS_TREE, MONEY_CONTRACT_INFO_TREE, MONEY_CONTRACT_LATEST_COIN_ROOT, - MONEY_CONTRACT_LATEST_NULLIFIER_ROOT, MONEY_CONTRACT_NULLIFIER_ROOTS_TREE, + error::MoneyError, MONEY_CONTRACT_COIN_ROOTS_TREE, MONEY_CONTRACT_INFO_TREE, + MONEY_CONTRACT_LATEST_COIN_ROOT, MONEY_CONTRACT_LATEST_NULLIFIER_ROOT, + MONEY_CONTRACT_NULLIFIER_ROOTS_TREE, }; use darkfi_sdk::{ crypto::{contract_id::MONEY_CONTRACT_ID, pasta_prelude::*, ContractId, MerkleNode, PublicKey}, @@ -149,7 +150,14 @@ pub(crate) fn dao_propose_process_instruction( return Err(DaoError::NonMatchingSnapshotRoots.into()) } - assert_eq!(coin_root_data.len(), 32 + 1); + if coin_root_data.len() != 32 + 1 { + msg!( + "[Dao::Propose] Error: Coin roots data length is not expected(32 + 1): {}", + coin_root_data.len() + ); + return Err(MoneyError::RootsValueDataMismatch.into()) + } + let tx_hash_data: [u8; 32] = coin_root_data[0..32].try_into().unwrap(); let tx_hash = TransactionHash(tx_hash_data); // Get block_height where tx_hash was confirmed