Skip to content

Commit

Permalink
refactor prepay gas calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
KaoImin committed Nov 29, 2023
1 parent 964f841 commit 421f8f8
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
17 changes: 8 additions & 9 deletions core/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,16 @@ impl AxonExecutor {
// The `Backend` trait is imply in
// `core/executor/src/adapter/backend/read_only.rs`. The `gas_price` is never
// larger than u64::MAX.
let tx_gas_price = adapter.gas_price().low_u64();
let tx_gas_price = adapter.gas_price();
let gas_limit = tx.transaction.unsigned.gas_limit().low_u64();
let prepay_gas = tx_gas_price * gas_limit;
// The overflow check is done in the `check_authorization` function
// of`core/mempool/src/adapter/mod.rs`.
let prepay_gas = tx_gas_price * U256::from(gas_limit);

let mut account = adapter.get_account(&sender);
let old_nonce = account.nonce;

account.balance = account.balance.saturating_sub(prepay_gas.into());
account.balance = account.balance.saturating_sub(prepay_gas);
adapter.save_account(&sender, &account);

let metadata = StackSubstateMetadata::new(gas_limit, config);
Expand Down Expand Up @@ -372,9 +374,7 @@ impl AxonExecutor {

// Add remain gas
if remained_gas != 0 {
let remain_gas = U256::from(remained_gas)
.checked_mul(tx_gas_price.into())
.unwrap_or_else(U256::max_value);
let remain_gas = U256::from(remained_gas) * tx_gas_price;
account.balance = account
.balance
.checked_add(remain_gas)
Expand All @@ -388,9 +388,8 @@ impl AxonExecutor {
ret: res,
remain_gas: remained_gas,
gas_used: used_gas,
fee_cost: U256::from(tx_gas_price)
.checked_mul(used_gas.into())
.unwrap_or(U256::max_value()),
fee_cost: tx_gas_price * U256::from(used_gas), /* used_gas must le transaction
* gas_limit */
logs: vec![],
code_address: code_addr,
removed: false,
Expand Down
4 changes: 2 additions & 2 deletions core/mempool/src/adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ where
tx_nonce: tx.transaction.unsigned.nonce().low_u64(),
}
.into());
} else if res.value().1 < tx.transaction.unsigned.may_cost() {
} else if res.value().1 < tx.transaction.unsigned.may_cost()? {
return Err(MemPoolError::ExceedBalance {
tx_hash: tx.transaction.hash,
account_balance: res.value().1,
Expand All @@ -410,7 +410,7 @@ where
.into());
}

if account.balance < tx.transaction.unsigned.may_cost() {
if account.balance < tx.transaction.unsigned.may_cost()? {
return Err(MemPoolError::ExceedBalance {
tx_hash: tx.transaction.hash,
account_balance: account.balance,
Expand Down
12 changes: 10 additions & 2 deletions protocol/src/constants/configs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use crate::types::U64;

pub const MAX_GAS_LIMIT: u64 = 30_000_000;
pub const MAX_GAS_PRICE: U64 = U64([u64::MAX / MAX_GAS_LIMIT / 100_000 - 1]);
/// There is not a standard for the maximum gas limit, as long as the account
/// balance can pay the `gas_limit * gas_price`. For reduce some useless
/// calculation, `50_000_000` is large enough to cover the transaction usage.
pub const MAX_GAS_LIMIT: u64 = 50_000_000;
/// According to [go-ethereum](https://github.com/ethereum/go-ethereum/blob/be65b47/eth/gasprice/gasprice.go#L38),
/// the maximum gas price is 500 Gwei.
pub const MAX_GAS_PRICE: U64 = U64([500 * GWEI]);
pub const MIN_TRANSACTION_GAS_LIMIT: u64 = 21_000;
/// The mempool refresh timeout is 50 milliseconds.
pub const MEMPOOL_REFRESH_TIMEOUT: u64 = 50;
pub const MAX_BLOCK_GAS_LIMIT: u64 = 30_000_000;
// MAX_FEE_HISTORY is the maximum number of blocks that can be retrieved for a
Expand All @@ -11,3 +17,5 @@ pub const MAX_BLOCK_GAS_LIMIT: u64 = 30_000_000;
pub const MAX_FEE_HISTORY: u64 = 1024;
pub const MAX_RPC_GAS_CAP: u64 = 50_000_000;
pub const BASE_FEE_PER_GAS: u64 = 0x539;

const GWEI: u64 = 100_000_000;
3 changes: 3 additions & 0 deletions protocol/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ pub enum TypesError {

#[display(fmt = "Decode interoperation signature R error {:?}", _0)]
DecodeInteroperationSigR(rlp::DecoderError),

#[display(fmt = "Prepay gas is too large")]
PrepayGasIsTooLarge,
}

impl Error for TypesError {}
Expand Down
17 changes: 11 additions & 6 deletions protocol/src/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ impl UnsignedTransaction {
}
}

pub fn may_cost(&self) -> U256 {
if let Some(res) = self.gas_price().checked_mul(*self.gas_limit()) {
return U256::from(res.low_u64())
pub fn may_cost(&self) -> ProtocolResult<U256> {
if let Some(res) = U256::from(self.gas_price().low_u64())
.checked_mul(U256::from(self.gas_limit().low_u64()))
{
return Ok(res
.checked_add(*self.value())
.unwrap_or_else(U256::max_value);
.unwrap_or_else(U256::max_value));
}

U256::max_value()
Err(TypesError::PrepayGasIsTooLarge.into())
}

pub fn base_gas(&self) -> u64 {
Expand Down Expand Up @@ -182,7 +184,8 @@ impl UnsignedTransaction {

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct LegacyTransaction {
// According to [EIP-2681](https://eips.ethereum.org/EIPS/eip-2681), limit account nonce to 2^64-1
/// According to [EIP-2681](https://eips.ethereum.org/EIPS/eip-2681),
/// limit account nonce to 2^64-1.
pub nonce: U64,
pub gas_price: U64,
pub gas_limit: U64,
Expand Down Expand Up @@ -215,6 +218,8 @@ impl LegacyTransaction {

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Eip2930Transaction {
/// According to [EIP-2681](https://eips.ethereum.org/EIPS/eip-2681),
/// limit account nonce to 2^64-1.
pub nonce: U64,
pub gas_price: U64,
pub gas_limit: U64,
Expand Down

0 comments on commit 421f8f8

Please sign in to comment.