Skip to content

Commit

Permalink
Split quorum for each proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
VlodkoMr committed Apr 12, 2024
1 parent 77eaf6f commit d7be420
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 85 deletions.
7 changes: 7 additions & 0 deletions voting_body/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ impl Contract {
self.pre_vote_proposals.insert(&self.prop_counter, &prop);
}

// Add proposal consent
let consent = match prop.kind.required_consent() {
ConsentKind::Simple => self.simple_consent.clone(),
ConsentKind::Super => self.super_consent.clone(),
};
self.proposal_consent.insert(&self.prop_counter, &consent);

Ok(self.prop_counter)
}

Expand Down
157 changes: 78 additions & 79 deletions voting_body/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub struct Contract {
/// As we don't have a way to remove people from the blacklist, we can add them to the whitelist
/// and allow them to vote directly.
pub iom_whitelist: LookupSet<AccountId>,
pub proposal_consent: LookupMap<u32, Consent>,
}

#[near_bindgen]
Expand Down Expand Up @@ -97,6 +98,7 @@ impl Contract {
simple_consent,
super_consent,
iom_whitelist: LookupSet::new(StorageKey::IomWhitelist),
proposal_consent: LookupMap::new(StorageKey::ProposalConsent),
}
}

Expand All @@ -108,16 +110,16 @@ impl Contract {
* TRANSACTIONS
**********/

#[payable]
pub fn create_proposal_whitelist(&mut self, payload: CreatePropPayload) -> u32 {
let caller = env::predecessor_account_id();
self.assert_whitelist(&caller);

match self.create_proposal_impl(caller, payload) {
Ok(id) => id,
Err(error) => error.panic(),
}
}
// #[payable]
// pub fn create_proposal_whitelist(&mut self, payload: CreatePropPayload) -> u32 {
// let caller = env::predecessor_account_id();
// self.assert_whitelist(&caller);
//
// match self.create_proposal_impl(caller, payload) {
// Ok(id) => id,
// Err(error) => error.panic(),
// }
// }

/// Must be called via `iah_registry.is_human_call`.
#[payable]
Expand Down Expand Up @@ -191,21 +193,21 @@ impl Contract {
Ok(true)
}

pub fn support_proposal_whitelist(&mut self, payload: u32) -> bool {
let caller = env::predecessor_account_id();
self.assert_whitelist(&caller);

match self.support_proposal_impl(
caller,
// Lock is required to prevent double voting by moving sbt to another account.
// It is not required for the whitelist version, as only whitelisted accounts can call
env::block_timestamp_ms() + MAX_DURATION + 1,
payload,
) {
Ok(supported) => supported,
Err(err) => err.panic(),
}
}
// pub fn support_proposal_whitelist(&mut self, payload: u32) -> bool {
// let caller = env::predecessor_account_id();
// self.assert_whitelist(&caller);
//
// match self.support_proposal_impl(
// caller,
// // Lock is required to prevent double voting by moving sbt to another account.
// // It is not required for the whitelist version, as only whitelisted accounts can call
// env::block_timestamp_ms() + MAX_DURATION + 1,
// payload,
// ) {
// Ok(supported) => supported,
// Err(err) => err.panic(),
// }
// }

/// Supports proposal in the pre-vote queue.
/// Returns false if the proposal can't be supported because it is overdue.
Expand Down Expand Up @@ -265,19 +267,19 @@ impl Contract {
Ok(true)
}

pub fn vote_whitelist(&mut self, payload: VotePayload) {
let caller = env::predecessor_account_id();
self.assert_whitelist(&caller);

match self.vote_impl(
caller,
env::block_timestamp_ms() + MAX_DURATION + 1,
payload,
) {
Ok(_) => (),
Err(err) => err.panic(),
}
}
// pub fn vote_whitelist(&mut self, payload: VotePayload) {
// let caller = env::predecessor_account_id();
// self.assert_whitelist(&caller);
//
// match self.vote_impl(
// caller,
// env::block_timestamp_ms() + MAX_DURATION + 1,
// payload,
// ) {
// Ok(_) => (),
// Err(err) => err.panic(),
// }
// }

/// Must be called via `iah_registry.is_human_call_lock` with
/// `lock_duration: self.vote_duration + 1`.
Expand Down Expand Up @@ -311,7 +313,7 @@ impl Contract {
return Err(ExecError::AlreadyFinalized);
}

prop.recompute_status(self.vote_duration, self.prop_consent(&prop));
prop.recompute_status(self.vote_duration, self.prop_consent(id));
match prop.status {
ProposalStatus::PreVote => panic_str("pre-vote proposal can't be in the active queue"),
ProposalStatus::InProgress => return Err(ExecError::InProgress),
Expand Down Expand Up @@ -408,16 +410,16 @@ impl Contract {
}

/// Allows admin to add a user to the whitelist.
pub fn admin_add_to_whitelist(&mut self, user: AccountId) {
self.assert_admin();
self.iom_whitelist.insert(user);
}
// pub fn admin_add_to_whitelist(&mut self, user: AccountId) {
// self.assert_admin();
// self.iom_whitelist.insert(user);
// }

/// Allows admin to remove a user from the whitelist.
pub fn admin_remove_from_whitelist(&mut self, user: AccountId) {
self.assert_admin();
self.iom_whitelist.remove(&user);
}
// pub fn admin_remove_from_whitelist(&mut self, user: AccountId) {
// self.assert_admin();
// self.iom_whitelist.remove(&user);
// }

// /// udpate voting time for e2e tests purposes
// /// TODO: remove
Expand Down Expand Up @@ -467,9 +469,9 @@ impl Contract {
);
}

fn assert_whitelist(&self, account_id: &AccountId) {
require!(self.iom_whitelist.contains(account_id), "not whitelisted");
}
// fn assert_whitelist(&self, account_id: &AccountId) {
// require!(self.iom_whitelist.contains(account_id), "not whitelisted");
// }

fn remove_pre_vote_prop(&mut self, id: u32) -> Result<Proposal, PrevoteError> {
self.pre_vote_proposals
Expand Down Expand Up @@ -497,11 +499,8 @@ impl Contract {
emit_prevote_prop_slashed(prop_id, amount);
}

fn prop_consent(&self, prop: &Proposal) -> Consent {
match prop.kind.required_consent() {
ConsentKind::Simple => self.simple_consent.clone(),
ConsentKind::Super => self.super_consent.clone(),
}
fn prop_consent(&self, id: u32) -> Consent {
self.proposal_consent.get(&id).unwrap()
}

fn add_vote(&mut self, prop_id: u32, user: AccountId, vote: Vote, prop: &mut Proposal) {
Expand Down Expand Up @@ -1340,30 +1339,30 @@ mod unit_tests {
assert_eq!(c2, ctr.super_consent);
}

#[test]
fn update_white_list() {
let (mut ctx, mut ctr, _) = setup_ctr(BOND);
ctx.predecessor_account_id = admin();
testing_env!(ctx.clone());

assert_eq!(ctr.is_iom_whitelisted(&acc(1)), false);
ctr.admin_add_to_whitelist(acc(1));
assert_eq!(ctr.is_iom_whitelisted(&acc(1)), true);
ctr.admin_remove_from_whitelist(acc(1));
assert_eq!(ctr.is_iom_whitelisted(&acc(1)), false);
}

#[test]
fn whitelisted_can_vote() {
let (mut ctx, mut ctr, id) = setup_ctr(BOND);
ctx.predecessor_account_id = admin();
testing_env!(ctx.clone());
ctr.admin_add_to_whitelist(acc(1));
ctx.predecessor_account_id = acc(1);
ctx.attached_deposit = VOTE_DEPOSIT;
testing_env!(ctx.clone());
ctr.vote_whitelist(vote_payload(id, Vote::Approve));
}
// #[test]
// fn update_white_list() {
// let (mut ctx, mut ctr, _) = setup_ctr(BOND);
// ctx.predecessor_account_id = admin();
// testing_env!(ctx.clone());
//
// assert_eq!(ctr.is_iom_whitelisted(&acc(1)), false);
// ctr.admin_add_to_whitelist(acc(1));
// assert_eq!(ctr.is_iom_whitelisted(&acc(1)), true);
// ctr.admin_remove_from_whitelist(acc(1));
// assert_eq!(ctr.is_iom_whitelisted(&acc(1)), false);
// }
//
// #[test]
// fn whitelisted_can_vote() {
// let (mut ctx, mut ctr, id) = setup_ctr(BOND);
// ctx.predecessor_account_id = admin();
// testing_env!(ctx.clone());
// ctr.admin_add_to_whitelist(acc(1));
// ctx.predecessor_account_id = acc(1);
// ctx.attached_deposit = VOTE_DEPOSIT;
// testing_env!(ctx.clone());
// ctr.vote_whitelist(vote_payload(id, Vote::Approve));
// }

#[test]
fn not_called_by_iah_registry() {
Expand Down
9 changes: 7 additions & 2 deletions voting_body/src/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub struct OldState {
pub pre_vote_duration: u64,
pub vote_duration: u64,
pub accounts: LazyOption<Accounts>,

pub iom_whitelist: LookupSet<AccountId>,
pub proposal_consent: LookupMap<u32, Consent>,
}

#[near_bindgen]
Expand All @@ -34,6 +37,7 @@ impl Contract {
#[init(ignore_state)]
pub fn migrate() -> Self {
let old_state: OldState = env::state_read().expect("Old state doesn't exist");

Self {
prop_counter: old_state.prop_counter,
pre_vote_proposals: old_state.pre_vote_proposals,
Expand All @@ -47,7 +51,8 @@ impl Contract {
pre_vote_duration: old_state.pre_vote_duration,
vote_duration: old_state.vote_duration,
accounts: old_state.accounts,
iom_whitelist: LookupSet::new(StorageKey::IomWhitelist),
iom_whitelist: old_state.iom_whitelist,
proposal_consent: old_state.proposal_consent,
}
}
}
}
1 change: 1 addition & 0 deletions voting_body/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub enum StorageKey {
Accounts,
Votes,
IomWhitelist,
ProposalConsent,
}

/// External account required for the Voting Body.
Expand Down
24 changes: 20 additions & 4 deletions voting_body/src/view.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cmp::{max, min};
use std::collections::HashMap;

use itertools::Either;
use near_sdk::serde::Serialize;
Expand Down Expand Up @@ -82,7 +83,7 @@ impl Contract {

iter.filter_map(|id| {
proposals.get(&id).map(|mut proposal| {
proposal.recompute_status(self.vote_duration, self.prop_consent(&proposal));
proposal.recompute_status(self.vote_duration, self.prop_consent(id));
ProposalOutput { id, proposal }
})
})
Expand All @@ -96,7 +97,7 @@ impl Contract {
p = self.pre_vote_proposals.get(&id);
}
p.map(|mut proposal| {
proposal.recompute_status(self.vote_duration, self.prop_consent(&proposal));
proposal.recompute_status(self.vote_duration, self.prop_consent(id));
ProposalOutput { id, proposal }
})
}
Expand Down Expand Up @@ -136,7 +137,22 @@ impl Contract {
self._get_proposals(from_index, limit, reverse, true)
}

pub fn is_iom_whitelisted(&self, account_id: &AccountId) -> bool {
self.iom_whitelist.contains(&account_id)
// pub fn is_iom_whitelisted(&self, account_id: &AccountId) -> bool {
// self.iom_whitelist.contains(&account_id)
// }

pub fn get_proposal_consent(&self, id: u32) -> Consent {
self.proposal_consent.get(&id).unwrap_or_else(|| {
panic_str("No consent");
})
}

pub fn get_proposals_consent(&self, id_list: Vec<u32>) -> HashMap<u32, Consent> {
let mut results = HashMap::new();
for id in id_list {
let consent = self.get_proposal_consent(id);
results.insert(id, consent);
}
results
}
}

0 comments on commit d7be420

Please sign in to comment.