Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Murisi/move init proposal content #1611

Merged
merged 7 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Move the content and code of init proposal transactions
into separare section to reduce tx size for hardware wallets
([\#1611](https://github.com/anoma/namada/pull/1611))
11 changes: 11 additions & 0 deletions apps/src/bin/namada-client/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ pub async fn main() -> Result<()> {
tx::submit_withdraw::<HttpClient>(&client, ctx, args)
.await?;
}
Sub::TxCommissionRateChange(TxCommissionRateChange(args)) => {
wait_until_node_is_synched(&args.tx.ledger_address).await;
let client =
HttpClient::new(args.tx.ledger_address.clone())
.unwrap();
let args = args.to_sdk(&mut ctx);
tx::submit_validator_commission_change::<HttpClient>(
&client, ctx, args,
)
.await?;
}
// Ledger queries
Sub::QueryEpoch(QueryEpoch(args)) => {
wait_until_node_is_synched(&args.ledger_address).await;
Expand Down
41 changes: 36 additions & 5 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ pub mod cmds {
.subcommand(Bond::def().display_order(2))
.subcommand(Unbond::def().display_order(2))
.subcommand(Withdraw::def().display_order(2))
.subcommand(TxCommissionRateChange::def().display_order(2))
// Queries
.subcommand(QueryEpoch::def().display_order(3))
.subcommand(QueryTransfers::def().display_order(3))
Expand Down Expand Up @@ -198,6 +199,8 @@ pub mod cmds {
Self::parse_with_ctx(matches, TxInitProposal);
let tx_vote_proposal =
Self::parse_with_ctx(matches, TxVoteProposal);
let tx_commission_rate_change =
Self::parse_with_ctx(matches, TxCommissionRateChange);
let bond = Self::parse_with_ctx(matches, Bond);
let unbond = Self::parse_with_ctx(matches, Unbond);
let withdraw = Self::parse_with_ctx(matches, Withdraw);
Expand Down Expand Up @@ -232,6 +235,7 @@ pub mod cmds {
.or(tx_init_proposal)
.or(tx_vote_proposal)
.or(tx_init_validator)
.or(tx_commission_rate_change)
.or(bond)
.or(unbond)
.or(withdraw)
Expand Down Expand Up @@ -294,6 +298,7 @@ pub mod cmds {
TxUpdateVp(TxUpdateVp),
TxInitAccount(TxInitAccount),
TxInitValidator(TxInitValidator),
TxCommissionRateChange(TxCommissionRateChange),
TxInitProposal(TxInitProposal),
TxVoteProposal(TxVoteProposal),
TxRevealPk(TxRevealPk),
Expand Down Expand Up @@ -1534,6 +1539,32 @@ pub mod cmds {
}
}

#[derive(Clone, Debug)]
pub struct TxCommissionRateChange(
pub args::CommissionRateChange<args::CliTypes>,
);

impl SubCmd for TxCommissionRateChange {
const CMD: &'static str = "change-commission-rate";

fn parse(matches: &ArgMatches) -> Option<Self>
where
Self: Sized,
{
matches.subcommand_matches(Self::CMD).map(|matches| {
TxCommissionRateChange(args::CommissionRateChange::parse(
matches,
))
})
}

fn def() -> App {
App::new(Self::CMD)
.about("Change commission raate.")
.add_args::<args::CommissionRateChange<args::CliTypes>>()
}
}

#[derive(Clone, Debug)]
pub struct TxVoteProposal(pub args::VoteProposal<args::CliTypes>);

Expand Down Expand Up @@ -3101,11 +3132,11 @@ pub mod args {
}
}

impl CliToSdk<TxCommissionRateChange<SdkTypes>>
for TxCommissionRateChange<CliTypes>
impl CliToSdk<CommissionRateChange<SdkTypes>>
for CommissionRateChange<CliTypes>
{
fn to_sdk(self, ctx: &mut Context) -> TxCommissionRateChange<SdkTypes> {
TxCommissionRateChange::<SdkTypes> {
fn to_sdk(self, ctx: &mut Context) -> CommissionRateChange<SdkTypes> {
CommissionRateChange::<SdkTypes> {
tx: self.tx.to_sdk(ctx),
validator: ctx.get(&self.validator),
rate: self.rate,
Expand All @@ -3114,7 +3145,7 @@ pub mod args {
}
}

impl Args for TxCommissionRateChange<CliTypes> {
impl Args for CommissionRateChange<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let tx = Tx::parse(matches);
let validator = VALIDATOR.parse(matches);
Expand Down
48 changes: 33 additions & 15 deletions apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ use namada::types::hash::Hash;
use namada::types::key::*;
use namada::types::storage::{Epoch, Key};
use namada::types::token;
use namada::types::transaction::governance::{
InitProposalData, ProposalType, VoteProposalData,
};
use namada::types::transaction::governance::{ProposalType, VoteProposalData};
use namada::types::transaction::{InitValidator, TxType};
use sha2::{Digest as Sha2Digest, Sha256};

Expand Down Expand Up @@ -566,13 +564,14 @@ pub async fn submit_init_proposal<C: namada::ledger::queries::Client + Sync>(
Ok(())
} else {
let signer = ctx.get(&signer);
let tx_data: Result<InitProposalData, _> = proposal.clone().try_into();
let init_proposal_data = if let Ok(data) = tx_data {
data
} else {
eprintln!("Invalid data for init proposal transaction.");
safe_exit(1)
};
let tx_data = proposal.clone().try_into();
let (mut init_proposal_data, init_proposal_content, init_proposal_code) =
if let Ok(data) = tx_data {
data
} else {
eprintln!("Invalid data for init proposal transaction.");
safe_exit(1)
};

let balance =
rpc::get_token_balance(client, &ctx.native_token, &proposal.author)
Expand All @@ -592,22 +591,41 @@ pub async fn submit_init_proposal<C: namada::ledger::queries::Client + Sync>(
safe_exit(1);
}

if init_proposal_data.content.len()
if init_proposal_content.len()
> governance_parameters.max_proposal_content_size as usize
{
eprintln!("Proposal content size too big.",);
safe_exit(1);
}

let mut tx = Tx::new(TxType::Raw);
let data = init_proposal_data
.try_to_vec()
.expect("Encoding proposal data shouldn't fail");
let tx_code_hash = query_wasm_code_hash(client, args::TX_INIT_PROPOSAL)
.await
.unwrap();
tx.header.chain_id = ctx.config.ledger.chain_id.clone();
tx.header.expiration = args.tx.expiration;
// Put the content of this proposal into an extra section
{
let content_sec = tx.add_section(Section::ExtraData(Code::new(
init_proposal_content,
)));
let content_sec_hash = Hash(
content_sec.hash(&mut Sha256::new()).finalize_reset().into(),
);
init_proposal_data.content = content_sec_hash;
}
// Put any proposal code into an extra section
if let Some(init_proposal_code) = init_proposal_code {
let code_sec = tx
.add_section(Section::ExtraData(Code::new(init_proposal_code)));
let code_sec_hash =
Hash(code_sec.hash(&mut Sha256::new()).finalize_reset().into());
init_proposal_data.r#type =
ProposalType::Default(Some(code_sec_hash));
}
let data = init_proposal_data
.try_to_vec()
.expect("Encoding proposal data shouldn't fail");
tx.set_data(Data::new(data));
tx.set_code(Code::from_hash(tx_code_hash));

Expand Down Expand Up @@ -1036,7 +1054,7 @@ pub async fn submit_validator_commission_change<
>(
client: &C,
mut ctx: Context,
mut args: args::TxCommissionRateChange,
mut args: args::CommissionRateChange,
) -> Result<(), tx::Error> {
args.tx.chain_id = args
.tx
Expand Down
5 changes: 4 additions & 1 deletion apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,7 @@ mod test_finalize_block {
use namada::proto::{Code, Data, Section, Signature};
use namada::types::dec::POS_DECIMAL_PRECISION;
use namada::types::governance::ProposalVote;
use namada::types::hash::Hash;
use namada::types::key::tm_consensus_key_raw_hash;
use namada::types::storage::Epoch;
use namada::types::time::DurationSecs;
Expand Down Expand Up @@ -1316,7 +1317,7 @@ mod test_finalize_block {

let proposal = InitProposalData {
id: Some(proposal_id),
content: vec![],
content: Hash::default(),
author: validator.clone(),
voting_start_epoch: Epoch::default(),
voting_end_epoch: Epoch::default().next(),
Expand All @@ -1327,6 +1328,8 @@ mod test_finalize_block {
storage_api::governance::init_proposal(
&mut shell.wl_storage,
proposal,
vec![],
None,
)
.unwrap();

Expand Down
15 changes: 11 additions & 4 deletions core/src/ledger/storage_api/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use crate::types::transaction::governance::{
pub fn init_proposal<S>(
storage: &mut S,
data: InitProposalData,
content: Vec<u8>,
code: Option<Vec<u8>>,
) -> storage_api::Result<()>
where
S: StorageRead + StorageWrite,
Expand All @@ -23,18 +25,21 @@ where
};

let content_key = storage::get_content_key(proposal_id);
storage.write_bytes(&content_key, data.content)?;
storage.write_bytes(&content_key, content)?;

let author_key = storage::get_author_key(proposal_id);
storage.write(&author_key, data.author.clone())?;

let proposal_type_key = storage::get_proposal_type_key(proposal_id);
match data.r#type {
ProposalType::Default(Some(ref code)) => {
ProposalType::Default(Some(_)) => {
// Remove wasm code and write it under a different subkey
storage.write(&proposal_type_key, ProposalType::Default(None))?;
let proposal_code_key = storage::get_proposal_code_key(proposal_id);
storage.write_bytes(&proposal_code_key, code)?
let proposal_code = code.clone().ok_or(
storage_api::Error::new_const("Missing proposal code"),
)?;
storage.write_bytes(&proposal_code_key, proposal_code)?
}
_ => storage.write(&proposal_type_key, data.r#type.clone())?,
}
Expand All @@ -49,8 +54,10 @@ where
let grace_epoch_key = storage::get_grace_epoch_key(proposal_id);
storage.write(&grace_epoch_key, data.grace_epoch)?;

if let ProposalType::Default(Some(proposal_code)) = data.r#type {
if let ProposalType::Default(Some(_)) = data.r#type {
let proposal_code_key = storage::get_proposal_code_key(proposal_id);
let proposal_code =
code.ok_or(storage_api::Error::new_const("Missing proposal code"))?;
storage.write_bytes(&proposal_code_key, proposal_code)?;
}

Expand Down
47 changes: 30 additions & 17 deletions core/src/types/transaction/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::types::address::Address;
use crate::types::governance::{
self, Proposal, ProposalError, ProposalVote, VoteType,
};
use crate::types::hash::Hash;
use crate::types::storage::Epoch;

/// The type of a Proposal
Expand All @@ -21,7 +22,7 @@ use crate::types::storage::Epoch;
)]
pub enum ProposalType {
/// Default governance proposal with the optional wasm code
Default(Option<Vec<u8>>),
Default(Option<Hash>),
/// PGF council proposal
PGFCouncil,
/// ETH proposal
Expand Down Expand Up @@ -54,23 +55,30 @@ impl PartialEq<VoteType> for ProposalType {
}
}

impl TryFrom<governance::ProposalType> for ProposalType {
impl TryFrom<governance::ProposalType> for (ProposalType, Option<Vec<u8>>) {
type Error = ProposalError;

fn try_from(value: governance::ProposalType) -> Result<Self, Self::Error> {
match value {
governance::ProposalType::Default(path) => {
if let Some(p) = path {
match std::fs::read(p) {
Ok(code) => Ok(Self::Default(Some(code))),
Ok(code) => Ok((
ProposalType::Default(Some(Hash::default())),
Some(code),
)),
Err(_) => Err(Self::Error::InvalidProposalData),
}
} else {
Ok(Self::Default(None))
Ok((ProposalType::Default(None), None))
}
}
governance::ProposalType::PGFCouncil => Ok(Self::PGFCouncil),
governance::ProposalType::ETHBridge => Ok(Self::ETHBridge),
governance::ProposalType::PGFCouncil => {
Ok((ProposalType::PGFCouncil, None))
}
governance::ProposalType::ETHBridge => {
Ok((ProposalType::ETHBridge, None))
}
}
}
}
Expand All @@ -89,7 +97,7 @@ pub struct InitProposalData {
/// The proposal id
pub id: Option<u64>,
/// The proposal content
pub content: Vec<u8>,
pub content: Hash,
/// The proposal author address
pub author: Address,
/// The proposal type
Expand Down Expand Up @@ -123,18 +131,23 @@ pub struct VoteProposalData {
pub delegations: Vec<Address>,
}

impl TryFrom<Proposal> for InitProposalData {
impl TryFrom<Proposal> for (InitProposalData, Vec<u8>, Option<Vec<u8>>) {
type Error = ProposalError;

fn try_from(proposal: Proposal) -> Result<Self, Self::Error> {
Ok(InitProposalData {
id: proposal.id,
content: proposal.content.try_to_vec().unwrap(),
author: proposal.author,
r#type: proposal.r#type.try_into()?,
voting_start_epoch: proposal.voting_start_epoch,
voting_end_epoch: proposal.voting_end_epoch,
grace_epoch: proposal.grace_epoch,
})
let (r#type, code) = proposal.r#type.try_into()?;
Ok((
InitProposalData {
id: proposal.id,
content: Hash::default(),
author: proposal.author,
r#type,
voting_start_epoch: proposal.voting_start_epoch,
voting_end_epoch: proposal.voting_end_epoch,
grace_epoch: proposal.grace_epoch,
},
proposal.content.try_to_vec().unwrap(),
code,
))
}
}
Loading