From 024cfb874244212a930f9b0523b60718daa1e039 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Fri, 17 Feb 2023 14:16:22 +0100 Subject: [PATCH] Refactors proposal execution --- apps/src/lib/node/ledger/shell/governance.rs | 325 ++++++++---------- shared/src/ledger/native_vp/governance/mod.rs | 1 + 2 files changed, 142 insertions(+), 184 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 9efc7d1697e..f508622d56c 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -13,7 +13,7 @@ use namada::ledger::storage::{DBIter, StorageHasher, DB}; use namada::ledger::storage_api::{token, StorageWrite}; use namada::proof_of_stake::read_total_stake; use namada::types::address::Address; -use namada::types::governance::{Tally, TallyResult, VotePower}; +use namada::types::governance::{Council, Tally, TallyResult, VotePower}; use namada::types::storage::Epoch; use super::*; @@ -75,192 +75,30 @@ where // Execute proposal if succesful let transfer_address = match tally_result { TallyResult::Passed(tally) => { - match tally { - Tally::Default => { - let proposal_author_key = - gov_storage::get_author_key(id); - let proposal_author = shell - .read_storage_key::
(&proposal_author_key) - .ok_or_else(|| { - Error::BadProposal( - id, - "Invalid proposal author.".to_string(), - ) - })?; - - let proposal_code_key = - gov_storage::get_proposal_code_key(id); - let proposal_code = - shell.read_storage_key_bytes(&proposal_code_key); - match proposal_code { - Some(proposal_code) => { - let tx = - Tx::new(proposal_code, Some(encode(&id))); - let tx_type = - TxType::Decrypted(DecryptedTx::Decrypted { - tx, - #[cfg(not(feature = "mainnet"))] - has_valid_pow: false, - }); - let pending_execution_key = - gov_storage::get_proposal_execution_key(id); - shell - .wl_storage - .write(&pending_execution_key, ()) - .expect( - "Should be able to write to storage.", - ); - let tx_result = protocol::apply_tx( - tx_type, - 0, /* this is used to compute the fee - * based on the code size. We dont - * need it here. */ - TxIndex::default(), - &mut BlockGasMeter::default(), - &mut shell.wl_storage.write_log, - &shell.wl_storage.storage, - &mut shell.vp_wasm_cache, - &mut shell.tx_wasm_cache, - ); - shell - .wl_storage - .storage - .delete(&pending_execution_key) - .expect( - "Should be able to delete the storage.", - ); - match tx_result { - Ok(tx_result) => { - if tx_result.is_accepted() { - shell.wl_storage.commit_tx(); - let proposal_event: Event = - ProposalEvent::new( - EventType::Proposal - .to_string(), - TallyResult::Passed( - Tally::Default, - ), - id, - true, - true, - ) - .into(); - response - .events - .push(proposal_event); - proposals_result.passed.push(id); - - proposal_author - } else { - shell.wl_storage.drop_tx(); - let proposal_event: Event = - ProposalEvent::new( - EventType::Proposal - .to_string(), - TallyResult::Passed( - Tally::Default, - ), - id, - true, - false, - ) - .into(); - response - .events - .push(proposal_event); - proposals_result.rejected.push(id); - - slash_fund_address - } - } - Err(_e) => { - shell.wl_storage.drop_tx(); - let proposal_event: Event = - ProposalEvent::new( - EventType::Proposal.to_string(), - TallyResult::Passed( - Tally::Default, - ), - id, - true, - false, - ) - .into(); - response.events.push(proposal_event); - proposals_result.rejected.push(id); - - slash_fund_address - } - } - } - None => { - let proposal_event: Event = ProposalEvent::new( - EventType::Proposal.to_string(), - TallyResult::Passed(Tally::Default), - id, - false, - false, - ) - .into(); - response.events.push(proposal_event); - proposals_result.passed.push(id); - - proposal_author - } - } - } + let (successful_execution, proposal_event) = match tally { + Tally::Default => execute_default_proposal(shell, id), Tally::PGFCouncil(council) => { - // TODO: implement when PGF is in place, update the PGF - // council in storage - let proposal_event: Event = ProposalEvent::new( - EventType::Proposal.to_string(), - TallyResult::Passed(Tally::PGFCouncil(council)), - id, - false, - false, - ) - .into(); - response.events.push(proposal_event); - proposals_result.passed.push(id); - - let proposal_author_key = - gov_storage::get_author_key(id); - - shell - .read_storage_key::
(&proposal_author_key) - .ok_or_else(|| { - Error::BadProposal( - id, - "Invalid proposal author.".to_string(), - ) - })? + execute_pgf_proposal(id, council) } - Tally::ETHBridge => { - // TODO: implement when ETH Bridge. Apply the - // modification requested by the proposal - let proposal_event: Event = ProposalEvent::new( - EventType::Proposal.to_string(), - TallyResult::Passed(Tally::ETHBridge), - id, - false, - false, - ) - .into(); - response.events.push(proposal_event); - proposals_result.passed.push(id); + Tally::ETHBridge => execute_eth_proposal(id), + }; - let proposal_author_key = - gov_storage::get_author_key(id); - - shell - .read_storage_key::
(&proposal_author_key) - .ok_or_else(|| { - Error::BadProposal( - id, - "Invalid proposal author.".to_string(), - ) - })? - } + response.events.push(proposal_event); + if successful_execution { + proposals_result.passed.push(id); + shell + .read_storage_key::
( + &gov_storage::get_author_key(id), + ) + .ok_or_else(|| { + Error::BadProposal( + id, + "Invalid proposal author.".to_string(), + ) + })? + } else { + proposals_result.rejected.push(id); + slash_fund_address } } TallyResult::Rejected => { @@ -296,3 +134,122 @@ where Ok(proposals_result) } + +fn execute_default_proposal( + shell: &mut Shell, + id: u64, +) -> (bool, Event) +where + D: DB + for<'iter> DBIter<'iter> + Sync + 'static, + H: StorageHasher + Sync + 'static, +{ + let proposal_code_key = gov_storage::get_proposal_code_key(id); + let proposal_code = shell.read_storage_key_bytes(&proposal_code_key); + match proposal_code { + Some(proposal_code) => { + let tx = Tx::new(proposal_code, Some(encode(&id))); + let tx_type = TxType::Decrypted(DecryptedTx::Decrypted { + tx, + #[cfg(not(feature = "mainnet"))] + has_valid_pow: false, + }); + let pending_execution_key = + gov_storage::get_proposal_execution_key(id); + shell + .wl_storage + .write(&pending_execution_key, ()) + .expect("Should be able to write to storage."); + let tx_result = protocol::apply_tx( + tx_type, + 0, /* this is used to compute the fee + * based on the code size. We dont + * need it here. */ + TxIndex::default(), + &mut BlockGasMeter::default(), + &mut shell.wl_storage.write_log, + &shell.wl_storage.storage, + &mut shell.vp_wasm_cache, + &mut shell.tx_wasm_cache, + ); + shell + .wl_storage + .storage + .delete(&pending_execution_key) + .expect("Should be able to delete the storage."); + match tx_result { + Ok(tx_result) if tx_result.is_accepted() => { + shell.wl_storage.commit_tx(); + ( + tx_result.is_accepted(), + ProposalEvent::new( + EventType::Proposal.to_string(), + TallyResult::Passed(Tally::Default), + id, + true, + tx_result.is_accepted(), + ) + .into(), + ) + } + _ => { + shell.wl_storage.drop_tx(); + ( + false, + ProposalEvent::new( + EventType::Proposal.to_string(), + TallyResult::Passed(Tally::Default), + id, + true, + false, + ) + .into(), + ) + } + } + } + None => ( + true, + ProposalEvent::new( + EventType::Proposal.to_string(), + TallyResult::Passed(Tally::Default), + id, + false, + false, + ) + .into(), + ), + } +} + +fn execute_pgf_proposal(id: u64, council: Council) -> (bool, Event) { + // TODO: implement when PGF is in place, update the PGF + // council in storage + ( + true, + ProposalEvent::new( + EventType::Proposal.to_string(), + TallyResult::Passed(Tally::PGFCouncil(council)), + id, + false, + false, + ) + .into(), + ) +} + +fn execute_eth_proposal(id: u64) -> (bool, Event) { + // TODO: implement when ETH Bridge. Apply the + // modification requested by the proposal + // + ( + true, + ProposalEvent::new( + EventType::Proposal.to_string(), + TallyResult::Passed(Tally::ETHBridge), + id, + false, + false, + ) + .into(), + ) +} diff --git a/shared/src/ledger/native_vp/governance/mod.rs b/shared/src/ledger/native_vp/governance/mod.rs index 022103d499d..2e0de7a18ff 100644 --- a/shared/src/ledger/native_vp/governance/mod.rs +++ b/shared/src/ledger/native_vp/governance/mod.rs @@ -238,6 +238,7 @@ where } else if let VoteType::ETHBridge(_sig) = vote_type { // TODO: Check the validity of the signature with the // governance ETH key in storage for the given validator + // } }