Skip to content

Commit

Permalink
feat: support taiko protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
johntaiko committed Oct 17, 2023
1 parent 23cbac4 commit daf73ee
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 2 deletions.
1 change: 1 addition & 0 deletions crates/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde = ["dep:serde", "revm-primitives/serde"]
arbitrary = ["std", "revm-primitives/arbitrary"]

optimism = ["revm-primitives/optimism"]
taiko = ["revm-primitives/taiko"]

dev = [
"memory_limit",
Expand Down
1 change: 1 addition & 0 deletions crates/precompile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ std = [
]

optimism = ["revm-primitives/optimism"]
taiko = ["revm-primitives/taiko"]


# This library may not work on all no_std platforms as they depend on C libraries.
Expand Down
1 change: 1 addition & 0 deletions crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ serde = [
arbitrary = ["std", "alloy-primitives/arbitrary", "bitflags/arbitrary"]

optimism = []
taiko = ["dep:once_cell"]

dev = [
"memory_limit",
Expand Down
36 changes: 36 additions & 0 deletions crates/primitives/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::{
InvalidTransaction, Spec, SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK,
MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG,
};
#[cfg(feature = "taiko")]
use crate::{EVMError, TaikoEnv, TxType};
use core::cmp::{min, Ordering};

#[derive(Clone, Debug, Default, PartialEq, Eq)]
Expand All @@ -11,6 +13,23 @@ pub struct Env {
pub cfg: CfgEnv,
pub block: BlockEnv,
pub tx: TxEnv,
#[cfg(feature = "taiko")]
/// Configuration of the taiko
pub taiko: TaikoEnv,
}

#[cfg(feature = "taiko")]
impl Env {
pub fn pre_check<DB>(&self) -> Result<(), EVMError<DB>> {
if !crate::anchor::validate(self) {
return Err(InvalidTransaction::InvalidAnchorTransaction.into());
}
Ok(())
}

pub fn is_anchor(&self) -> bool {
self.tx.index == 0
}
}

/// The block environment.
Expand Down Expand Up @@ -129,6 +148,13 @@ impl BlockEnv {
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TxEnv {
/// The index of the transaction in the block.
#[cfg(feature = "taiko")]
pub index: usize,
/// The type of the transaction.
#[cfg(feature = "taiko")]
pub tx_type: TxType,

/// Caller aka Author aka transaction signer.
pub caller: Address,
/// The gas limit of the transaction.
Expand Down Expand Up @@ -428,6 +454,11 @@ impl Default for BlockEnv {
impl Default for TxEnv {
fn default() -> Self {
Self {
#[cfg(feature = "taiko")]
index: 0,
#[cfg(feature = "taiko")]
tx_type: TxType::Legacy,

caller: Address::ZERO,
gas_limit: u64::MAX,
gas_price: U256::ZERO,
Expand Down Expand Up @@ -648,6 +679,11 @@ impl Env {
.ok_or(InvalidTransaction::OverflowPaymentInTransaction)?;
}

#[cfg(feature = "taiko")]
if self.is_anchor() {
return Ok(());
}

// Check if account has enough balance for gas_limit*gas_price and value transfer.
// Transfer will be done inside `*_inner` functions.
if balance_check > account.info.balance {
Expand Down
4 changes: 4 additions & 0 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub mod precompile;
pub mod result;
pub mod specification;
pub mod state;
#[cfg(feature = "taiko")]
pub mod taiko;
pub mod utilities;

pub use alloy_primitives::{
Expand All @@ -32,4 +34,6 @@ pub use precompile::*;
pub use result::*;
pub use specification::*;
pub use state::*;
#[cfg(feature = "taiko")]
pub use taiko::*;
pub use utilities::*;
3 changes: 3 additions & 0 deletions crates/primitives/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ pub enum InvalidTransaction {
/// post-regolith hardfork.
#[cfg(feature = "optimism")]
DepositSystemTxPostRegolith,
/// Anchor check failed
#[cfg(feature = "taiko")]
InvalidAnchorTransaction,
}

impl<DBError> From<InvalidHeader> for EVMError<DBError> {
Expand Down
5 changes: 5 additions & 0 deletions crates/primitives/src/taiko.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod anchor;
pub mod env;

pub use anchor::*;
pub use env::*;
27 changes: 27 additions & 0 deletions crates/primitives/src/taiko/anchor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use super::env::TxType;
use crate::{Address, Env, TransactTo, U256};
use once_cell::sync::Lazy;
use std::str::FromStr;

const ANCHOR_SELECTOR: u32 = 0xda69d3db;
const ANCHOR_GAS_LIMIT: u64 = 180_000;
static GOLDEN_TOUCH_ACCOUNT: Lazy<Address> = Lazy::new(|| {
Address::from_str("0x0000777735367b36bC9B61C50022d9D0700dB4Ec")
.expect("invalid golden touch account")
});

pub static TREASURY: Lazy<Address> = Lazy::new(|| {
Address::from_str("0xdf09A0afD09a63fb04ab3573922437e1e637dE8b")
.expect("invalid treasury account")
});

pub(crate) fn validate(env: &Env) -> bool {
!env.is_anchor()
|| (env.tx.tx_type == TxType::Eip1559
&& env.tx.transact_to == TransactTo::Call(env.taiko.l2_address)
&& u32::from_be_bytes(env.tx.data[..4].try_into().unwrap()) == ANCHOR_SELECTOR
&& env.tx.value == U256::ZERO
&& env.tx.gas_limit == ANCHOR_GAS_LIMIT
&& env.tx.gas_price == env.block.basefee
&& env.tx.caller == *GOLDEN_TOUCH_ACCOUNT)
}
15 changes: 15 additions & 0 deletions crates/primitives/src/taiko/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::Address;

#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TaikoEnv {
pub l2_address: Address,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TxType {
Legacy,
Eip2930,
Eip1559,
}
1 change: 1 addition & 0 deletions crates/revm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ serde = ["dep:serde", "dep:serde_json", "revm-interpreter/serde"]
arbitrary = ["revm-interpreter/arbitrary"]

optimism = ["revm-interpreter/optimism", "revm-precompile/optimism"]
taiko = ["revm-interpreter/taiko", "revm-precompile/taiko"]

ethersdb = ["std", "tokio", "futures", "ethers-providers", "ethers-core"]

Expand Down
28 changes: 26 additions & 2 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact<DB::Error>
fn preverify_transaction(&mut self) -> Result<(), EVMError<DB::Error>> {
let env = self.env();

#[cfg(feature = "taiko")]
env.pre_check()?;

// Important: validate block before tx.
env.validate_block_env::<GSPEC>()?;
env.validate_tx::<GSPEC>()?;
Expand Down Expand Up @@ -193,6 +196,8 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact<DB::Error>
let tx_value = env.tx.value;
let tx_data = env.tx.data.clone();
let tx_gas_limit = env.tx.gas_limit;
#[cfg(feature = "taiko")]
let is_anchor = env.is_anchor();

#[cfg(feature = "optimism")]
let tx_l1_cost = {
Expand Down Expand Up @@ -278,8 +283,15 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact<DB::Error>
gas_cost = gas_cost.saturating_add(data_fee);
}

caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost);
#[cfg(feature = "taiko")]
if !is_anchor {
caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost);
}

#[cfg(not(feature = "taiko"))]
{
caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost);
}
// touch account so we know it is changed.
caller_account.mark_touch();

Expand Down Expand Up @@ -402,6 +414,18 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
precompiles: Precompiles,
) -> Self {
let journaled_state = JournaledState::new(precompiles.len(), GSPEC::SPEC_ID);

#[cfg(feature = "optimism")]
let handler = if env.cfg.optimism {
Handler::optimism::<GSPEC>()
} else {
Handler::mainnet::<GSPEC>()
};
#[cfg(feature = "taiko")]
let handler = Handler::taiko::<GSPEC>();
#[cfg(not(any(feature = "optimism", feature = "taiko")))]
let handler = Handler::mainnet::<GSPEC>();

Self {
data: EVMData {
env,
Expand All @@ -413,7 +437,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
l1_block_info: None,
},
inspector,
handler: Handler::mainnet::<GSPEC>(),
handler,
_phantomdata: PhantomData {},
}
}
Expand Down
13 changes: 13 additions & 0 deletions crates/revm/src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod mainnet;
#[cfg(feature = "optimism")]
pub mod optimism;
#[cfg(feature = "taiko")]
pub mod taiko;

use revm_interpreter::primitives::db::Database;
use revm_interpreter::primitives::{EVMError, EVMResultGeneric};
Expand Down Expand Up @@ -45,6 +47,17 @@ impl<DB: Database> Handler<DB> {
}
}

/// Handler for the taiko
#[cfg(feature = "taiko")]
pub fn taiko<SPEC: Spec>() -> Self {
Self {
call_return: taiko::handle_call_return::<SPEC>,
calculate_gas_refund: taiko::calculate_gas_refund::<SPEC>,
reimburse_caller: taiko::handle_reimburse_caller::<SPEC, DB>,
reward_beneficiary: taiko::reward_beneficiary::<SPEC, DB>,
}
}

/// Handler for the optimism
#[cfg(feature = "optimism")]
pub fn optimism<SPEC: Spec>() -> Self {
Expand Down
Loading

0 comments on commit daf73ee

Please sign in to comment.