Skip to content

Commit

Permalink
On-chain MultiSig changes at Rust layer (#68)
Browse files Browse the repository at this point in the history
* feat(genesis): interfaces changes to support multisig accounts

* fix(genesis): add ordering traits to genesis types

* fix(genesis): update to latest GenesisConfigurations

* refactor(multisig): update to latest multisig changes from Move

* fix(genesis): optionally pass multisig foundation account testnet encoder
---------

Co-authored-by: so-kkroy22 <[email protected]>
  • Loading branch information
supra-yoga and so-kkroy22 authored Sep 7, 2024
1 parent 69a7f86 commit 496835b
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 80 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

261 changes: 214 additions & 47 deletions aptos-move/vm-genesis/src/lib.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/aptos-genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,14 @@ impl GenesisInfo {
epoch_duration_secs: self.epoch_duration_secs,
is_test: true,
min_stake: self.min_stake,
min_voting_threshold: self.min_voting_threshold,
min_voting_threshold: self.min_voting_threshold as u64,
max_stake: self.max_stake,
recurring_lockup_duration_secs: self.recurring_lockup_duration_secs,
required_proposer_stake: self.required_proposer_stake,
rewards_apy_percentage: self.rewards_apy_percentage,
voting_duration_secs: self.voting_duration_secs,
voters: vec![],
voting_power_increase_limit: self.voting_power_increase_limit,
voters: Vec::new(),
employee_vesting_start: 1663456089,
employee_vesting_period_duration: 5 * 60, // 5 minutes
initial_features_override: self.initial_features_override.clone(),
Expand Down
6 changes: 4 additions & 2 deletions crates/aptos-genesis/src/mainnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ impl MainnetGenesisInfo {
aptos_vm_genesis::encode_aptos_mainnet_genesis_transaction(
&self.accounts,
&[],
None,
&[],
&[],
&self.framework,
self.chain_id,
Expand All @@ -137,14 +139,14 @@ impl MainnetGenesisInfo {
is_test: false,
epoch_duration_secs: self.epoch_duration_secs,
min_stake: self.min_stake,
min_voting_threshold: self.min_voting_threshold,
min_voting_threshold: self.min_voting_threshold as u64,
max_stake: self.max_stake,
recurring_lockup_duration_secs: self.recurring_lockup_duration_secs,
required_proposer_stake: self.required_proposer_stake,
rewards_apy_percentage: self.rewards_apy_percentage,
voting_duration_secs: self.voting_duration_secs,
voters: vec![],
voting_power_increase_limit: self.voting_power_increase_limit,
voters: Vec::new(),
genesis_timestamp_in_microseconds: self.genesis_timestamp_in_microseconds,
employee_vesting_start: self.employee_vesting_start,
employee_vesting_period_duration: self.employee_vesting_period_duration,
Expand Down
141 changes: 116 additions & 25 deletions crates/aptos/src/governance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::common::utils::read_from_file;
use crate::{
common::{
types::{
CliError, CliTypedResult, MovePackageDir, PoolAddressArgs, ProfileOptions,
CliError, CliTypedResult, MovePackageDir, ProfileOptions,
PromptOptions, RestOptions, TransactionOptions, TransactionSummary,
},
utils::prompt_yes_with_override,
Expand Down Expand Up @@ -49,6 +49,7 @@ use std::{
fs,
path::{Path, PathBuf},
};
use supra_aptos::{SupraCommand, SupraCommandArguments};
use tempfile::TempDir;

/// Tool for on-chain governance
Expand Down Expand Up @@ -112,7 +113,7 @@ impl CliCommand<VerifiedProposal> for ViewProposal {
let forum = client
.get_account_resource_bcs::<VotingForum>(
AccountAddress::ONE,
"0x1::voting::VotingForum<0x1::governance_proposal::GovernanceProposal>",
"0x1::multisig_voting::VotingForum<0x1::governance_proposal::GovernanceProposal>", // multisig_voting
)
.await?
.into_inner();
Expand Down Expand Up @@ -174,7 +175,7 @@ impl CliCommand<Vec<ProposalSummary>> for ListProposals {
let events = client
.get_account_events_bcs(
AccountAddress::ONE,
"0x1::supra_governance::GovernanceEvents",
"0x1::supra_governance::SupraGovernanceEvents",
"create_proposal_events",
None,
Some(100),
Expand Down Expand Up @@ -237,7 +238,7 @@ impl CliCommand<VerifyProposalResponse> for VerifyProposal {
let forum = client
.get_account_resource_bcs::<VotingForum>(
AccountAddress::ONE,
"0x1::voting::VotingForum<0x1::governance_proposal::GovernanceProposal>",
"0x1::multisig_voting::VotingForum<0x1::governance_proposal::GovernanceProposal>", // multisig_voting
)
.await?
.into_inner();
Expand Down Expand Up @@ -268,7 +269,7 @@ async fn get_proposal(
.get_table_item(
voting_table,
"u64",
"0x1::voting::Proposal<0x1::governance_proposal::GovernanceProposal>",
"0x1::multisig_voting::Proposal<0x1::governance_proposal::GovernanceProposal>", // multisig_voting
format!("{}", proposal_id),
)
.await?
Expand Down Expand Up @@ -404,6 +405,40 @@ impl CliCommand<ProposalSubmissionSummary> for SubmitProposal {
}
}

#[async_trait]
impl SupraCommand for SubmitProposal {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
// Validate the proposal metadata
let (script_hash, metadata_hash) = self.args.compile_proposals().await?;
prompt_yes_with_override(
"Do you want to submit this proposal?",
self.args.txn_options.prompt_options,
)?;

let payload = if self.args.is_multi_step {
aptos_stdlib::supra_governance_supra_create_proposal_v2(
script_hash.to_vec(),
self.args.metadata_url.to_string().as_bytes().to_vec(),
metadata_hash.to_hex().as_bytes().to_vec(),
true,
)
} else {
aptos_stdlib::supra_governance_supra_create_proposal(
script_hash.to_vec(),
self.args.metadata_url.to_string().as_bytes().to_vec(),
metadata_hash.to_hex().as_bytes().to_vec(),
)
};
Ok(SupraCommandArguments {
payload,
sender_account: self.args.txn_options.sender_account,
profile_options: supra_aptos::ProfileOptions::from(self.args.txn_options.profile_options),
rest_options: supra_aptos::RestOptions::from(self.args.txn_options.rest_options),
gas_options: supra_aptos::GasOptions::from(self.args.txn_options.gas_options),
})
}
}

/// Retrieve the Metadata from the given URL
async fn get_metadata_from_url(metadata_url: &Url) -> CliTypedResult<Vec<u8>> {
let client = reqwest::ClientBuilder::default()
Expand Down Expand Up @@ -436,7 +471,7 @@ fn extract_proposal_id(txn: &Transaction) -> CliTypedResult<Option<u64>> {
if let Transaction::UserTransaction(inner) = txn {
// Find event with proposal id
let proposal_id = if let Some(event) = inner.events.iter().find(|event| {
event.typ.to_string().as_str() == "0x1::supra_governance::CreateProposalEvent"
event.typ.to_string().as_str() == "0x1::supra_governance::SupraCreateProposalEvent"
}) {
let data: CreateProposalEvent =
serde_json::from_value(event.data.clone()).map_err(|_| {
Expand Down Expand Up @@ -498,7 +533,7 @@ pub struct SubmitVoteArgs {
#[clap(long, group = "vote")]
pub(crate) no: bool,

/// Voting power to use for the vote. If not specified, all the voting power will be used.
// Voting power to use for the vote. If not specified, all the voting power will be used.
#[clap(long)]
pub(crate) voting_power: Option<u64>,

Expand Down Expand Up @@ -677,25 +712,52 @@ impl CliCommand<Vec<TransactionSummary>> for SubmitVote {
async fn execute(mut self) -> CliTypedResult<Vec<TransactionSummary>> {
// The vote option is a group, so only one of yes and no must be true.
let vote = self.args.yes;
let proposal_id = self.args.proposal_id;

let client: &Client = &self
.args
.txn_options
.rest_options
.client(&self.args.txn_options.profile_options)?;
let mut summaries: Vec<TransactionSummary> = vec![];
summaries.push(
self.args
.txn_options
.submit_transaction(aptos_stdlib::supra_governance_supra_vote(
proposal_id,
vote,
))
.await
.map(TransactionSummary::from)?,
);
Ok(summaries)
}
}

if is_partial_governance_voting_enabled(client).await? {
self.vote_after_partial_governance_voting(vote).await
} else {
return self
.vote_before_partial_governance_voting(client, vote)
.await;
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct VotingRecord {
proposal_id: String,
stake_pool: AccountAddress,
}

#[async_trait]
impl SupraCommand for SubmitVote {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
// The vote option is a group, so only one of yes and no must be true.
let vote = self.args.yes;
let proposal_id = self.args.proposal_id;

let payload = aptos_stdlib::supra_governance_supra_vote(
proposal_id,
vote,
);
Ok(SupraCommandArguments {
payload,
sender_account: self.args.txn_options.sender_account,
profile_options: supra_aptos::ProfileOptions::from(self.args.txn_options.profile_options),
rest_options: supra_aptos::RestOptions::from(self.args.txn_options.rest_options),
gas_options: supra_aptos::GasOptions::from(self.args.txn_options.gas_options),
})
}
}

/// Submit a transaction to approve a proposal's script hash to bypass the transaction size limit.
/// This is needed for upgrading large packages such as aptos-framework.
/// This is needed for upgrading large packages such as supra-framework.
#[derive(Parser)]
pub struct ApproveExecutionHash {
/// Id of the proposal to vote on
Expand Down Expand Up @@ -723,10 +785,18 @@ impl CliCommand<TransactionSummary> for ApproveExecutionHash {
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct VotingRecord {
proposal_id: String,
stake_pool: AccountAddress,
#[async_trait]
impl SupraCommand for ApproveExecutionHash {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
let payload = aptos_stdlib::supra_governance_add_supra_approved_script_hash_script(self.proposal_id);
Ok(SupraCommandArguments{
payload,
sender_account: self.txn_options.sender_account,
profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options),
rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options),
gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options),
})
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -862,6 +932,27 @@ impl CliCommand<TransactionSummary> for ExecuteProposal {
}
}

#[async_trait]
impl SupraCommand for ExecuteProposal {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
let (bytecode, _script_hash) = self
.compile_proposal_args
.compile("ExecuteProposal", self.txn_options.prompt_options)?;
// TODO: Check hash so we don't do a failed roundtrip?

let args = vec![TransactionArgument::U64(self.proposal_id)];
let payload = TransactionPayload::Script(Script::new(bytecode, vec![], args));

Ok(SupraCommandArguments{
payload,
sender_account: self.txn_options.sender_account,
profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options),
rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options),
gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options),
})
}
}

/// Compile a specified script.
#[derive(Parser)]
pub struct CompileScriptFunction {
Expand Down Expand Up @@ -1032,7 +1123,7 @@ impl GenerateExecutionHash {
.canonicalize()
.map_err(|err| {
CliError::IO(
format!("Failed to canonicalize aptos framework path: {:?}", path),
format!("Failed to canonicalize supra framework path: {:?}", path),
err,
)
})?
Expand Down
9 changes: 6 additions & 3 deletions crates/aptos/src/move_tool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,9 @@ impl CliCommand<TransactionSummary> for PublishPackage {
}
}

#[async_trait]
impl SupraCommand for PublishPackage {
fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
let package_publication_data: PackagePublicationData = (&self).try_into()?;
Ok(SupraCommandArguments {
payload: package_publication_data.payload,
Expand Down Expand Up @@ -1475,8 +1476,9 @@ impl CliCommand<TransactionSummary> for RunFunction {
}
}

#[async_trait]
impl SupraCommand for RunFunction {
fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
Ok(SupraCommandArguments {
payload: TransactionPayload::EntryFunction(self.entry_function_args.try_into()?),
sender_account: self.txn_options.sender_account,
Expand Down Expand Up @@ -1539,8 +1541,9 @@ impl CliCommand<TransactionSummary> for RunScript {
}
}

#[async_trait]
impl SupraCommand for RunScript {
fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
async fn supra_command_arguments(self) -> anyhow::Result<SupraCommandArguments> {
let (bytecode, _script_hash) = self
.compile_proposal_args
.compile("RunScript", self.txn_options.prompt_options)?;
Expand Down
1 change: 1 addition & 0 deletions crates/supra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ rust-version.workspace = true
aptos-types = { workspace = true }
reqwest = { workspace = true }
anyhow = { workspace = true }
async-trait= { workspace = true }
4 changes: 3 additions & 1 deletion crates/supra/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// Copyright © Entropy Foundation

use anyhow::Result;
use async_trait::async_trait;
use aptos_types::account_address::AccountAddress;
use aptos_types::transaction::TransactionPayload;

Expand Down Expand Up @@ -77,8 +78,9 @@ pub struct SupraCommandArguments {
}

/// Trait required by supra cli for its operation.
#[async_trait]
pub trait SupraCommand {

/// consume self and returns [SupraCommandArguments]
fn supra_command_arguments(self) -> Result<SupraCommandArguments>;
async fn supra_command_arguments(self) -> Result<SupraCommandArguments>;
}

0 comments on commit 496835b

Please sign in to comment.