Skip to content

Commit

Permalink
Merge pull request #251 from anoma/fix-transparent-tx-kind
Browse files Browse the repository at this point in the history
improve transfer classification
  • Loading branch information
Fraccaman authored Jan 21, 2025
2 parents 9dbd562 + 711be21 commit 01fd6b1
Show file tree
Hide file tree
Showing 13 changed files with 554 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
SELECT 1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Your SQL goes here
ALTER TYPE TRANSACTION_KIND ADD VALUE 'mixed_transfer';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
SELECT 1;
4 changes: 4 additions & 0 deletions orm/migrations/2025-01-16-131336_transaction_ibc_types/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- Your SQL goes here
ALTER TYPE TRANSACTION_KIND ADD VALUE 'ibc_transparent_transfer';
ALTER TYPE TRANSACTION_KIND ADD VALUE 'ibc_shielding_transfer';
ALTER TYPE TRANSACTION_KIND ADD VALUE 'ibc_unshielding_transfer';
18 changes: 18 additions & 0 deletions orm/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ pub enum TransactionKindDb {
ShieldedTransfer,
ShieldingTransfer,
UnshieldingTransfer,
MixedTransfer,
IbcMsgTransfer,
IbcTransparentTransfer,
IbcShieldingTransfer,
IbcUnshieldingTransfer,
Bond,
Redelegation,
Unbond,
Expand All @@ -41,7 +45,21 @@ impl From<TransactionKind> for TransactionKindDb {
Self::TransparentTransfer
}
TransactionKind::ShieldedTransfer(_) => Self::ShieldedTransfer,
TransactionKind::UnshieldingTransfer(_) => {
Self::UnshieldingTransfer
}
TransactionKind::ShieldingTransfer(_) => Self::ShieldingTransfer,
TransactionKind::MixedTransfer(_) => Self::MixedTransfer,
TransactionKind::IbcMsgTransfer(_) => Self::IbcMsgTransfer,
TransactionKind::IbcTrasparentTransfer(_) => {
Self::IbcTransparentTransfer
}
TransactionKind::IbcShieldingTransfer(_) => {
Self::IbcShieldingTransfer
}
TransactionKind::IbcUnshieldingTransfer(_) => {
Self::IbcUnshieldingTransfer
}
TransactionKind::Bond(_) => Self::Bond,
TransactionKind::Redelegation(_) => Self::Redelegation,
TransactionKind::Unbond(_) => Self::Unbond,
Expand Down
320 changes: 314 additions & 6 deletions shared/src/block.rs

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions shared/src/block_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ impl TxAttributesType {
.unwrap_or_default()
.to_owned();

tracing::error!("{}", timeout_timestamp);

Some(Self::SendPacket(SendPacket {
source_port,
dest_port,
Expand Down
18 changes: 18 additions & 0 deletions shared/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ pub struct GasEstimation {
pub transparent_transfer: u64,
pub shielded_transfer: u64,
pub shielding_transfer: u64,
pub ibc_unshielding_transfer: u64,
pub ibc_shielding_transfer: u64,
pub unshielding_transfer: u64,
pub ibc_msg_transfer: u64,
pub mixed_transfer: u64,
pub bond: u64,
pub redelegation: u64,
pub unbond: u64,
Expand All @@ -34,7 +37,10 @@ impl GasEstimation {
shielded_transfer: 0,
shielding_transfer: 0,
unshielding_transfer: 0,
ibc_shielding_transfer: 0,
ibc_unshielding_transfer: 0,
ibc_msg_transfer: 0,
mixed_transfer: 0,
bond: 0,
redelegation: 0,
unbond: 0,
Expand Down Expand Up @@ -63,6 +69,18 @@ impl GasEstimation {
self.unshielding_transfer += 1
}

pub fn increase_mixed_transfer(&mut self) {
self.mixed_transfer += 1
}

pub fn increase_ibc_shielding_transfer(&mut self) {
self.ibc_shielding_transfer += 1
}

pub fn increase_ibc_unshielding_transfer(&mut self) {
self.ibc_unshielding_transfer += 1
}

pub fn increase_ibc_msg_transfer(&mut self) {
self.ibc_msg_transfer += 1
}
Expand Down
6 changes: 3 additions & 3 deletions shared/src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'de> Deserialize<'de> for AccountsMap {
}

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct TransparentTransfer {
pub struct TransferData {
/// Sources of this transfer
pub sources: AccountsMap,
/// Targets of this transfer
Expand All @@ -77,13 +77,13 @@ pub struct TransparentTransfer {
pub shielded_section_hash: Option<MaspTxId>,
}

impl From<NamadaTransfer> for TransparentTransfer {
impl From<NamadaTransfer> for TransferData {
fn from(transfer: NamadaTransfer) -> Self {
let sources = AccountsMap(transfer.sources);
let targets = AccountsMap(transfer.targets);
let shielded_section_hash = transfer.shielded_section_hash;

TransparentTransfer {
TransferData {
sources,
targets,
shielded_section_hash,
Expand Down
81 changes: 63 additions & 18 deletions shared/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use namada_governance::{InitProposalData, VoteProposalData};
use namada_sdk::address::Address;
use namada_sdk::borsh::BorshDeserialize;
use namada_sdk::key::common::PublicKey;
use namada_sdk::masp::ShieldedTransfer;
use namada_sdk::token::Transfer;
use namada_sdk::uint::Uint;
use namada_tx::data::pos::{
Expand All @@ -21,7 +20,8 @@ use crate::block::BlockHeight;
use crate::block_result::{BlockResult, TxEventStatusCode};
use crate::checksums::Checksums;
use crate::id::Id;
use crate::ser::{IbcMessage, TransparentTransfer};
use crate::ser::{IbcMessage, TransferData};
use crate::utils::{self, transfer_to_ibc_tx_kind};

// We wrap public key in a struct so we serialize data as object instead of
// string
Expand All @@ -33,11 +33,15 @@ pub struct RevealPkData {
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum TransactionKind {
TransparentTransfer(Option<TransparentTransfer>),
// TODO: remove once ShieldedTransfer can be serialized
#[serde(skip)]
ShieldedTransfer(Option<ShieldedTransfer>),
TransparentTransfer(Option<TransferData>),
ShieldedTransfer(Option<TransferData>),
ShieldingTransfer(Option<TransferData>),
UnshieldingTransfer(Option<TransferData>),
MixedTransfer(Option<TransferData>),
IbcMsgTransfer(Option<IbcMessage<Transfer>>),
IbcTrasparentTransfer((Option<IbcMessage<Transfer>>, TransferData)),
IbcShieldingTransfer((Option<IbcMessage<Transfer>>, TransferData)),
IbcUnshieldingTransfer((Option<IbcMessage<Transfer>>, TransferData)),
Bond(Option<Bond>),
Redelegation(Option<Redelegation>),
Unbond(Option<Unbond>),
Expand All @@ -60,15 +64,18 @@ impl TransactionKind {
serde_json::to_string(&self).ok()
}

pub fn from(tx_kind_name: &str, data: &[u8]) -> Self {
pub fn from(
tx_kind_name: &str,
data: &[u8],
masp_address: &Address,
) -> Self {
match tx_kind_name {
"tx_transfer" => {
let data = if let Ok(data) = Transfer::try_from_slice(data) {
Some(TransparentTransfer::from(data))
if let Ok(transfer) = Transfer::try_from_slice(data) {
utils::transfer_to_tx_kind(transfer, masp_address)
} else {
None
};
TransactionKind::TransparentTransfer(data)
TransactionKind::Unknown
}
}
"tx_bond" => {
let data = if let Ok(data) = Bond::try_from_slice(data) {
Expand Down Expand Up @@ -173,15 +180,38 @@ impl TransactionKind {
TransactionKind::ReactivateValidator(data)
}
"tx_ibc" => {
let data = if let Ok(data) =
if let Ok(ibc_data) =
namada_ibc::decode_message::<Transfer>(data)
{
Some(data)
match ibc_data.clone() {
namada_ibc::IbcMessage::Envelope(_msg_envelope) => {
TransactionKind::IbcMsgTransfer(Some(IbcMessage(
ibc_data,
)))
}
namada_ibc::IbcMessage::Transfer(transfer) => {
if let Some(data) = transfer.transfer {
utils::transfer_to_tx_kind(data, masp_address)
} else {
TransactionKind::IbcMsgTransfer(None)
}
}
namada_ibc::IbcMessage::NftTransfer(transfer) => {
if let Some(data) = transfer.transfer {
transfer_to_ibc_tx_kind(
data,
masp_address,
ibc_data,
)
} else {
TransactionKind::IbcMsgTransfer(None)
}
}
}
} else {
tracing::warn!("Cannot deserialize IBC transfer");
None
};
TransactionKind::IbcMsgTransfer(data.map(IbcMessage))
TransactionKind::IbcMsgTransfer(None)
}
}
"tx_unjail_validator" => {
let data = if let Ok(data) = Address::try_from_slice(data) {
Expand Down Expand Up @@ -281,6 +311,16 @@ impl InnerTransaction {
pub fn was_successful(&self) -> bool {
self.exit_code == TransactionExitStatus::Applied
}

pub fn is_ibc(&self) -> bool {
matches!(
self.kind,
TransactionKind::IbcMsgTransfer(_)
| TransactionKind::IbcTrasparentTransfer(_)
| TransactionKind::IbcUnshieldingTransfer(_)
| TransactionKind::IbcShieldingTransfer(_)
)
}
}

#[derive(Debug, Clone)]
Expand All @@ -299,6 +339,7 @@ impl Transaction {
block_height: BlockHeight,
checksums: Checksums,
block_results: &BlockResult,
masp_address: &Address,
) -> Result<(WrapperTransaction, Vec<InnerTransaction>), String> {
let transaction =
Tx::try_from(raw_tx_bytes).map_err(|e| e.to_string())?;
Expand Down Expand Up @@ -379,7 +420,11 @@ impl Transaction {
if let Some(tx_kind_name) =
checksums.get_name_by_id(&id)
{
TransactionKind::from(&tx_kind_name, &tx_data)
TransactionKind::from(
&tx_kind_name,
&tx_data,
masp_address,
)
} else {
TransactionKind::Unknown
}
Expand Down
96 changes: 96 additions & 0 deletions shared/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use namada_ibc::IbcMessage;
use namada_sdk::address::Address;
use namada_sdk::token::Transfer;

use crate::id::Id;
use crate::ser;
use crate::token::Token;
use crate::transaction::TransactionKind;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BalanceChange {
Expand All @@ -25,3 +31,93 @@ pub struct DelegationPair {
pub validator_address: Id,
pub delegator_address: Id,
}

pub fn transfer_to_tx_kind(
data: Transfer,
masp_address: &Address,
) -> TransactionKind {
let has_shielded_section = data.shielded_section_hash.is_some();

let (all_sources_are_masp, any_sources_are_masp) = data
.sources
.iter()
.fold((true, false), |(all, any), (acc, _)| {
let is_masp = acc.owner.eq(masp_address);
(all && is_masp, any || is_masp)
});

let (all_targets_are_masp, any_targets_are_masp) = data
.targets
.iter()
.fold((true, false), |(all, any), (acc, _)| {
let is_masp = acc.owner.eq(masp_address);
(all && is_masp, any || is_masp)
});

match (
all_sources_are_masp,
any_sources_are_masp,
all_targets_are_masp,
any_targets_are_masp,
has_shielded_section,
) {
(true, _, true, _, true) => {
TransactionKind::ShieldedTransfer(Some(data.into()))
}
(true, _, _, false, true) => {
TransactionKind::UnshieldingTransfer(Some(data.into()))
}
(false, _, true, _, true) => {
TransactionKind::ShieldingTransfer(Some(data.into()))
}
(false, _, false, _, false) => {
TransactionKind::TransparentTransfer(Some(data.into()))
}
_ => TransactionKind::MixedTransfer(Some(data.into())),
}
}

pub fn transfer_to_ibc_tx_kind(
data: Transfer,
masp_address: &Address,
ibc_data: IbcMessage<Transfer>,
) -> TransactionKind {
let has_shielded_section = data.shielded_section_hash.is_some();

let (all_sources_are_masp, any_sources_are_masp) = data
.sources
.iter()
.fold((true, false), |(all, any), (acc, _)| {
let is_masp = acc.owner.eq(masp_address);
(all && is_masp, any || is_masp)
});

let (all_targets_are_masp, any_targets_are_masp) = data
.targets
.iter()
.fold((true, false), |(all, any), (acc, _)| {
let is_masp = acc.owner.eq(masp_address);
(all && is_masp, any || is_masp)
});

match (
all_sources_are_masp,
any_sources_are_masp,
all_targets_are_masp,
any_targets_are_masp,
has_shielded_section,
) {
(true, _, _, false, true) => TransactionKind::IbcUnshieldingTransfer((
Some(ser::IbcMessage(ibc_data)),
data.into(),
)),
(false, _, true, _, true) => TransactionKind::IbcShieldingTransfer((
Some(ser::IbcMessage(ibc_data)),
data.into(),
)),
(false, _, false, _, false) => TransactionKind::IbcTrasparentTransfer(
(Some(ser::IbcMessage(ibc_data)), data.into()),
),
_ => TransactionKind::MixedTransfer(Some(data.into())),
}
}
Loading

0 comments on commit 01fd6b1

Please sign in to comment.