Skip to content

Commit

Permalink
Generalized the Transfer event to support reporting multiple account …
Browse files Browse the repository at this point in the history
…changes.
  • Loading branch information
murisi committed Jul 2, 2024
1 parent 317b3ad commit 98c88ec
Show file tree
Hide file tree
Showing 7 changed files with 294 additions and 168 deletions.
86 changes: 86 additions & 0 deletions crates/events/src/extend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use std::marker::PhantomData;
use std::ops::ControlFlow;
use std::str::FromStr;

use namada_core::address::Address;
use namada_core::collections::HashMap;
use namada_core::hash::Hash;
use namada_core::masp::MaspTxRefs;
use namada_core::storage::{BlockHeight, TxIndex};
use serde::Deserializer;

use super::*;

Expand Down Expand Up @@ -666,6 +668,90 @@ where
}
}

/// Implement the Display and FromStr traits for any serde type
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct EventValue<T>(pub T);

impl<T: Serialize> Display for EventValue<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let ser =
serde_json::to_string(&self.0).map_err(|_| std::fmt::Error)?;
write!(f, "{}", ser)
}
}

impl<T: for<'de> Deserialize<'de>> FromStr for EventValue<T> {
type Err = serde_json::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s).map(Self)
}
}

impl<T> From<T> for EventValue<T> {
fn from(t: T) -> Self {
Self(t)
}
}

/// A user account.
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum UserAccount {
/// Internal chain address in Namada.
Internal(Address),
/// External chain address.
External(String),
}

impl fmt::Display for UserAccount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Internal(addr) => write!(f, "internal-address/{addr}"),
Self::External(addr) => write!(f, "external-address/{addr}"),
}
}
}

impl FromStr for UserAccount {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split_once('/') {
Some(("internal-address", addr)) => {
Ok(Self::Internal(Address::decode(addr).map_err(|err| {
format!(
"Unknown internal address balance change target \
{s:?}: {err}"
)
})?))
}
Some(("external-address", addr)) => {
Ok(Self::External(addr.to_owned()))
}
_ => Err(format!("Unknown balance change target {s:?}")),
}
}
}

impl serde::Serialize for UserAccount {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for UserAccount {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = <String as Deserialize>::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(serde::de::Error::custom)
}
}

#[cfg(test)]
mod event_composition_tests {
use super::*;
Expand Down
7 changes: 4 additions & 3 deletions crates/ibc/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ use namada_core::address::{Address, InternalAddress, HASH_LEN, SHA_HASH_LEN};
use namada_core::ibc::IbcTokenHash;
use namada_core::storage::{DbKeySeg, Key, KeySeg};
use namada_core::token::Amount;
use namada_events::extend::UserAccount;
use namada_events::{EmitEvents, EventLevel};
use namada_state::{StorageRead, StorageResult, StorageWrite};
use namada_token as token;
use namada_token::event::{TokenEvent, TokenOperation, UserAccount};
use namada_token::event::{TokenEvent, TokenOperation};
use sha2::{Digest, Sha256};
use thiserror::Error;

Expand Down Expand Up @@ -75,8 +76,8 @@ where
state.emit(TokenEvent {
descriptor: TOKEN_EVENT_DESCRIPTOR.into(),
level: EventLevel::Tx,
token: token.clone(),
operation: TokenOperation::Mint {
token: token.clone(),
amount: amount.into(),
post_balance: token::read_balance(state, token, target)?.into(),
target_account: UserAccount::Internal(target.clone()),
Expand All @@ -101,8 +102,8 @@ where
state.emit(TokenEvent {
descriptor: TOKEN_EVENT_DESCRIPTOR.into(),
level: EventLevel::Tx,
token: token.clone(),
operation: TokenOperation::Burn {
token: token.clone(),
amount: amount.into(),
post_balance: token::read_balance(state, token, target)?.into(),
target_account: UserAccount::Internal(target.clone()),
Expand Down
36 changes: 16 additions & 20 deletions crates/namada/src/ledger/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use eyre::{eyre, WrapErr};
use namada_core::booleans::BoolResultUnitExt;
use namada_core::hash::Hash;
use namada_events::extend::{
ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr,
ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, UserAccount,
};
use namada_events::EventLevel;
use namada_gas::TxGasMeter;
use namada_state::StorageWrite;
use namada_token::event::{TokenEvent, TokenOperation, UserAccount};
use namada_token::event::{TokenEvent, TokenOperation};
use namada_tx::data::protocol::{ProtocolTx, ProtocolTxType};
use namada_tx::data::{
BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, VpStatusFlags,
Expand Down Expand Up @@ -522,16 +522,14 @@ where
TokenEvent {
descriptor: FEE_PAYMENT_DESCRIPTOR,
level: EventLevel::Tx,
token: wrapper.fee.token.clone(),
operation: TokenOperation::Transfer {
amount: fees.into(),
source: UserAccount::Internal(wrapper.fee_payer()),
target: UserAccount::Internal(
block_proposer.clone(),
),
source_post_balance: post_bal.into(),
operation: TokenOperation::transfer(
UserAccount::Internal(wrapper.fee_payer()),
UserAccount::Internal(block_proposer.clone()),
wrapper.fee.token.clone(),
fees.into(),
post_bal.into(),
target_post_balance,
},
),
}
.with(HeightAttr(current_block_height))
.with(TxHashAttr(wrapper_tx_hash)),
Expand Down Expand Up @@ -570,16 +568,14 @@ where
TokenEvent {
descriptor: FEE_PAYMENT_DESCRIPTOR,
level: EventLevel::Tx,
token: wrapper.fee.token.clone(),
operation: TokenOperation::Transfer {
amount: balance.into(),
source: UserAccount::Internal(wrapper.fee_payer()),
target: UserAccount::Internal(
block_proposer.clone(),
),
source_post_balance: namada_core::uint::ZERO,
operation: TokenOperation::transfer(
UserAccount::Internal(wrapper.fee_payer()),
UserAccount::Internal(block_proposer.clone()),
wrapper.fee.token.clone(),
balance.into(),
namada_core::uint::ZERO,
target_post_balance,
},
),
}
.with(HeightAttr(current_block_height))
.with(TxHashAttr(wrapper_tx_hash)),
Expand Down
64 changes: 27 additions & 37 deletions crates/node/src/shell/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use namada::governance::{
storage as gov_api, ProposalVote, ADDRESS as gov_address,
};
use namada::ibc;
use namada::ledger::events::extend::{ComposeEvent, Height};
use namada::ledger::events::extend::{ComposeEvent, Height, UserAccount};
use namada::proof_of_stake::bond_amount;
use namada::proof_of_stake::parameters::PosParams;
use namada::proof_of_stake::storage::{
Expand All @@ -25,7 +25,7 @@ use namada::proof_of_stake::storage::{
use namada::proof_of_stake::types::{BondId, ValidatorState};
use namada::sdk::events::{EmitEvents, EventLevel};
use namada::state::StorageWrite;
use namada::token::event::{TokenEvent, TokenOperation, UserAccount};
use namada::token::event::{TokenEvent, TokenOperation};
use namada::token::read_balance;
use namada::tx::{Code, Data};
use namada_sdk::proof_of_stake::storage::read_validator_stake;
Expand Down Expand Up @@ -261,14 +261,14 @@ where
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),
},
operation: TokenOperation::transfer(
UserAccount::Internal(gov_address),
UserAccount::Internal(address),
native_token.clone(),
funds.into(),
final_gov_balance,
Some(final_target_balance),
),
});
} else {
token::burn_tokens(
Expand All @@ -286,8 +286,8 @@ where
events.emit(TokenEvent {
descriptor: DESCRIPTOR.into(),
level: EventLevel::Block,
token: native_token.clone(),
operation: TokenOperation::Burn {
token: native_token.clone(),
amount: funds.into(),
target_account: UserAccount::Internal(gov_address),
post_balance: final_gov_balance,
Expand Down Expand Up @@ -532,42 +532,32 @@ where
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(
operation: TokenOperation::transfer(
UserAccount::Internal(ADDRESS),
UserAccount::Internal(target.target.clone()),
token.clone(),
target.amount.into(),
read_balance(state, token, &ADDRESS)?.into(),
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,
},
operation: TokenOperation::transfer(
UserAccount::Internal(ADDRESS),
UserAccount::External(target.target.clone()),
token.clone(),
target.amount.into(),
read_balance(state, token, &ADDRESS)?.into(),
None,
),
},
),
};
Expand Down
Loading

0 comments on commit 98c88ec

Please sign in to comment.