Skip to content

Commit

Permalink
perf(interpreter): keep track of remaining gas rather than spent (blu…
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored and fubuloubu committed Apr 11, 2024
1 parent 2ac52e4 commit c6c2409
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 43 deletions.
64 changes: 33 additions & 31 deletions crates/interpreter/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ use revm_primitives::{Spec, SpecId::LONDON};
/// Represents the state of gas during execution.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Gas {
/// The initial gas limit.
/// The initial gas limit. This is constant throughout execution.
limit: u64,
/// The total used gas.
all_used_gas: u64,
/// Used gas without memory expansion.
used: u64,
/// Used gas for memory expansion.
/// The remaining gas.
remaining: u64,
/// The remaining gas, without memory expansion.
remaining_nomem: u64,
/// The **last** memory expansion cost.
memory: u64,
/// Refunded gas. This is used only at the end of execution.
refunded: i64,
Expand All @@ -28,10 +28,10 @@ impl Gas {
pub const fn new(limit: u64) -> Self {
Self {
limit,
used: 0,
remaining: limit,
remaining_nomem: limit,
memory: 0,
refunded: 0,
all_used_gas: 0,
}
}

Expand All @@ -41,35 +41,42 @@ impl Gas {
self.limit
}

/// Returns the amount of gas that was used.
/// Returns the **last** memory expansion cost.
#[inline]
pub const fn memory(&self) -> u64 {
self.memory
}

/// Returns the amount of gas that was refunded.
/// Returns the total amount of gas that was refunded.
#[inline]
pub const fn refunded(&self) -> i64 {
self.refunded
}

/// Returns all the gas used in the execution.
/// Returns the total amount of gas spent.
#[inline]
pub const fn spent(&self) -> u64 {
self.limit - self.remaining
}

#[doc(hidden)]
#[inline]
#[deprecated(note = "use `spent` instead")]
pub const fn spend(&self) -> u64 {
self.all_used_gas
self.spent()
}

/// Returns the amount of gas remaining.
#[inline]
pub const fn remaining(&self) -> u64 {
self.limit - self.all_used_gas
self.remaining
}

/// Erases a gas cost from the totals.
#[inline]
pub fn erase_cost(&mut self, returned: u64) {
self.used -= returned;
self.all_used_gas -= returned;
self.remaining_nomem += returned;
self.remaining += returned;
}

/// Records a refund value.
Expand All @@ -86,12 +93,14 @@ impl Gas {
/// Max refund value is limited to Nth part (depending of fork) of gas spend.
///
/// Related to EIP-3529: Reduction in refunds
#[inline]
pub fn set_final_refund<SPEC: Spec>(&mut self) {
let max_refund_quotient = if SPEC::enabled(LONDON) { 5 } else { 2 };
self.refunded = (self.refunded() as u64).min(self.spend() / max_refund_quotient) as i64;
self.refunded = (self.refunded() as u64).min(self.spent() / max_refund_quotient) as i64;
}

/// Set a refund value
/// Set a refund value. This overrides the current refund value.
#[inline]
pub fn set_refund(&mut self, refund: i64) {
self.refunded = refund;
}
Expand All @@ -101,13 +110,13 @@ impl Gas {
/// Returns `false` if the gas limit is exceeded.
#[inline(always)]
pub fn record_cost(&mut self, cost: u64) -> bool {
let all_used_gas = self.all_used_gas.saturating_add(cost);
if self.limit < all_used_gas {
let (remaining, overflow) = self.remaining.overflowing_sub(cost);
if overflow {
return false;
}

self.used += cost;
self.all_used_gas = all_used_gas;
self.remaining_nomem -= cost;
self.remaining = remaining;
true
}

Expand All @@ -117,20 +126,13 @@ impl Gas {
#[inline]
pub fn record_memory(&mut self, gas_memory: u64) -> bool {
if gas_memory > self.memory {
let all_used_gas = self.used.saturating_add(gas_memory);
if self.limit < all_used_gas {
let (remaining, overflow) = self.remaining_nomem.overflowing_sub(gas_memory);
if overflow {
return false;
}
self.memory = gas_memory;
self.all_used_gas = all_used_gas;
self.remaining = remaining;
}
true
}

#[doc(hidden)]
#[deprecated = "use `record_refund` instead"]
#[inline]
pub fn gas_refund(&mut self, refund: i64) {
self.record_refund(refund);
}
}
8 changes: 4 additions & 4 deletions crates/revm/src/handler/mainnet/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ mod tests {
fn test_consume_gas() {
let gas = call_last_frame_return(InstructionResult::Stop, Gas::new(90));
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}

Expand All @@ -177,20 +177,20 @@ mod tests {

let gas = call_last_frame_return(InstructionResult::Stop, return_gas);
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 2);

let gas = call_last_frame_return(InstructionResult::Revert, return_gas);
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}

#[test]
fn test_revert_gas() {
let gas = call_last_frame_return(InstructionResult::Revert, Gas::new(90));
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}
}
4 changes: 2 additions & 2 deletions crates/revm/src/handler/mainnet/post_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn reward_beneficiary<SPEC: Spec, EXT, DB: Database>(
coinbase_account.info.balance = coinbase_account
.info
.balance
.saturating_add(coinbase_gas_price * U256::from(gas.spend() - gas.refunded() as u64));
.saturating_add(coinbase_gas_price * U256::from(gas.spent() - gas.refunded() as u64));

Ok(())
}
Expand Down Expand Up @@ -79,7 +79,7 @@ pub fn output<EXT, DB: Database>(
core::mem::replace(&mut context.evm.error, Ok(()))?;
// used gas with refund calculated.
let gas_refunded = result.gas().refunded() as u64;
let final_gas_used = result.gas().spend() - gas_refunded;
let final_gas_used = result.gas().spent() - gas_refunded;
let output = result.output();
let instruction_result = result.into_interpreter_result();

Expand Down
12 changes: 6 additions & 6 deletions crates/revm/src/optimism/handler_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ pub fn reward_beneficiary<SPEC: Spec, EXT, DB: Database>(
.env
.block
.basefee
.mul(U256::from(gas.spend() - gas.refunded() as u64));
.mul(U256::from(gas.spent() - gas.refunded() as u64));
}
Ok(())
}
Expand Down Expand Up @@ -410,7 +410,7 @@ mod tests {
let gas =
call_last_frame_return::<BedrockSpec>(env, InstructionResult::Revert, Gas::new(90));
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}

Expand All @@ -423,7 +423,7 @@ mod tests {
let gas =
call_last_frame_return::<RegolithSpec>(env, InstructionResult::Stop, Gas::new(90));
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}

Expand All @@ -439,12 +439,12 @@ mod tests {
let gas =
call_last_frame_return::<RegolithSpec>(env.clone(), InstructionResult::Stop, ret_gas);
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 2); // min(20, 10/5)

let gas = call_last_frame_return::<RegolithSpec>(env, InstructionResult::Revert, ret_gas);
assert_eq!(gas.remaining(), 90);
assert_eq!(gas.spend(), 10);
assert_eq!(gas.spent(), 10);
assert_eq!(gas.refunded(), 0);
}

Expand All @@ -456,7 +456,7 @@ mod tests {

let gas = call_last_frame_return::<BedrockSpec>(env, InstructionResult::Stop, Gas::new(90));
assert_eq!(gas.remaining(), 0);
assert_eq!(gas.spend(), 100);
assert_eq!(gas.spent(), 100);
assert_eq!(gas.refunded(), 0);
}

Expand Down

0 comments on commit c6c2409

Please sign in to comment.