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

improve gas estimation #267

Closed
wants to merge 1 commit into from
Closed
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
3 changes: 3 additions & 0 deletions orm/migrations/2025-01-27-130323_gas_estimation_ibc/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
ALTER TABLE gas_estimations DROP COLUMN ibc_unshielding_transfer;
ALTER TABLE gas_estimations DROP COLUMN ibc_shielding_transfer;
3 changes: 3 additions & 0 deletions orm/migrations/2025-01-27-130323_gas_estimation_ibc/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- Your SQL goes here
ALTER TABLE gas_estimations ADD COLUMN ibc_unshielding_transfer INT NOT NULL;
ALTER TABLE gas_estimations ADD COLUMN ibc_shielding_transfer INT NOT NULL;
4 changes: 4 additions & 0 deletions orm/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct GasEstimationDb {
pub shielded_transfer: i32,
pub shielding_transfer: i32,
pub unshielding_transfer: i32,
pub ibc_unshielding_transfer: i32,
pub ibc_shielding_transfer: i32,
pub ibc_msg_transfer: i32,
pub bond: i32,
pub redelegation: i32,
Expand All @@ -65,6 +67,8 @@ impl From<GasEstimation> for GasEstimationInsertDb {
shielding_transfer: value.shielding_transfer as i32,
unshielding_transfer: value.unshielding_transfer as i32,
ibc_msg_transfer: value.ibc_msg_transfer as i32,
ibc_unshielding_transfer: value.ibc_unshielding_transfer as i32,
ibc_shielding_transfer: value.ibc_shielding_transfer as i32,
bond: value.bond as i32,
redelegation: value.redelegation as i32,
unbond: value.unbond as i32,
Expand Down
18 changes: 18 additions & 0 deletions orm/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ pub mod sql_types {
#[diesel(postgres_type(name = "ibc_status"))]
pub struct IbcStatus;

#[derive(
diesel::query_builder::QueryId,
std::fmt::Debug,
diesel::sql_types::SqlType,
)]
#[diesel(postgres_type(name = "payment_kind"))]
pub struct PaymentKind;

#[derive(
diesel::query_builder::QueryId,
std::fmt::Debug,
diesel::sql_types::SqlType,
)]
#[diesel(postgres_type(name = "payment_recurrence"))]
pub struct PaymentRecurrence;

#[derive(
diesel::query_builder::QueryId,
std::fmt::Debug,
Expand Down Expand Up @@ -186,6 +202,8 @@ diesel::table! {
reveal_pk -> Int4,
tx_size -> Int4,
signatures -> Int4,
ibc_unshielding_transfer -> Int4,
ibc_shielding_transfer -> Int4,
}
}

Expand Down
64 changes: 62 additions & 2 deletions shared/src/block_result.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::str::FromStr;

use namada_sdk::events::extend::{IndexedMaspData, MaspTxRef};
use namada_tx::data::TxResult;
use tendermint_rpc::endpoint::block_results::Response as TendermintBlockResultResponse;

Expand Down Expand Up @@ -108,14 +110,35 @@ impl BatchResults {
}
}

#[derive(Debug, Clone, Default)]
#[derive(Clone)]
pub struct TxApplied {
pub code: TxEventStatusCode,
pub gas: u64,
pub hash: Id,
pub height: u64,
pub batch: BatchResults,
pub info: String,
pub masp_refs: HashMap<u64, Vec<MaspTxRef>>,
}

impl fmt::Debug for TxApplied {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TxApplied")
.field("code", &self.code)
.field("gas", &self.gas)
.field("hash", &self.hash)
.field("height", &self.height)
.field("batch", &self.batch)
.field("info", &self.info)
.field("masp_refs_len", &self.masp_refs.len())
.finish()
}
}

#[derive(Debug, Clone)]
pub enum MaspRef {
Native(String),
Ibc(String),
}

#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -189,6 +212,24 @@ impl TxAttributesType {
.map(|height| u64::from_str(height).unwrap())
.unwrap()
.to_owned(),
masp_refs: attributes
.get("masp_data_refs")
.map(|data| {
if let Ok(data) =
serde_json::from_str::<IndexedMaspData>(data)
{
let refs = data
.masp_refs
.0
.iter()
.map(|masp_ref| masp_ref.clone())
.collect();
HashMap::from_iter([(data.tx_index.0 as u64, refs)])
} else {
HashMap::default()
}
})
.unwrap_or_default(),
batch: attributes
.get("batch")
.map(|batch_result| {
Expand Down Expand Up @@ -323,4 +364,23 @@ impl BlockResult {
});
exit_status.unwrap_or(TransactionExitStatus::Rejected)
}

pub fn masp_refs(&self, wrapper_hash: &Id, index: u64) -> Vec<MaspTxRef> {
self.end_events
.iter()
.filter_map(|event| {
if let Some(TxAttributesType::TxApplied(data)) =
&event.attributes
{
Some(data.clone())
} else {
None
}
})
.find(|attributes| attributes.hash.eq(wrapper_hash))
.map(|event| {
event.masp_refs.get(&index).cloned().unwrap_or_default()
})
.unwrap_or_default()
}
}
24 changes: 12 additions & 12 deletions shared/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,28 @@ impl GasEstimation {
self.transparent_transfer += 1
}

pub fn increase_shielded_transfer(&mut self) {
self.shielded_transfer += 1
pub fn increase_shielded_transfer(&mut self, notes: u64) {
self.shielded_transfer += notes
}

pub fn increase_shielding_transfer(&mut self) {
self.shielding_transfer += 1
pub fn increase_shielding_transfer(&mut self, notes: u64) {
self.shielding_transfer += notes
}

pub fn increase_unshielding_transfer(&mut self) {
self.unshielding_transfer += 1
pub fn increase_unshielding_transfer(&mut self, notes: u64) {
self.unshielding_transfer += notes
}

pub fn increase_mixed_transfer(&mut self) {
self.mixed_transfer += 1
pub fn increase_mixed_transfer(&mut self, notes: u64) {
self.mixed_transfer += notes
}

pub fn increase_ibc_shielding_transfer(&mut self) {
self.ibc_shielding_transfer += 1
pub fn increase_ibc_shielding_transfer(&mut self, notes: u64) {
self.ibc_shielding_transfer += notes
}

pub fn increase_ibc_unshielding_transfer(&mut self) {
self.ibc_unshielding_transfer += 1
pub fn increase_ibc_unshielding_transfer(&mut self, notes: u64) {
self.ibc_unshielding_transfer += notes
}

pub fn increase_ibc_msg_transfer(&mut self) {
Expand Down
32 changes: 29 additions & 3 deletions shared/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fmt::Display;
use namada_governance::{InitProposalData, VoteProposalData};
use namada_sdk::address::Address;
use namada_sdk::borsh::BorshDeserialize;
use namada_sdk::events::extend::MaspTxRef;
use namada_sdk::key::common::PublicKey;
use namada_sdk::token::Transfer;
use namada_sdk::uint::Uint;
Expand Down Expand Up @@ -274,9 +275,8 @@ pub struct Transaction {
}

#[derive(Debug, Clone)]
pub struct Transaction2 {
pub wrapper: WrapperTransaction,
pub inners: InnerTransaction,
pub struct MaspSectionData {
pub total_notes: u64,
}

#[derive(Debug, Clone)]
Expand All @@ -300,6 +300,7 @@ pub struct InnerTransaction {
pub memo: Option<String>,
pub data: Option<String>,
pub extra_sections: HashMap<Id, Vec<u8>>,
pub notes: u64,
pub exit_code: TransactionExitStatus,
}

Expand Down Expand Up @@ -359,6 +360,8 @@ impl Transaction {
let gas_used = block_results
.gas_used(&wrapper_tx_id)
.map(|gas| gas.parse::<u64>().unwrap());
let masp_refs =
block_results.masp_refs(&wrapper_tx_id, index as u64);

let fee = Fee {
gas: Uint::from(wrapper.gas_limit).to_string(),
Expand Down Expand Up @@ -459,13 +462,36 @@ impl Transaction {
acc
});

let notes = masp_refs.clone().into_iter().map(|masp_ref| {
match masp_ref {
MaspTxRef::MaspSection(masp_tx_id) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should check if this specific masp ref belongs to this inner tx

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes so, we'd need to check if the inner tx we are currently analyzing is a successful masp tx and if so pop from the head of the masp_refs vector the next element and run the match expression here above. It's a bit unlucky cause the events don't carry the exact inner tx index of that masp data (it's not needed when constructing the local state of a shielded wallet) so we kind of have to do this manually in here. We should have the batch event somewhere here so that we can check the exit code of this inner tx. Understanding if it is a masp tx could be slightly more complex: we'd need to deserialize the tx data and see if it is a transfer, ibc transfer or neither. If none, then this is not a masp tx. If it is either a transfer or an ibc transfer we should check if it contains the pointer to the same MaspTxRef that we expect: if so we extract, otherwise we skip

transaction
.get_masp_section(&masp_tx_id)
.map(|bundle| bundle.clone().into_data().sapling_bundle().map(|bundle| bundle.shielded_spends.len() + bundle.shielded_outputs.len()).unwrap_or_default()).unwrap_or_default() as u64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and down below it might be nice to also account for the length of the shielded_converts vector since conversions affect the gas cost too. But let me know, maybe this would make the indexer algorithm too overfitted on the details of masp txs

},
MaspTxRef::IbcData(hash) => {
transaction.get_data_section(&hash).map(|section| match namada_sdk::ibc::decode_message::<Transfer>(&section) {
Ok(namada_ibc::IbcMessage::Envelope(msg_envelope)) => {
if let Some(bundle) = namada_sdk::ibc::extract_masp_tx_from_envelope(&msg_envelope) {
bundle.clone().into_data().sapling_bundle().map(|bundle| bundle.shielded_spends.len() + bundle.shielded_outputs.len()).unwrap_or_default() as u64
} else {
0
}
},
_ => 0,
}).unwrap_or_default()
},
}
}).sum::<u64>();

let inner_tx = InnerTransaction {
tx_id: inner_tx_id,
index,
wrapper_id: wrapper_tx_id.clone(),
memo,
data: encoded_tx_data,
extra_sections,
notes,
exit_code: inner_tx_status,
kind: tx_kind,
};
Expand Down
25 changes: 18 additions & 7 deletions transactions/src/services/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,12 @@ pub fn get_gas_estimates(
&& inner_tx.wrapper_id.eq(&wrapper_tx.tx_id)
})
.for_each(|tx| match tx.kind {
TransactionKind::TransparentTransfer(_)
| TransactionKind::MixedTransfer(_) => {
gas_estimate.increase_mixed_transfer()
TransactionKind::TransparentTransfer(_) => {
gas_estimate.increase_transparent_transfer();
}
TransactionKind::MixedTransfer(_) => {
let notes = tx.notes;
gas_estimate.increase_mixed_transfer(notes)
}
TransactionKind::IbcMsgTransfer(_) => {
gas_estimate.increase_ibc_msg_transfer()
Expand All @@ -155,16 +158,24 @@ pub fn get_gas_estimates(
gas_estimate.increase_reveal_pk()
}
TransactionKind::ShieldedTransfer(_) => {
gas_estimate.increase_shielded_transfer()
let notes = tx.notes;
gas_estimate.increase_shielded_transfer(notes);
}
TransactionKind::ShieldingTransfer(_) => {
gas_estimate.increase_shielding_transfer()
let notes = tx.notes;
gas_estimate.increase_shielding_transfer(notes)
}
TransactionKind::UnshieldingTransfer(_) => {
gas_estimate.increase_ibc_unshielding_transfer()
let notes = tx.notes;
gas_estimate.increase_unshielding_transfer(notes)
}
TransactionKind::IbcShieldingTransfer(_) => {
gas_estimate.increase_ibc_shielding_transfer()
let notes = tx.notes;
gas_estimate.increase_ibc_shielding_transfer(notes)
}
TransactionKind::IbcUnshieldingTransfer(_) => {
let notes = tx.notes;
gas_estimate.increase_ibc_unshielding_transfer(notes)
}
_ => (),
});
Expand Down
Loading