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

prepare for ontake upgrade #27

Merged
merged 10 commits into from
Aug 16, 2024
Merged
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
180 changes: 119 additions & 61 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -504,8 +504,6 @@ similar-asserts = "1.5.0"
test-fuzz = "5"

# raiko
raiko-core = { git = "https://github.com/taikoxyz/raiko.git", branch = "reth-wip" }
raiko-lib = { git = "https://github.com/taikoxyz/raiko.git", branch = "reth-wip" }
anyhow = "1.0"

[patch.crates-io]
1 change: 1 addition & 0 deletions crates/chainspec/Cargo.toml
Original file line number Diff line number Diff line change
@@ -50,3 +50,4 @@ arbitrary = [
"alloy-chains/arbitrary"
]
network = ["reth-network-peers"]
taiko = ["reth-ethereum-forks/taiko"]
14 changes: 11 additions & 3 deletions crates/chainspec/src/spec.rs
Original file line number Diff line number Diff line change
@@ -118,6 +118,8 @@ pub static TAIKO_A7: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(0) },
),
(Hardfork::Shanghai, ForkCondition::Timestamp(0)),
#[cfg(feature = "taiko")]
(Hardfork::Hekla, ForkCondition::Block(0)),
]),
deposit_contract: None,
..Default::default()
@@ -150,6 +152,10 @@ pub static TAIKO_DEV: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(0) },
),
(Hardfork::Shanghai, ForkCondition::Timestamp(0)),
#[cfg(feature = "taiko")]
(Hardfork::Hekla, ForkCondition::Block(0)),
#[cfg(feature = "taiko")]
(Hardfork::Ontake, ForkCondition::Block(20)), //todo
]),
deposit_contract: None,
..Default::default()
@@ -174,14 +180,16 @@ pub static TAIKO_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
(Hardfork::Byzantium, ForkCondition::Block(0)),
(Hardfork::Constantinople, ForkCondition::Block(0)),
(Hardfork::Petersburg, ForkCondition::Block(0)),
(Hardfork::Istanbul, ForkCondition::Block(1561651)),
(Hardfork::Berlin, ForkCondition::Block(4460644)),
(Hardfork::London, ForkCondition::Block(5062605)),
(Hardfork::Istanbul, ForkCondition::Block(0)),
(Hardfork::Berlin, ForkCondition::Block(0)),
(Hardfork::London, ForkCondition::Block(0)),
(
Hardfork::Paris,
ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(0) },
),
(Hardfork::Shanghai, ForkCondition::Timestamp(0)),
#[cfg(feature = "taiko")]
(Hardfork::Hekla, ForkCondition::Block(0)),
]),
deposit_contract: None,
..Default::default()
1 change: 1 addition & 0 deletions crates/ethereum-forks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ proptest-derive.workspace = true

[features]
default = ["std", "serde"]
taiko = []
std = ["thiserror-no-std/std"]
serde = ["dep:serde"]
arbitrary = ["dep:arbitrary", "dep:proptest", "dep:proptest-derive"]
6 changes: 6 additions & 0 deletions crates/ethereum-forks/src/hardfork.rs
Original file line number Diff line number Diff line change
@@ -65,6 +65,12 @@ pub enum Hardfork {
Regolith,
/// Shanghai: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md>.
Shanghai,
/// Hekla: the 1st taiko mainnet version: <>
#[cfg(feature = "taiko")]
Hekla,
/// Ontake: the 2nd taiko mainnet fork: <>
#[cfg(feature = "taiko")]
Ontake,
/// Canyon:
/// <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#canyon>.
#[cfg(feature = "optimism")]
31 changes: 27 additions & 4 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@

use crate::{
dao_fork::{DAO_HARDFORK_BENEFICIARY, DAO_HARDKFORK_ACCOUNTS},
taiko::{check_anchor_tx, TaikoData}, EthEvmConfig,
taiko::{check_anchor_tx, check_anchor_tx_ontake, TaikoData},
EthEvmConfig,
};
use reth_chainspec::{ChainSpec, MAINNET};
pub use reth_consensus::Consensus;
@@ -16,7 +17,8 @@ use reth_evm::{
};
use reth_execution_types::ExecutionOutcome;
use reth_primitives::{
BlockNumber, BlockWithSenders, Hardfork, Header, Receipt, Request, Withdrawals, U256,
revm::config::revm_spec, BlockNumber, BlockWithSenders, Hardfork, Head, Header, Receipt,
Request, Withdrawals, U256,
};
use reth_prune_types::PruneModes;
use reth_revm::{
@@ -31,7 +33,7 @@ use reth_revm::{
};
use revm_primitives::{
db::{Database, DatabaseCommit}, Address, BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ResultAndState,
EVMError, HashSet,
EVMError, HashSet, SpecId,
};
use std::sync::Arc;
use anyhow::Result;
@@ -176,8 +178,28 @@ where

// verify the anchor tx
if is_anchor {
check_anchor_tx(transaction, sender, &block.block, taiko_data.clone().unwrap())
let spec_id = revm_spec(
&self.chain_spec,
Head { number: block.number, ..Default::default() },
);
if spec_id.is_enabled_in(SpecId::ONTAKE) {
check_anchor_tx_ontake(
transaction,
sender,
&block.block,
taiko_data.clone().unwrap(),
)
.map_err(|e| BlockExecutionError::CanonicalRevert { inner: e.to_string() })?;
} else if spec_id.is_enabled_in(SpecId::HEKLA) {
check_anchor_tx(transaction, sender, &block.block, taiko_data.clone().unwrap())
.map_err(|e| BlockExecutionError::CanonicalRevert {
inner: e.to_string(),
})?;
} else {
return Err(BlockExecutionError::CanonicalRevert {
inner: "unknown spec id for anchor".to_string(),
});
}
}

// If the signature was not valid, the sender address will have been set to zero
@@ -211,6 +233,7 @@ where
evm.tx_mut().taiko.is_anchor = is_anchor;
// set the treasury address
evm.tx_mut().taiko.treasury = taiko_data.clone().unwrap().l2_contract;
evm.tx_mut().taiko.basefee_ratio = taiko_data.clone().unwrap().basefee_ratio;

// Execute transaction.
let res = evm.transact().map_err(move |err| {
92 changes: 91 additions & 1 deletion crates/ethereum/evm/src/taiko.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,12 @@ pub struct TaikoData {
pub parent_header: Header,
/// L2 contract
pub l2_contract: Address,
/// base fee sharing ratio
pub basefee_ratio: u8,
/// base fee adjustment quotient
pub basefee_adj_quotient: u8,
/// gas issuance per second
pub gas_issue_per_sec: u32,
}

/// Anchor tx gas limit
@@ -80,8 +86,23 @@ sol! {
)
external
{}

function anchorV2(
uint64 _anchorBlockId,
bytes32 _anchorStateRoot,
uint32 _parentGasUsed,
uint32 _gasIssuancePerSecond,
uint8 _basefeeAdjustmentQuotient
)
external
nonReentrant
{}
}

// todo, use compiled abi once test passes
// sol!(TaikoL2, "./res/TaikoL2.json");
// use TaikoL2::{anchor, anchorV2};

/// Decode anchor tx data
pub fn decode_anchor(bytes: &[u8]) -> Result<anchorCall> {
anchorCall::abi_decode(bytes, true).map_err(|e| anyhow!(e))
@@ -146,4 +167,73 @@ pub fn check_anchor_tx(tx: &TransactionSigned, from: &Address, block: &Block, ta
);

Ok(())
}
}

pub fn decode_anchor_ontake(bytes: &[u8]) -> Result<anchorV2Call> {
anchorV2Call::abi_decode(bytes, true).map_err(|e| anyhow!(e))
}

/// Verifies the anchor tx correctness in ontake fork
pub fn check_anchor_tx_ontake(
tx: &TransactionSigned,
from: &Address,
block: &Block,
taiko_data: TaikoData,
) -> Result<()> {
let anchor: &reth_primitives::TxEip1559 =
tx.as_eip1559().context(anyhow!("anchor tx is not an EIP1559 tx"))?;

// Check the signature
check_anchor_signature(tx).context(anyhow!("failed to check anchor signature"))?;

// Extract the `to` address
let TxKind::Call(to) = anchor.to else { panic!("anchor tx not a smart contract call") };
// Check that it's from the golden touch address
ensure!(*from == *GOLDEN_TOUCH_ACCOUNT, "anchor transaction from mismatch");
// Check that the L2 contract is being called
ensure!(to == taiko_data.l2_contract, "anchor transaction to mismatch");
// Tx can't have any ETH attached
ensure!(anchor.value == U256::from(0), "anchor transaction value mismatch");
// Tx needs to have the expected gas limit
ensure!(anchor.gas_limit == ANCHOR_GAS_LIMIT, "anchor transaction gas price mismatch");
// Check needs to have the base fee set to the block base fee
ensure!(
anchor.max_fee_per_gas == block.header.base_fee_per_gas.unwrap().into(),
"anchor transaction gas mismatch"
);

/*
uint64 _anchorBlockId,
bytes32 _anchorStateRoot,
uint32 _parentGasUsed,
uint32 _gasIssuancePerSecond,
uint8 _basefeeAdjustmentQuotient
*/

// Okay now let's decode the anchor tx to verify the inputs
let anchor_call = decode_anchor_ontake(&anchor.input)?;
ensure!(
anchor_call._anchorStateRoot == taiko_data.l1_header.state_root,
"L1 state root mismatch"
);
ensure!(anchor_call._anchorBlockId == taiko_data.l1_header.number, "L1 block number mismatch");
ensure!(
anchor_call._anchorStateRoot == taiko_data.l1_header.state_root,
"L1 state root mismatch"
);
// The parent gas used input needs to match the gas used value of the parent block
ensure!(
anchor_call._parentGasUsed == taiko_data.parent_header.gas_used as u32,
"parentGasUsed mismatch"
);
ensure!(
anchor_call._gasIssuancePerSecond == taiko_data.gas_issue_per_sec,
"gas issuance per second mismatch"
);
ensure!(
anchor_call._basefeeAdjustmentQuotient == taiko_data.basefee_adj_quotient,
"basefee adjustment quotient mismatch"
);

Ok(())
}
1 change: 1 addition & 0 deletions crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
@@ -121,6 +121,7 @@ optimism = [
taiko = [
"revm-primitives/taiko",
"revm/taiko",
"reth-ethereum-forks/taiko",
]
alloy-compat = [
"reth-primitives-traits/alloy-compat",
9 changes: 9 additions & 0 deletions crates/primitives/src/revm/config.rs
Original file line number Diff line number Diff line change
@@ -52,6 +52,15 @@ pub fn revm_spec(chain_spec: &ChainSpec, block: Head) -> revm_primitives::SpecId
}
}

#[cfg(feature = "taiko")]
if chain_spec.is_taiko() {
if chain_spec.fork(Hardfork::Ontake).active_at_head(&block) {
return revm_primitives::ONTAKE;
} else if chain_spec.fork(Hardfork::Hekla).active_at_head(&block) {
return revm_primitives::HEKLA;
}
}

if chain_spec.fork(Hardfork::Prague).active_at_head(&block) {
revm_primitives::PRAGUE
} else if chain_spec.fork(Hardfork::Cancun).active_at_head(&block) {
2 changes: 1 addition & 1 deletion crates/primitives/src/revm/env.rs
Original file line number Diff line number Diff line change
@@ -212,7 +212,7 @@ fn fill_tx_env_with_system_contract_call(
enveloped_tx: Some(Bytes::default()),
},
#[cfg(feature = "taiko")]
taiko: revm_primitives::TaikoFields { treasury: Address::default(), is_anchor: false },
taiko: revm_primitives::TaikoFields { treasury: Address::default(), is_anchor: false, basefee_ratio: 0u8 },
};

// ensure the block gas limit is >= the tx
2 changes: 0 additions & 2 deletions testing/ef-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -41,6 +41,4 @@ thiserror.workspace = true
rayon.workspace = true

# raiko
raiko-core.workspace = true
raiko-lib.workspace = true
anyhow.workspace = true
Loading