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

Add Gas and Ink types in rust #2736

Merged
merged 7 commits into from
Oct 16, 2024
Merged
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
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)
eljobe marked this conversation as resolved.
Show resolved Hide resolved
}
}

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
Loading