Skip to content

Commit

Permalink
Merge branch 'tiago/balance-change-events' (#3141)
Browse files Browse the repository at this point in the history
* origin/tiago/balance-change-events:
  Changelog for #3141
  Fix Multitoken native VP err msg
  Log which token failed to be minted on IBC native VP
  Fix unit tests
  Emit token transfer event from wasm
  Emit PoS slashing events
  Add void event sink for testing
  Proof of stake events
  Move `token` events to `trans_token`
  Refactor token events
  Remove minted supply target
  Governance refund balance change events
  Burn IBC tokens and emit events
  Mint IBC tokens and emit events
  Remove unused file
  Implement EmitEvents on state impls
  Add token minting function
  Emit PGF payment events
  Add event level to balance change events
  Make the token event's post balance optional
  Extend event with a closure
  Refactor governace event emission
  Add more balance change targets
  Include wrapper tx hash in balance change event
  Include current height in wrapper fee payment event
  Emit fee payment balance change events
  Add token balance change events
  Negate I256 numbers
  Convert from Uint to Amount with 0 denom
  Implement FromStr on I256
  • Loading branch information
brentstone committed May 8, 2024
2 parents 94191ca + 50dc3c7 commit c360811
Show file tree
Hide file tree
Showing 37 changed files with 1,196 additions and 159 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Emit balance change events for various protocol actions.
([\#3141](https://github.com/anoma/namada/pull/3141))
3 changes: 3 additions & 0 deletions Cargo.lock

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

133 changes: 111 additions & 22 deletions crates/apps/src/lib/node/ledger/shell/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ use namada::proof_of_stake::storage::{
read_total_active_stake, validator_state_handle,
};
use namada::proof_of_stake::types::{BondId, ValidatorState};
use namada::sdk::events::EmitEvents;
use namada::sdk::events::{EmitEvents, EventLevel};
use namada::state::StorageWrite;
use namada::token::event::{TokenEvent, TokenOperation, UserAccount};
use namada::token::read_balance;
use namada::tx::{Code, Data};
use namada_sdk::proof_of_stake::storage::read_validator_stake;

Expand Down Expand Up @@ -171,6 +173,7 @@ where
let native_token = &shell.state.get_native_token()?;
let _result = execute_pgf_funding_proposal(
&mut shell.state,
events,
native_token,
payments,
id,
Expand All @@ -189,11 +192,17 @@ where

// Take events that could have been emitted by PGF
// over IBC, governance proposal execution, etc
for event in shell.state.write_log_mut().take_events() {
events.emit(event.with(Height(
shell.state.in_mem().get_last_block_height() + 1,
)));
}
let current_height =
shell.state.in_mem().get_last_block_height() + 1;

events.emit_many(
shell
.state
.write_log_mut()
.take_events()
.into_iter()
.map(|event| event.with(Height(current_height))),
);

gov_api::get_proposal_author(&shell.state, id)?
}
Expand Down Expand Up @@ -240,13 +249,49 @@ where
&address,
funds,
)?;

const DESCRIPTOR: &str = "governance-locked-funds-refund";

let final_gov_balance =
read_balance(&shell.state, &native_token, &gov_address)?.into();
let final_target_balance =
read_balance(&shell.state, &native_token, &address)?.into();

events.emit(TokenEvent {
descriptor: DESCRIPTOR.into(),
level: EventLevel::Block,
token: native_token.clone(),
operation: TokenOperation::Transfer {
amount: funds.into(),
source: UserAccount::Internal(gov_address),
target: UserAccount::Internal(address),
source_post_balance: final_gov_balance,
target_post_balance: Some(final_target_balance),
},
});
} else {
token::burn_tokens(
&mut shell.state,
&native_token,
&gov_address,
funds,
)?;

const DESCRIPTOR: &str = "governance-locked-funds-burn";

let final_gov_balance =
read_balance(&shell.state, &native_token, &gov_address)?.into();

events.emit(TokenEvent {
descriptor: DESCRIPTOR.into(),
level: EventLevel::Block,
token: native_token.clone(),
operation: TokenOperation::Burn {
amount: funds.into(),
target_account: UserAccount::Internal(gov_address),
post_balance: final_gov_balance,
},
});
}
}

Expand Down Expand Up @@ -414,6 +459,7 @@ where

fn execute_pgf_funding_proposal<D, H>(
state: &mut WlState<D, H>,
events: &mut impl EmitEvents,
token: &Address,
fundings: BTreeSet<PGFAction>,
proposal_id: u64,
Expand Down Expand Up @@ -452,25 +498,68 @@ where
}
},
PGFAction::Retro(target) => {
let result = match &target {
PGFTarget::Internal(target) => token::transfer(
state,
token,
&ADDRESS,
&target.target,
target.amount,
let (result, event) = match &target {
PGFTarget::Internal(target) => (
token::transfer(
state,
token,
&ADDRESS,
&target.target,
target.amount,
),
TokenEvent {
descriptor: "pgf-payments".into(),
level: EventLevel::Block,
token: token.clone(),
operation: TokenOperation::Transfer {
amount: target.amount.into(),
source: UserAccount::Internal(ADDRESS),
target: UserAccount::Internal(
target.target.clone(),
),
source_post_balance: read_balance(
state, token, &ADDRESS,
)?
.into(),
target_post_balance: Some(
read_balance(state, token, &target.target)?
.into(),
),
},
},
),
PGFTarget::Ibc(target) => (
ibc::transfer_over_ibc(state, token, &ADDRESS, target),
TokenEvent {
descriptor: "pgf-payments-over-ibc".into(),
level: EventLevel::Block,
token: token.clone(),
operation: TokenOperation::Transfer {
amount: target.amount.into(),
source: UserAccount::Internal(ADDRESS),
target: UserAccount::External(
target.target.clone(),
),
source_post_balance: read_balance(
state, token, &ADDRESS,
)?
.into(),
target_post_balance: None,
},
},
),
PGFTarget::Ibc(target) => {
ibc::transfer_over_ibc(state, token, &ADDRESS, target)
}
};
match result {
Ok(()) => tracing::info!(
"Execute RetroPgf from proposal id {}: sent {} to {}.",
proposal_id,
target.amount().to_string_native(),
target.target()
),
Ok(()) => {
tracing::info!(
"Execute RetroPgf from proposal id {}: sent {} to \
{}.",
proposal_id,
target.amount().to_string_native(),
target.target()
);
events.emit(event);
}
Err(e) => tracing::warn!(
"Error in RetroPgf transfer from proposal id {}, \
amount {} to {}: {}",
Expand Down
2 changes: 1 addition & 1 deletion crates/apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ mod test {
token::Amount::from_uint(1, 6).unwrap(),
6.into(),
),
"Insufficient source balance".to_string(),
format!("{albert_address_str} has insufficient balance"),
)];
assert_eq!(expected, initializer.warnings);
initializer.warnings.clear();
Expand Down
13 changes: 11 additions & 2 deletions crates/apps/src/lib/node/ledger/shell/prepare_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use masp_primitives::transaction::Transaction;
use namada::core::address::Address;
use namada::core::key::tm_raw_hash_to_string;
use namada::gas::TxGasMeter;
use namada::hash::Hash;
use namada::ledger::protocol::{self, ShellParams};
use namada::proof_of_stake::storage::find_validator_by_raw_hash;
use namada::state::{DBIter, StorageHasher, TempWlState, DB};
Expand Down Expand Up @@ -295,6 +296,7 @@ where
// Check fees and extract the gas limit of this transaction
match prepare_proposal_fee_check(
&wrapper,
tx.header_hash(),
protocol::get_fee_unshielding_transaction(&tx, &wrapper),
block_proposer,
proposer_local_config,
Expand All @@ -313,8 +315,10 @@ where
}
}

#[allow(clippy::too_many_arguments)]
fn prepare_proposal_fee_check<D, H, CA>(
wrapper: &WrapperTx,
wrapper_tx_hash: Hash,
masp_transaction: Option<Transaction>,
proposer: &Address,
proposer_local_config: Option<&ValidatorLocalConfig>,
Expand Down Expand Up @@ -357,8 +361,13 @@ where
shell_params,
)?;

protocol::transfer_fee(shell_params.state, proposer, wrapper)
.map_err(Error::TxApply)
protocol::transfer_fee(
shell_params.state,
proposer,
wrapper,
wrapper_tx_hash,
)
.map_err(Error::TxApply)
}

#[cfg(test)]
Expand Down
12 changes: 10 additions & 2 deletions crates/apps/src/lib/node/ledger/shell/process_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! and [`RevertProposal`] ABCI++ methods for the Shell
use data_encoding::HEXUPPER;
use namada::hash::Hash;
use namada::ledger::pos::PosQueries;
use namada::proof_of_stake::storage::find_validator_by_raw_hash;
use namada::tx::data::protocol::ProtocolTxType;
Expand Down Expand Up @@ -465,6 +466,7 @@ where
// Check that the fee payer has sufficient balance.
match process_proposal_fee_check(
&wrapper,
tx.header_hash(),
get_fee_unshielding_transaction(&tx, &wrapper),
block_proposer,
&mut ShellParams::new(
Expand Down Expand Up @@ -498,6 +500,7 @@ where

fn process_proposal_fee_check<D, H, CA>(
wrapper: &WrapperTx,
wrapper_tx_hash: Hash,
masp_transaction: Option<Transaction>,
proposer: &Address,
shell_params: &mut ShellParams<'_, TempWlState<D, H>, D, H, CA>,
Expand All @@ -524,8 +527,13 @@ where
shell_params,
)?;

protocol::transfer_fee(shell_params.state, proposer, wrapper)
.map_err(Error::TxApply)
protocol::transfer_fee(
shell_params.state,
proposer,
wrapper,
wrapper_tx_hash,
)
.map_err(Error::TxApply)
}

/// We test the failure cases of [`process_proposal`]. The happy flows
Expand Down
8 changes: 7 additions & 1 deletion crates/core/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ impl Amount {
let denom = denom.into();
let uint = uint.into();
if denom == 0 {
return Ok(Self { raw: uint });
return Ok(uint.into());
}
match Uint::from(10)
.checked_pow(Uint::from(denom))
Expand Down Expand Up @@ -907,6 +907,12 @@ impl From<Amount> for Uint {
}
}

impl From<Uint> for Amount {
fn from(raw: Uint) -> Self {
Self { raw }
}
}

/// The four possible u64 words in a [`Uint`].
/// Used for converting to MASP amounts.
#[derive(
Expand Down
30 changes: 30 additions & 0 deletions crates/core/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use std::cmp::Ordering;
use std::fmt;
use std::ops::{Add, AddAssign, BitAnd, Div, Mul, Neg, Rem, Sub, SubAssign};
use std::str::FromStr;

use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use impl_num_traits::impl_uint_num_traits;
Expand Down Expand Up @@ -507,7 +508,26 @@ impl fmt::Display for I256 {
}
}

impl FromStr for I256 {
type Err = Box<dyn 'static + std::error::Error>;

fn from_str(num: &str) -> Result<Self, Self::Err> {
if let Some(("", neg_num)) = num.split_once('-') {
let uint = neg_num.parse::<Uint>()?.negate();
Ok(I256(uint))
} else {
let uint = num.parse::<Uint>()?;
Ok(I256(uint))
}
}
}

impl I256 {
/// Compute the two's complement of a number.
pub fn negate(&self) -> Self {
Self(self.0.negate())
}

/// Check if the amount is not negative (greater
/// than or equal to zero)
pub fn non_negative(&self) -> bool {
Expand Down Expand Up @@ -1064,4 +1084,14 @@ mod test_uint {
assert_eq!(e.checked_mul_div(c, b), Some((Uint::zero(), c)));
assert_eq!(d.checked_mul_div(a, e), None);
}

#[test]
fn test_i256_str_roundtrip() {
let minus_one = I256::one().negate();
let minus_one_str = minus_one.to_string();
assert_eq!(minus_one_str, "-1");

let parsed: I256 = minus_one_str.parse().unwrap();
assert_eq!(minus_one, parsed);
}
}
1 change: 1 addition & 0 deletions crates/events/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ migrations = [
"namada_migrations",
"linkme",
]
testing = []

[dependencies]
namada_core = {path = "../core"}
Expand Down
Loading

0 comments on commit c360811

Please sign in to comment.