-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[framework] Partial governance voting support for delegation pool (#8090
) * Support partial voting in aptos-governance * Support delegation partial governance voting * Add comments * Refactor naming. Fix a edge case when a delegation pool voter votes before enabling partial governance voting on this delegation pool. Add DelegateVotingPowerEvent. Fix typos. * Remove redundant condition checking * Fix naming Fix comments Remove get_latest_delegator_vote_delegation and get_latest_vote_delegation Wrap logic of updating governance records into functions Fix a bug of governance records when withdrawing inactive shares Fix get_remaining_voting_power in aptos_governance when proposals expire * Add TODOs * Fix lint * Fix struct annotation * Fix a typo * Fix a bug about voting power Fix a comment Add additional feature flag checking in delegation_pool.move * Fix specs * Remove unnecessary move prover change * Fix enable_partial_governance_voting condition in initialize_delegation_pool * Remove redundant borrow Remove unnecessary prover spec pragma * Use smart_table instead of table in aptos_governance --------- Co-authored-by: Teng Zhang <[email protected]>
- Loading branch information
Showing
19 changed files
with
4,812 additions
and
523 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright © Aptos Foundation | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::harness::MoveHarness; | ||
use aptos::move_tool::MemberId; | ||
use aptos_cached_packages::aptos_stdlib; | ||
use aptos_language_e2e_tests::account::Account; | ||
use aptos_types::{ | ||
account_address::AccountAddress, state_store::table::TableHandle, | ||
transaction::TransactionStatus, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
use std::str::FromStr; | ||
|
||
#[derive(Deserialize, Serialize)] | ||
struct PartialVotingProposals { | ||
pub proposals: TableHandle, | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
struct RecordKey { | ||
pub stake_pool: AccountAddress, | ||
pub proposal_id: u64, | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
struct VotingRecordsV2 { | ||
pub votes: TableHandle, | ||
} | ||
|
||
pub fn create_proposal_v2( | ||
harness: &mut MoveHarness, | ||
account: &Account, | ||
stake_pool: AccountAddress, | ||
execution_hash: Vec<u8>, | ||
metadata_location: Vec<u8>, | ||
metadata_hash: Vec<u8>, | ||
is_multi_step_proposal: bool, | ||
) -> TransactionStatus { | ||
harness.run_transaction_payload( | ||
account, | ||
aptos_stdlib::aptos_governance_create_proposal_v2( | ||
stake_pool, | ||
execution_hash, | ||
metadata_location, | ||
metadata_hash, | ||
is_multi_step_proposal, | ||
), | ||
) | ||
} | ||
|
||
pub fn partial_vote( | ||
harness: &mut MoveHarness, | ||
account: &Account, | ||
stake_pool: AccountAddress, | ||
proposal_id: u64, | ||
voting_power: u64, | ||
should_pass: bool, | ||
) -> TransactionStatus { | ||
harness.run_transaction_payload( | ||
account, | ||
aptos_stdlib::aptos_governance_partial_vote( | ||
stake_pool, | ||
proposal_id, | ||
voting_power, | ||
should_pass, | ||
), | ||
) | ||
} | ||
|
||
pub fn get_remaining_voting_power( | ||
harness: &mut MoveHarness, | ||
stake_pool: AccountAddress, | ||
proposal_id: u64, | ||
) -> u64 { | ||
let fun = MemberId::from_str("0x1::aptos_governance::get_remaining_voting_power").unwrap(); | ||
let res = harness | ||
.execute_view_function(fun, vec![], vec![ | ||
bcs::to_bytes(&stake_pool).unwrap(), | ||
bcs::to_bytes(&proposal_id).unwrap(), | ||
]) | ||
.unwrap(); | ||
bcs::from_bytes::<u64>(&res[0]).unwrap() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,4 @@ mod token_objects; | |
mod transaction_fee; | ||
mod type_too_large; | ||
mod vector_numeric_address; | ||
mod vote; |
6 changes: 6 additions & 0 deletions
6
aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/Move.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = 'EnablePartialGovernanceVoting' | ||
version = "0.0.0" | ||
|
||
[dependencies] | ||
AptosFramework = { local = "../../../../../framework/aptos-framework" } |
13 changes: 13 additions & 0 deletions
13
...ove/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
script { | ||
use aptos_framework::aptos_governance; | ||
use std::features; | ||
use aptos_framework::aptos_governance::reconfigure; | ||
|
||
fun main(core_resources: &signer) { | ||
let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @aptos_framework); | ||
aptos_governance::initialize_partial_voting(&framework_signer); | ||
let feature = features::get_partial_governance_voting(); | ||
features::change_feature_flags(&framework_signer, vector[feature], vector[]); | ||
reconfigure(&framework_signer); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// Copyright © Aptos Foundation | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::{ | ||
aptos_governance::*, assert_abort, assert_success, increase_lockup, setup_staking, | ||
tests::common, MoveHarness, | ||
}; | ||
use aptos_types::account_address::AccountAddress; | ||
use once_cell::sync::Lazy; | ||
use std::collections::BTreeMap; | ||
|
||
pub static PROPOSAL_SCRIPTS: Lazy<BTreeMap<String, Vec<u8>>> = Lazy::new(build_scripts); | ||
|
||
fn build_scripts() -> BTreeMap<String, Vec<u8>> { | ||
let package_folder = "vote.data"; | ||
let package_names = vec!["enable_partial_governance_voting"]; | ||
common::build_scripts(package_folder, package_names) | ||
} | ||
|
||
#[test] | ||
fn test_vote() { | ||
// Genesis starts with one validator with index 0 | ||
let mut harness = MoveHarness::new(); | ||
let validator_1 = harness.new_account_at(AccountAddress::from_hex_literal("0x123").unwrap()); | ||
let validator_2 = harness.new_account_at(AccountAddress::from_hex_literal("0x234").unwrap()); | ||
let validator_1_address = *validator_1.address(); | ||
let validator_2_address = *validator_2.address(); | ||
|
||
let stake_amount_1 = 25_000_000; | ||
assert_success!(setup_staking(&mut harness, &validator_1, stake_amount_1)); | ||
assert_success!(increase_lockup(&mut harness, &validator_1)); | ||
let stake_amount_2 = 25_000_000; | ||
assert_success!(setup_staking(&mut harness, &validator_2, stake_amount_2)); | ||
assert_success!(increase_lockup(&mut harness, &validator_2)); | ||
|
||
let mut proposal_id: u64 = 0; | ||
assert_success!(create_proposal_v2( | ||
&mut harness, | ||
&validator_2, | ||
validator_2_address, | ||
vec![1], | ||
vec![], | ||
vec![], | ||
true | ||
)); | ||
// Voters can vote on a partial voting proposal but argument voting_power will be ignored. | ||
assert_success!(partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
proposal_id, | ||
100, | ||
true | ||
)); | ||
// No remaining voting power. | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_1_address, proposal_id), | ||
0 | ||
); | ||
|
||
// Enable partial governance voting. In production it requires governance. | ||
let core_resources = | ||
harness.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); | ||
let script_code = PROPOSAL_SCRIPTS | ||
.get("enable_partial_governance_voting") | ||
.expect("proposal script should be built"); | ||
let txn = harness.create_script(&core_resources, script_code.clone(), vec![], vec![]); | ||
assert_success!(harness.run(txn)); | ||
|
||
// If a voter has already voted on a proposal before partial voting is enabled, the voter cannot vote on the proposal again. | ||
assert_abort!( | ||
partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
proposal_id, | ||
100, | ||
true | ||
), | ||
0x10005 | ||
); | ||
|
||
assert_success!(create_proposal_v2( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
vec![1], | ||
vec![], | ||
vec![], | ||
true | ||
)); | ||
|
||
// Cannot vote on a non-exist proposal. | ||
let wrong_proposal_id: u64 = 2; | ||
assert_abort!( | ||
partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
wrong_proposal_id, | ||
100, | ||
true | ||
), | ||
25863 | ||
); | ||
|
||
proposal_id = 1; | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_1_address, proposal_id), | ||
stake_amount_1 | ||
); | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_2_address, proposal_id), | ||
stake_amount_1 | ||
); | ||
|
||
// A voter can vote on a proposal multiple times with both Yes/No. | ||
assert_success!(partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
proposal_id, | ||
100, | ||
true | ||
)); | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_1_address, proposal_id), | ||
stake_amount_1 - 100 | ||
); | ||
assert_success!(partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
proposal_id, | ||
1000, | ||
false | ||
)); | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_1_address, proposal_id), | ||
stake_amount_1 - 1100 | ||
); | ||
// A voter cannot use voting power more than it has. | ||
assert_success!(partial_vote( | ||
&mut harness, | ||
&validator_1, | ||
validator_1_address, | ||
proposal_id, | ||
stake_amount_1, | ||
true | ||
)); | ||
assert_eq!( | ||
get_remaining_voting_power(&mut harness, validator_1_address, proposal_id), | ||
0 | ||
); | ||
} |
Oops, something went wrong.