Skip to content

Commit

Permalink
feat(node): txn prioritization based on gas parameters (#1185)
Browse files Browse the repository at this point in the history
Co-authored-by: cryptoAtwill <willes.lau@protocol.ai>
  • Loading branch information
cryptoAtwill and cryptoAtwill authored Dec 17, 2024
1 parent 8f88bb7 commit 94ec24f
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 5 deletions.
10 changes: 6 additions & 4 deletions fendermint/app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,9 +646,6 @@ where
.await
.context("error running check")?;

// Update the check state.
*guard = Some(state);

let mut mpool_received_trace = MpoolReceived::default();

let response = match result {
Expand All @@ -658,11 +655,16 @@ where
Ok(Err(InvalidSignature(d))) => invalid_check_tx(AppError::InvalidSignature, d),
Ok(Ok(ret)) => {
mpool_received_trace.message = Some(Message::from(&ret.message));
to_check_tx(ret)

let priority = state.txn_priority_calculator().priority(&ret.message);
to_check_tx(ret, priority)
}
},
};

// Update the check state.
*guard = Some(state);

mpool_received_trace.accept = response.code.is_ok();
if !mpool_received_trace.accept {
mpool_received_trace.reason = Some(format!("{:?} - {}", response.code, response.info));
Expand Down
3 changes: 2 additions & 1 deletion fendermint/app/src/tmconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ pub fn to_deliver_tx(
}
}

pub fn to_check_tx(ret: FvmCheckRet) -> response::CheckTx {
pub fn to_check_tx(ret: FvmCheckRet, priority: i64) -> response::CheckTx {
// Putting the message `log` because only `log` appears in the `tx_sync` JSON-RPC response.
let message = ret
.info
Expand All @@ -144,6 +144,7 @@ pub fn to_check_tx(ret: FvmCheckRet) -> response::CheckTx {
data,
gas_wanted: ret.gas_limit.try_into().unwrap_or(i64::MAX),
sender: ret.sender.to_string(),
priority,
..Default::default()
}
}
Expand Down
4 changes: 4 additions & 0 deletions fendermint/vm/interpreter/src/fvm/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ pub struct BlockGasTracker {
}

impl BlockGasTracker {
pub fn base_fee(&self) -> &TokenAmount {
&self.base_fee
}

pub fn create<E: Executor>(executor: &mut E) -> anyhow::Result<BlockGasTracker> {
let mut ret = Self {
base_fee: Zero::zero(),
Expand Down
9 changes: 9 additions & 0 deletions fendermint/vm/interpreter/src/fvm/state/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::{HashMap, HashSet};
use crate::fvm::activity::actor::ActorActivityTracker;
use crate::fvm::externs::FendermintExterns;
use crate::fvm::gas::BlockGasTracker;
use crate::fvm::state::priority::TxnPriorityCalculator;
use anyhow::Ok;
use cid::Cid;
use fendermint_actors_api::gas_market::Reading;
Expand Down Expand Up @@ -149,6 +150,8 @@ where
params: FvmUpdatableParams,
/// Indicate whether the parameters have been updated.
params_dirty: bool,

txn_priority: TxnPriorityCalculator,
}

impl<DB> FvmExecState<DB>
Expand Down Expand Up @@ -185,6 +188,7 @@ where
let mut executor = DefaultExecutor::new(engine.clone(), machine)?;

let block_gas_tracker = BlockGasTracker::create(&mut executor)?;
let base_fee = block_gas_tracker.base_fee().clone();

Ok(Self {
executor,
Expand All @@ -198,6 +202,7 @@ where
power_scale: params.power_scale,
},
params_dirty: false,
txn_priority: TxnPriorityCalculator::new(base_fee),
})
}

Expand Down Expand Up @@ -312,6 +317,10 @@ where
self.params.power_scale
}

pub fn txn_priority_calculator(&self) -> &TxnPriorityCalculator {
&self.txn_priority
}

pub fn app_version(&self) -> u64 {
self.params.app_version
}
Expand Down
1 change: 1 addition & 0 deletions fendermint/vm/interpreter/src/fvm/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod snapshot;
mod check;
mod exec;
mod genesis;
mod priority;
mod query;

use std::sync::Arc;
Expand Down
80 changes: 80 additions & 0 deletions fendermint/vm/interpreter/src/fvm/state/priority.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT

use crate::fvm::FvmMessage;
use fvm_shared::econ::TokenAmount;
use num_traits::ToPrimitive;

/// The transaction priority calculator. The priority calculated is used to determine the ordering
/// in the mempool.
pub struct TxnPriorityCalculator {
base_fee: TokenAmount,
}

impl TxnPriorityCalculator {
pub fn new(base_fee: TokenAmount) -> Self {
Self { base_fee }
}

pub fn priority(&self, msg: &FvmMessage) -> i64 {
if msg.gas_fee_cap < self.base_fee {
return i64::MIN;
}

let effective_premium = msg
.gas_premium
.clone()
.min(&msg.gas_fee_cap - &self.base_fee);
effective_premium.atto().to_i64().unwrap_or(i64::MAX)
}
}

#[cfg(test)]
mod tests {
use crate::fvm::state::priority::TxnPriorityCalculator;
use crate::fvm::FvmMessage;
use fvm_shared::address::Address;
use fvm_shared::bigint::BigInt;
use fvm_shared::econ::TokenAmount;

fn create_msg(fee_cap: TokenAmount, premium: TokenAmount) -> FvmMessage {
FvmMessage {
version: 0,
from: Address::new_id(10),
to: Address::new_id(12),
sequence: 0,
value: Default::default(),
method_num: 0,
params: Default::default(),
gas_limit: 0,
gas_fee_cap: fee_cap,
gas_premium: premium,
}
}

#[test]
fn priority_calculation() {
let cal = TxnPriorityCalculator::new(TokenAmount::from_atto(30));

let msg = create_msg(TokenAmount::from_atto(1), TokenAmount::from_atto(20));
assert_eq!(cal.priority(&msg), i64::MIN);

let msg = create_msg(TokenAmount::from_atto(10), TokenAmount::from_atto(20));
assert_eq!(cal.priority(&msg), i64::MIN);

let msg = create_msg(TokenAmount::from_atto(35), TokenAmount::from_atto(20));
assert_eq!(cal.priority(&msg), 5);

let msg = create_msg(TokenAmount::from_atto(50), TokenAmount::from_atto(20));
assert_eq!(cal.priority(&msg), 20);

let msg = create_msg(TokenAmount::from_atto(50), TokenAmount::from_atto(10));
assert_eq!(cal.priority(&msg), 10);

let msg = create_msg(
TokenAmount::from_atto(BigInt::from(i128::MAX)),
TokenAmount::from_atto(BigInt::from(i128::MAX)),
);
assert_eq!(cal.priority(&msg), i64::MAX);
}
}

0 comments on commit 94ec24f

Please sign in to comment.