Skip to content

Commit

Permalink
Merge pull request #2736 from OffchainLabs/gas-and-ink-types
Browse files Browse the repository at this point in the history
Add Gas and Ink types in rust
  • Loading branch information
tsahee authored Oct 16, 2024
2 parents 432b539 + 5497a48 commit fc2c2d8
Show file tree
Hide file tree
Showing 31 changed files with 441 additions and 291 deletions.
128 changes: 106 additions & 22 deletions arbitrator/arbutil/src/evm/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,103 @@ impl DataReader for VecReader {
}
}

macro_rules! derive_math {
($t:ident) => {
impl std::ops::Add for $t {
type Output = Self;

fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}

impl std::ops::AddAssign for $t {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}

impl std::ops::Sub for $t {
type Output = Self;

fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}
}

impl std::ops::SubAssign for $t {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
}
}

impl std::ops::Mul<u64> for $t {
type Output = Self;

fn mul(self, rhs: u64) -> Self {
Self(self.0 * rhs)
}
}

impl std::ops::Mul<$t> for u64 {
type Output = $t;

fn mul(self, rhs: $t) -> $t {
$t(self * rhs.0)
}
}

impl $t {
/// Equivalent to the Add trait, but const.
pub const fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}

/// Equivalent to the Sub trait, but const.
pub const fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}

pub const fn saturating_add(self, rhs: Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}

pub const fn saturating_sub(self, rhs: Self) -> Self {
Self(self.0.saturating_sub(rhs.0))
}

pub fn to_be_bytes(self) -> [u8; 8] {
self.0.to_be_bytes()
}
}
};
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
#[must_use]
pub struct Gas(pub u64);

derive_math!(Gas);

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
#[must_use]
pub struct Ink(pub u64);

derive_math!(Ink);

pub trait EvmApi<D: DataReader>: Send + 'static {
/// Reads the 32-byte value in the EVM state trie at offset `key`.
/// Returns the value and the access cost in gas.
/// Analogous to `vm.SLOAD`.
fn get_bytes32(&mut self, key: Bytes32, evm_api_gas_to_use: u64) -> (Bytes32, u64);
fn get_bytes32(&mut self, key: Bytes32, evm_api_gas_to_use: Gas) -> (Bytes32, Gas);

/// Stores the given value at the given key in Stylus VM's cache of the EVM state trie.
/// Note that the actual values only get written after calls to `set_trie_slots`.
fn cache_bytes32(&mut self, key: Bytes32, value: Bytes32) -> u64;
fn cache_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Gas;

/// Persists any dirty values in the storage cache to the EVM state trie, dropping the cache entirely if requested.
/// Analogous to repeated invocations of `vm.SSTORE`.
fn flush_storage_cache(&mut self, clear: bool, gas_left: u64) -> Result<u64>;
fn flush_storage_cache(&mut self, clear: bool, gas_left: Gas) -> Result<Gas>;

/// Reads the 32-byte value in the EVM's transient state trie at offset `key`.
/// Analogous to `vm.TLOAD`.
Expand All @@ -102,10 +186,10 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
&mut self,
contract: Bytes20,
calldata: &[u8],
gas_left: u64,
gas_req: u64,
gas_left: Gas,
gas_req: Gas,
value: Bytes32,
) -> (u32, u64, UserOutcomeKind);
) -> (u32, Gas, UserOutcomeKind);

/// Delegate-calls the contract at the given address.
/// Returns the EVM return data's length, the gas cost, and whether the call succeeded.
Expand All @@ -114,9 +198,9 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
&mut self,
contract: Bytes20,
calldata: &[u8],
gas_left: u64,
gas_req: u64,
) -> (u32, u64, UserOutcomeKind);
gas_left: Gas,
gas_req: Gas,
) -> (u32, Gas, UserOutcomeKind);

/// Static-calls the contract at the given address.
/// Returns the EVM return data's length, the gas cost, and whether the call succeeded.
Expand All @@ -125,9 +209,9 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
&mut self,
contract: Bytes20,
calldata: &[u8],
gas_left: u64,
gas_req: u64,
) -> (u32, u64, UserOutcomeKind);
gas_left: Gas,
gas_req: Gas,
) -> (u32, Gas, UserOutcomeKind);

/// Deploys a new contract using the init code provided.
/// Returns the new contract's address on success, or the error reason on failure.
Expand All @@ -137,8 +221,8 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
&mut self,
code: Vec<u8>,
endowment: Bytes32,
gas: u64,
) -> (eyre::Result<Bytes20>, u32, u64);
gas: Gas,
) -> (eyre::Result<Bytes20>, u32, Gas);

/// Deploys a new contract using the init code provided, with an address determined in part by the `salt`.
/// Returns the new contract's address on success, or the error reason on failure.
Expand All @@ -149,8 +233,8 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
code: Vec<u8>,
endowment: Bytes32,
salt: Bytes32,
gas: u64,
) -> (eyre::Result<Bytes20>, u32, u64);
gas: Gas,
) -> (eyre::Result<Bytes20>, u32, Gas);

/// Returns the EVM return data.
/// Analogous to `vm.RETURNDATACOPY`.
Expand All @@ -164,29 +248,29 @@ pub trait EvmApi<D: DataReader>: Send + 'static {
/// Gets the balance of the given account.
/// Returns the balance and the access cost in gas.
/// Analogous to `vm.BALANCE`.
fn account_balance(&mut self, address: Bytes20) -> (Bytes32, u64);
fn account_balance(&mut self, address: Bytes20) -> (Bytes32, Gas);

/// Returns the code and the access cost in gas.
/// Analogous to `vm.EXTCODECOPY`.
fn account_code(&mut self, address: Bytes20, gas_left: u64) -> (D, u64);
fn account_code(&mut self, address: Bytes20, gas_left: Gas) -> (D, Gas);

/// Gets the hash of the given address's code.
/// Returns the hash and the access cost in gas.
/// Analogous to `vm.EXTCODEHASH`.
fn account_codehash(&mut self, address: Bytes20) -> (Bytes32, u64);
fn account_codehash(&mut self, address: Bytes20) -> (Bytes32, Gas);

/// Determines the cost in gas of allocating additional wasm pages.
/// Note: has the side effect of updating Geth's memory usage tracker.
/// Not analogous to any EVM opcode.
fn add_pages(&mut self, pages: u16) -> u64;
fn add_pages(&mut self, pages: u16) -> Gas;

/// Captures tracing information for hostio invocations during native execution.
fn capture_hostio(
&mut self,
name: &str,
args: &[u8],
outs: &[u8],
start_ink: u64,
end_ink: u64,
start_ink: Ink,
end_ink: Ink,
);
}
49 changes: 25 additions & 24 deletions arbitrator/arbutil/src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,78 @@
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::{Bytes20, Bytes32};
use api::Gas;

pub mod api;
pub mod req;
pub mod storage;
pub mod user;

// params.SstoreSentryGasEIP2200
pub const SSTORE_SENTRY_GAS: u64 = 2300;
pub const SSTORE_SENTRY_GAS: Gas = Gas(2300);

// params.ColdAccountAccessCostEIP2929
pub const COLD_ACCOUNT_GAS: u64 = 2600;
pub const COLD_ACCOUNT_GAS: Gas = Gas(2600);

// params.ColdSloadCostEIP2929
pub const COLD_SLOAD_GAS: u64 = 2100;
pub const COLD_SLOAD_GAS: Gas = Gas(2100);

// params.WarmStorageReadCostEIP2929
pub const WARM_SLOAD_GAS: u64 = 100;
pub const WARM_SLOAD_GAS: Gas = Gas(100);

// params.WarmStorageReadCostEIP2929 (see enable1153 in jump_table.go)
pub const TLOAD_GAS: u64 = WARM_SLOAD_GAS;
pub const TSTORE_GAS: u64 = WARM_SLOAD_GAS;
pub const TLOAD_GAS: Gas = WARM_SLOAD_GAS;
pub const TSTORE_GAS: Gas = WARM_SLOAD_GAS;

// params.LogGas and params.LogDataGas
pub const LOG_TOPIC_GAS: u64 = 375;
pub const LOG_DATA_GAS: u64 = 8;
pub const LOG_TOPIC_GAS: Gas = Gas(375);
pub const LOG_DATA_GAS: Gas = Gas(8);

// params.CopyGas
pub const COPY_WORD_GAS: u64 = 3;
pub const COPY_WORD_GAS: Gas = Gas(3);

// params.Keccak256Gas
pub const KECCAK_256_GAS: u64 = 30;
pub const KECCAK_WORD_GAS: u64 = 6;
pub const KECCAK_256_GAS: Gas = Gas(30);
pub const KECCAK_WORD_GAS: Gas = Gas(6);

// vm.GasQuickStep (see gas.go)
pub const GAS_QUICK_STEP: u64 = 2;
pub const GAS_QUICK_STEP: Gas = Gas(2);

// vm.GasQuickStep (see jump_table.go)
pub const ADDRESS_GAS: u64 = GAS_QUICK_STEP;
pub const ADDRESS_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see eips.go)
pub const BASEFEE_GAS: u64 = GAS_QUICK_STEP;
pub const BASEFEE_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see eips.go)
pub const CHAINID_GAS: u64 = GAS_QUICK_STEP;
pub const CHAINID_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const COINBASE_GAS: u64 = GAS_QUICK_STEP;
pub const COINBASE_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const GASLIMIT_GAS: u64 = GAS_QUICK_STEP;
pub const GASLIMIT_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const NUMBER_GAS: u64 = GAS_QUICK_STEP;
pub const NUMBER_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const TIMESTAMP_GAS: u64 = GAS_QUICK_STEP;
pub const TIMESTAMP_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const GASLEFT_GAS: u64 = GAS_QUICK_STEP;
pub const GASLEFT_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const CALLER_GAS: u64 = GAS_QUICK_STEP;
pub const CALLER_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const CALLVALUE_GAS: u64 = GAS_QUICK_STEP;
pub const CALLVALUE_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const GASPRICE_GAS: u64 = GAS_QUICK_STEP;
pub const GASPRICE_GAS: Gas = GAS_QUICK_STEP;

// vm.GasQuickStep (see jump_table.go)
pub const ORIGIN_GAS: u64 = GAS_QUICK_STEP;
pub const ORIGIN_GAS: Gas = GAS_QUICK_STEP;

pub const ARBOS_VERSION_STYLUS_CHARGING_FIXES: u64 = 32;

Expand Down
Loading

0 comments on commit fc2c2d8

Please sign in to comment.