dao: proposals now have a duration, votes are not allowed past the expiry time

This commit is contained in:
zero
2023-12-25 12:13:53 +01:00
parent 62df0d2c41
commit bb2769a207
14 changed files with 68 additions and 2 deletions

View File

@@ -9,6 +9,8 @@ constant "DaoAuthMoneyTransfer" {
witness "DaoAuthMoneyTransfer" {
# Proposal parameters
Base proposal_auth_calls_commit,
Base proposal_current_day,
Base proposal_duration_days,
Base proposal_user_data,
Base proposal_blind,
@@ -51,6 +53,8 @@ circuit "DaoAuthMoneyTransfer" {
# proposal - so it is redundant to check DAO bulla exists here.
proposal_bulla = poseidon_hash(
proposal_auth_calls_commit,
proposal_current_day,
proposal_duration_days,
proposal_user_data,
dao_bulla,
proposal_blind,

View File

@@ -9,6 +9,8 @@ constant "DaoExec" {
witness "DaoExec" {
# Proposal parameters
Base proposal_auth_calls_commit,
Base proposal_current_day,
Base proposal_duration_days,
Base proposal_user_data,
Base proposal_blind,
@@ -46,6 +48,8 @@ circuit "DaoExec" {
# proposal - so it is redundant to check DAO bulla exists here.
proposal_bulla = poseidon_hash(
proposal_auth_calls_commit,
proposal_current_day,
proposal_duration_days,
proposal_user_data,
dao_bulla,
proposal_blind,

View File

@@ -16,6 +16,8 @@ witness "DaoProposeMain" {
# Proposal parameters
Base proposal_auth_calls_commit,
Base proposal_current_day,
Base proposal_duration_days,
Base proposal_user_data,
Base proposal_blind,
@@ -54,11 +56,14 @@ circuit "DaoProposeMain" {
proposal_bulla = poseidon_hash(
proposal_auth_calls_commit,
proposal_current_day,
proposal_duration_days,
proposal_user_data,
dao_bulla,
proposal_blind,
);
constrain_instance(proposal_bulla);
constrain_instance(proposal_current_day);
# This is the main check
# We check that dao_proposer_limit <= total_funds

View File

@@ -9,6 +9,8 @@ constant "DaoVoteMain" {
witness "DaoVoteMain" {
# Proposal parameters
Base proposal_auth_calls_commit,
Base proposal_current_day,
Base proposal_duration_days,
Base proposal_user_data,
Base proposal_blind,
@@ -32,6 +34,9 @@ witness "DaoVoteMain" {
# Check the inputs and this proof are for the same token
Base gov_token_blind,
# Check whether the proposal has expired or not
Base current_day,
}
circuit "DaoVoteMain" {
@@ -51,6 +56,8 @@ circuit "DaoVoteMain" {
proposal_bulla = poseidon_hash(
proposal_auth_calls_commit,
proposal_current_day,
proposal_duration_days,
proposal_user_data,
dao_bulla,
proposal_blind,
@@ -75,4 +82,9 @@ circuit "DaoVoteMain" {
# Vote option should be 0 or 1
bool_check(vote_option);
# Enforce that the proposal has not expired
end_time = base_add(proposal_current_day, proposal_duration_days);
less_than_strict(current_day, end_time);
constrain_instance(current_day);
}

View File

@@ -61,6 +61,8 @@ impl DaoAuthMoneyTransferCall {
let prover_witnesses = vec![
// proposal params
Witness::Base(Value::known(self.proposal.auth_calls.commit())),
Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_day))),
Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_days))),
Witness::Base(Value::known(self.proposal.user_data)),
Witness::Base(Value::known(self.proposal.blind)),
// DAO params

View File

@@ -79,6 +79,8 @@ impl DaoExecCall {
let prover_witnesses = vec![
// proposal params
Witness::Base(Value::known(proposal_auth_calls_commit)),
Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_day))),
Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_days))),
Witness::Base(Value::known(self.proposal.user_data)),
Witness::Base(Value::known(self.proposal.blind)),
// DAO params

View File

@@ -173,6 +173,8 @@ impl DaoProposeCall {
Witness::Base(Value::known(gov_token_blind)),
// proposal params
Witness::Base(Value::known(self.proposal.auth_calls.commit())),
Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_day))),
Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_days))),
Witness::Base(Value::known(self.proposal.user_data)),
Witness::Base(Value::known(self.proposal.blind)),
// DAO params
@@ -191,6 +193,7 @@ impl DaoProposeCall {
token_commit,
self.dao_merkle_root.inner(),
proposal_bulla.inner(),
pallas::Base::from(self.proposal.creation_day),
*total_funds_coords.x(),
*total_funds_coords.y(),
];

View File

@@ -63,6 +63,7 @@ pub struct DaoVoteCall {
pub vote_keypair: Keypair,
pub proposal: DaoProposal,
pub dao: Dao,
pub current_day: u64,
}
impl DaoVoteCall {
@@ -189,9 +190,12 @@ impl DaoVoteCall {
let all_vote_commit = pedersen_commitment_u64(all_vote_value, all_vote_blind);
let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
let current_day = pallas::Base::from(self.current_day);
let prover_witnesses = vec![
// proposal params
Witness::Base(Value::known(self.proposal.auth_calls.commit())),
Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_day))),
Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_days))),
Witness::Base(Value::known(self.proposal.user_data)),
Witness::Base(Value::known(self.proposal.blind)),
// DAO params
@@ -211,6 +215,8 @@ impl DaoVoteCall {
Witness::Scalar(Value::known(all_vote_blind)),
// gov token
Witness::Base(Value::known(gov_token_blind)),
// time checks
Witness::Base(Value::known(current_day)),
];
let public_inputs = vec![
@@ -220,6 +226,7 @@ impl DaoVoteCall {
*yes_vote_commit_coords.y(),
*all_vote_commit_coords.x(),
*all_vote_commit_coords.y(),
current_day,
];
let circuit = ZkCircuit::new(prover_witnesses, main_zkbin);

View File

@@ -26,6 +26,7 @@ use darkfi_sdk::{
error::{ContractError, ContractResult},
msg,
pasta::pallas,
util::get_blockchain_time,
ContractCall,
};
use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
@@ -37,6 +38,8 @@ use crate::{
DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS,
};
const SECS_IN_DAY: u64 = 24 * 60 * 60;
/// `get_metdata` function for `Dao::Propose`
pub(crate) fn dao_propose_get_metadata(
_cid: ContractId,
@@ -80,6 +83,8 @@ pub(crate) fn dao_propose_get_metadata(
));
}
let current_day = get_blockchain_time() / SECS_IN_DAY;
let total_funds_coords = total_funds_commit.to_affine().coordinates().unwrap();
zk_public_inputs.push((
DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS.to_string(),
@@ -87,6 +92,7 @@ pub(crate) fn dao_propose_get_metadata(
params.token_commit,
params.dao_merkle_root.inner(),
params.proposal_bulla.inner(),
pallas::Base::from(current_day),
*total_funds_coords.x(),
*total_funds_coords.y(),
],

View File

@@ -24,6 +24,7 @@ use darkfi_sdk::{
error::{ContractError, ContractResult},
msg,
pasta::pallas,
util::get_blockchain_time,
ContractCall,
};
use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
@@ -35,6 +36,8 @@ use crate::{
DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
};
const SECS_IN_DAY: u64 = 24 * 60 * 60;
/// `get_metdata` function for `Dao::Vote`
pub(crate) fn dao_vote_get_metadata(
_cid: ContractId,
@@ -84,6 +87,8 @@ pub(crate) fn dao_vote_get_metadata(
));
}
let current_day = get_blockchain_time() / SECS_IN_DAY;
let yes_vote_commit_coords = params.yes_vote_commit.to_affine().coordinates().unwrap();
let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
@@ -96,6 +101,7 @@ pub(crate) fn dao_vote_get_metadata(
*yes_vote_commit_coords.y(),
*all_vote_commit_coords.x(),
*all_vote_commit_coords.y(),
pallas::Base::from(current_day),
],
));

View File

@@ -139,6 +139,8 @@ impl VecAuthCallCommit for Vec<DaoAuthCall> {
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
pub struct DaoProposal {
pub auth_calls: Vec<DaoAuthCall>,
pub creation_day: u64,
pub duration_days: u64,
/// Arbitrary data provided by the user. We don't use this.
pub user_data: pallas::Base,
pub dao_bulla: DaoBulla,
@@ -149,6 +151,8 @@ impl DaoProposal {
pub fn to_bulla(&self) -> DaoProposalBulla {
let bulla = poseidon_hash([
self.auth_calls.commit(),
pallas::Base::from(self.creation_day),
pallas::Base::from(self.duration_days),
self.user_data,
self.dao_bulla.inner(),
self.blind,

View File

@@ -38,6 +38,8 @@ use rand::rngs::OsRng;
use super::{Holder, TestHarness, TxAction};
const SECS_IN_DAY: u64 = 24 * 60 * 60;
impl TestHarness {
pub fn dao_propose(
&mut self,
@@ -97,8 +99,12 @@ impl TestHarness {
},
];
let creation_day =
wallet.validator.consensus.time_keeper.blockchain_timestamp() / SECS_IN_DAY;
let proposal = DaoProposal {
auth_calls,
creation_day,
duration_days: 30,
user_data,
dao_bulla: dao.to_bulla(),
blind: pallas::Base::random(&mut OsRng),

View File

@@ -38,6 +38,8 @@ use rand::rngs::OsRng;
use super::{Holder, TestHarness, TxAction};
const SECS_IN_DAY: u64 = 24 * 60 * 60;
impl TestHarness {
pub fn dao_vote(
&mut self,
@@ -78,6 +80,8 @@ impl TestHarness {
signature_secret,
};
let current_day =
wallet.validator.consensus.time_keeper.blockchain_timestamp() / SECS_IN_DAY;
let call = DaoVoteCall {
inputs: vec![input],
vote_option,
@@ -85,6 +89,7 @@ impl TestHarness {
vote_keypair: *dao_kp,
proposal: proposal.clone(),
dao: dao.clone(),
current_day,
};
let (params, proofs) = call.make(

View File

@@ -49,8 +49,8 @@ use darkfi_serial::{deserialize, serialize};
use log::debug;
/// Update this if any circuits are changed
const VKS_HASH: &str = "3f47adca36cd4e17c625d838425793ad7d9ac4ddcc3ed6739add3adb4dfbab8c";
const PKS_HASH: &str = "0d3fef220868380aeb9146a9530bd4e9cbe3b7c1d05b20bfe5c8335741367bc8";
const VKS_HASH: &str = "3571f82a2ff9f05dda4a280b6100aae77fc743f8dc2d6aa02c885ccc2a8f14c3";
const PKS_HASH: &str = "f3399d23e4b917b2156e140227dac5ee5ba3977064ec2132954636441c4fbfb7";
fn pks_path(typ: &str) -> Result<PathBuf> {
let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;