From 2b3b82a87d47fa659d1e8317e58764ffe964599b Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 26 Jul 2024 13:28:01 +0800 Subject: [PATCH] use forked verifier set together with taiko hard forks Signed-off-by: smtmfft --- core/src/lib.rs | 16 ++-- core/src/preflight.rs | 1 - host/config/chain_spec_list_default.json | 59 ++++++++---- lib/src/builder.rs | 35 ++++++- lib/src/consts.rs | 112 +++++++++++++++++++++-- lib/src/input.rs | 16 ++++ lib/src/protocol_instance.rs | 54 +++++------ provers/sgx/setup/src/app_args.rs | 4 + provers/sgx/setup/src/setup_bootstrap.rs | 10 +- 9 files changed, 236 insertions(+), 71 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index 0f0c143e..18e48afd 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -16,6 +16,7 @@ use raiko_lib::{ input::{GuestInput, GuestOutput, TaikoProverData}, prover::{IdStore, IdWrite}, }; +use reth_primitives::revm_primitives::SpecId; use reth_primitives::Header; use serde_json::Value; use std::{collections::HashMap, hint::black_box}; @@ -52,8 +53,11 @@ impl Raiko { provider: BDP, ) -> RaikoResult { //TODO: read fork from config - if self.request.block_number <= 999999999 { - preflight( + match self + .taiko_chain_spec + .active_fork(self.request.block_number, 0)? + { + SpecId::HEKLA => preflight( provider, self.request.block_number, self.l1_chain_spec.to_owned(), @@ -65,9 +69,8 @@ impl Raiko { self.request.blob_proof_type.clone(), ) .await - .map_err(Into::::into) - } else { - crate::preflight::ontake::preflight( + .map_err(Into::::into), + SpecId::ONTAKE => crate::preflight::ontake::preflight( provider, self.request.block_number, self.request.block_number, @@ -80,7 +83,8 @@ impl Raiko { self.request.blob_proof_type.clone(), ) .await - .map_err(Into::::into) + .map_err(Into::::into), + _ => Err(RaikoError::Preflight("Unsupported fork".to_owned())), } } diff --git a/core/src/preflight.rs b/core/src/preflight.rs index 71c405cb..e00bfe03 100644 --- a/core/src/preflight.rs +++ b/core/src/preflight.rs @@ -38,7 +38,6 @@ pub mod ontake; pub use hekla::*; - // block_time_to_block_slot returns the slots of the given timestamp. fn block_time_to_block_slot( block_time: u64, diff --git a/host/config/chain_spec_list_default.json b/host/config/chain_spec_list_default.json index 37921d26..5aac0a61 100644 --- a/host/config/chain_spec_list_default.json +++ b/host/config/chain_spec_list_default.json @@ -27,10 +27,12 @@ "l2_contract": null, "rpc": "https://rpc.ankr.com/eth", "beacon_rpc": "https://ethereum-beacon-api.publicnode.com", - "verifier_address": { - "SGX":"0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", - "SP1":null, - "RISC0":"0x0000000000000000000000000000000000000000" + "verifier_address_forks": { + "FRONTIER": { + "SGX": "0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", + "SP1": null, + "RISC0": "0x0000000000000000000000000000000000000000" + } }, "genesis_time": 1606824023, "seconds_per_slot": 12, @@ -61,10 +63,12 @@ "l2_contract": null, "rpc": "https://ethereum-holesky-rpc.publicnode.com", "beacon_rpc": "https://fabled-weathered-cherry.ethereum-holesky.quiknode.pro/8f1c66935fa5f9afbda0db43318fe3c9e7b061e1/", - "verifier_address": { - "SGX":"0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", - "SP1":null, - "RISC0":"0x0000000000000000000000000000000000000000" + "verifier_address_forks": { + "FRONTIER": { + "SGX": "0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", + "SP1": null, + "RISC0": "0x0000000000000000000000000000000000000000" + } }, "genesis_time": 1695902400, "seconds_per_slot": 12, @@ -73,11 +77,14 @@ { "name": "taiko_a7", "chain_id": 167009, - "max_spec_id": "SHANGHAI", + "max_spec_id": "ONTAKE", "hard_forks": { - "SHANGHAI": { + "HEKLA": { "Block": 0 }, + "ONTAKE": { + "Block": 999999 + }, "CANCUN": "TBD" }, "eip_1559_constants": { @@ -90,10 +97,17 @@ "l2_contract": "0x1670090000000000000000000000000000010001", "rpc": "https://rpc.hekla.taiko.xyz", "beacon_rpc": null, - "verifier_address":{ - "SGX":"0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", - "SP1":null, - "RISC0":"0x0000000000000000000000000000000000000000" + "verifier_address_forks": { + "HEKLA": { + "SGX": "0x532efbf6d62720d0b2a2bb9d11066e8588cae6d9", + "SP1": null, + "RISC0": "0x0000000000000000000000000000000000000000" + }, + "ONTAKE": { + "SGX": "0xf6d620d0b2a2bb9d11066e8532efb72588cae6d9", + "SP1": null, + "RISC0": "0x0000000000000000000000000000000000000000" + } }, "genesis_time": 0, "seconds_per_slot": 1, @@ -102,11 +116,14 @@ { "name": "taiko_mainnet", "chain_id": 167000, - "max_spec_id": "SHANGHAI", + "max_spec_id": "ONTAKE", "hard_forks": { - "SHANGHAI": { + "HEKLA": { "Block": 0 }, + "ONTAKE": { + "Block": 999999 + }, "CANCUN": "TBD" }, "eip_1559_constants": { @@ -119,10 +136,12 @@ "l2_contract": "0x1670000000000000000000000000000000010001", "rpc": "https://rpc.mainnet.taiko.xyz", "beacon_rpc": null, - "verifier_address": { - "SGX":"0xb0f3186FC1963f774f52ff455DC86aEdD0b31F81", - "SP1":null, - "RISC0":"0x0000000000000000000000000000000000000000" + "verifier_address_forks": { + "HEKLA": { + "SGX": "0xb0f3186FC1963f774f52ff455DC86aEdD0b31F81", + "SP1": null, + "RISC0": "0x0000000000000000000000000000000000000000" + } }, "genesis_time": 0, "seconds_per_slot": 1, diff --git a/lib/src/builder.rs b/lib/src/builder.rs index bc662681..bd4d9197 100644 --- a/lib/src/builder.rs +++ b/lib/src/builder.rs @@ -12,7 +12,9 @@ use crate::{ CycleTracker, }; use anyhow::{bail, ensure, Result}; -use reth_chainspec::{ChainSpecBuilder, HOLESKY, MAINNET, TAIKO_A7, TAIKO_DEV, TAIKO_MAINNET}; +use reth_chainspec::{ + ChainSpecBuilder, Hardfork, HOLESKY, MAINNET, TAIKO_A7, TAIKO_DEV, TAIKO_MAINNET, +}; use reth_evm::execute::{BlockExecutionOutput, BlockValidationError, Executor, ProviderError}; use reth_evm_ethereum::execute::{ validate_block_post_execution, Consensus, EthBeaconConsensus, EthExecutorProvider, @@ -20,7 +22,7 @@ use reth_evm_ethereum::execute::{ use reth_evm_ethereum::taiko::TaikoData; use reth_primitives::revm_primitives::db::{Database, DatabaseCommit}; use reth_primitives::revm_primitives::{ - Account, AccountInfo, AccountStatus, Bytecode, Bytes, HashMap, + Account, AccountInfo, AccountStatus, Bytecode, Bytes, HashMap, SpecId, }; use reth_primitives::{Address, BlockWithSenders, Header, B256, KECCAK_EMPTY, U256}; use tracing::debug; @@ -96,6 +98,35 @@ impl + DatabaseCommit + OptimisticDatabase> _ => unimplemented!(), }; + if reth_chain_spec.is_taiko() { + let block_num = self.input.taiko.block_proposed.block_number(); + let block_timestamp = 0u64; // self.input.taiko.block_proposed.block_timestamp(); + let taiko_fork = self + .input + .chain_spec + .spec_id(block_num, block_timestamp) + .unwrap(); + match taiko_fork { + SpecId::HEKLA => { + assert!( + reth_chain_spec + .fork(Hardfork::Ontake) + .active_at_block(block_num), + "evm fork is not active, please update the chain spec" + ); + } + SpecId::ONTAKE => { + assert!( + reth_chain_spec + .fork(Hardfork::Ontake) + .active_at_block(block_num), + "evm fork is not active, please update the chain spec" + ); + } + _ => unimplemented!(), + } + } + // Generate the transactions from the tx list let mut block = self.input.block.clone(); block.body = generate_transactions( diff --git a/lib/src/consts.rs b/lib/src/consts.rs index bc941fd1..6ebd88a2 100644 --- a/lib/src/consts.rs +++ b/lib/src/consts.rs @@ -148,7 +148,7 @@ pub struct ChainSpec { pub l2_contract: Option
, pub rpc: String, pub beacon_rpc: Option, - pub verifier_address: BTreeMap>, + pub verifier_address_forks: BTreeMap>>, pub genesis_time: u64, pub seconds_per_slot: u64, pub is_taiko: bool, @@ -173,7 +173,7 @@ impl ChainSpec { l2_contract: None, rpc: "".to_string(), beacon_rpc: None, - verifier_address: BTreeMap::new(), + verifier_address_forks: BTreeMap::new(), genesis_time: 0u64, seconds_per_slot: 1u64, is_taiko, @@ -204,7 +204,7 @@ impl ChainSpec { &self.eip_1559_constants } - fn spec_id(&self, block_no: BlockNumber, timestamp: u64) -> Option { + pub fn spec_id(&self, block_no: BlockNumber, timestamp: u64) -> Option { for (spec_id, fork) in self.hard_forks.iter().rev() { if fork.active(block_no, timestamp) { return Some(*spec_id); @@ -213,6 +213,26 @@ impl ChainSpec { None } + pub fn get_fork_verifier_address( + &self, + block_num: u64, + verifier_type: VerifierType, + ) -> Result
{ + // fall down to the first fork that is active as default + for (spec_id, fork) in self.hard_forks.iter().rev() { + if fork.active(block_num, 0u64) { + if let Some(fork_verifier) = self.verifier_address_forks.get(&spec_id) { + return fork_verifier + .get(&verifier_type) + .unwrap() + .ok_or_else(|| anyhow!("Verifier address not found")); + } + } + } + + Err(anyhow!("fork verifier is not active")) + } + pub fn is_taiko(&self) -> bool { self.is_taiko } @@ -249,6 +269,8 @@ impl std::fmt::Display for Network { #[cfg(test)] mod tests { + use reth_primitives::address; + use super::*; #[test] @@ -265,6 +287,77 @@ mod tests { ); } + #[test] + fn raiko_active_fork() { + let eth_mainnet_spec = SupportedChainSpecs::default() + .get_chain_spec(&Network::Ethereum.to_string()) + .unwrap(); + assert_eq!( + eth_mainnet_spec.active_fork(0, 0).unwrap(), + SpecId::FRONTIER + ); + assert_eq!( + eth_mainnet_spec.active_fork(15_537_394, 0).unwrap(), + SpecId::MERGE + ); + assert_eq!( + eth_mainnet_spec.active_fork(17_034_869, 0).unwrap(), + SpecId::MERGE + ); + assert_eq!( + eth_mainnet_spec.active_fork(17_034_870, 0).unwrap(), + SpecId::SHANGHAI + ); + + let taiko_mainnet_spec = SupportedChainSpecs::default() + .get_chain_spec(&Network::TaikoMainnet.to_string()) + .unwrap(); + assert_eq!( + taiko_mainnet_spec.active_fork(0, 0).unwrap(), + SpecId::HEKLA + ); + assert_eq!( + taiko_mainnet_spec.active_fork(999998, 0).unwrap(), + SpecId::HEKLA + ); + assert_eq!( + taiko_mainnet_spec.active_fork(999999, 0).unwrap(), + SpecId::ONTAKE + ); + } + + #[test] + fn forked_verifier_address() { + let eth_mainnet_spec = SupportedChainSpecs::default() + .get_chain_spec(&Network::Ethereum.to_string()) + .unwrap(); + let verifier_address = eth_mainnet_spec + .get_fork_verifier_address(15_537_394, VerifierType::SGX) + .unwrap(); + assert_eq!( + verifier_address, + address!("532efbf6d62720d0b2a2bb9d11066e8588cae6d9") + ); + + let hekla_mainnet_spec = SupportedChainSpecs::default() + .get_chain_spec(&Network::TaikoA7.to_string()) + .unwrap(); + let verifier_address = hekla_mainnet_spec + .get_fork_verifier_address(12345, VerifierType::SGX) + .unwrap(); + assert_eq!( + verifier_address, + address!("532efbf6d62720d0b2a2bb9d11066e8588cae6d9") + ); + let verifier_address = hekla_mainnet_spec + .get_fork_verifier_address(15_537_394, VerifierType::SGX) + .unwrap(); + assert_eq!( + verifier_address, + address!("f6d620d0b2a2bb9d11066e8532efb72588cae6d9") + ); + } + #[ignore] #[test] fn serde_chain_spec() { @@ -288,11 +381,14 @@ mod tests { l2_contract: None, rpc: "".to_string(), beacon_rpc: None, - verifier_address: BTreeMap::from([ - (VerifierType::SGX, Some(Address::default())), - (VerifierType::SP1, None), - (VerifierType::RISC0, Some(Address::default())), - ]), + verifier_address_forks: BTreeMap::from([( + SpecId::FRONTIER, + BTreeMap::from([ + (VerifierType::SGX, Some(Address::default())), + (VerifierType::SP1, None), + (VerifierType::RISC0, Some(Address::default())), + ]), + )]), genesis_time: 0u64, seconds_per_slot: 1u64, is_taiko: false, diff --git a/lib/src/input.rs b/lib/src/input.rs index c96155fd..bc58fdab 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -73,6 +73,22 @@ impl BlockProposedFork { _ => false, } } + + pub fn block_number(&self) -> u64 { + match self { + BlockProposedFork::Hekla(block) => block.meta.id, + BlockProposedFork::Ontake(block) => block.meta.id, + _ => 0, + } + } + + pub fn block_timestamp(&self) -> u64 { + match self { + BlockProposedFork::Hekla(block) => block.meta.timestamp, + BlockProposedFork::Ontake(block) => block.meta.timestamp, + _ => 0, + } + } } #[serde_as] diff --git a/lib/src/protocol_instance.rs b/lib/src/protocol_instance.rs index 2f365e20..e7672898 100644 --- a/lib/src/protocol_instance.rs +++ b/lib/src/protocol_instance.rs @@ -28,29 +28,27 @@ impl BlockMetaDataFork { fn from(input: &GuestInput, header: &Header, tx_list_hash: B256) -> Self { match &input.taiko.block_proposed { BlockProposedFork::Nothing => unimplemented!("no block proposed"), - BlockProposedFork::Hekla(block_proposed) => { - BlockMetaDataFork::Hekla(BlockMetadata { - l1Hash: input.taiko.l1_header.hash_slow(), - difficulty: block_proposed.meta.difficulty, - blobHash: tx_list_hash, - extraData: bytes_to_bytes32(&header.extra_data).into(), - depositsHash: keccak(Vec::::new().abi_encode()).into(), - coinbase: header.beneficiary, - id: header.number, - gasLimit: (header.gas_limit - - if input.chain_spec.is_taiko() { - ANCHOR_GAS_LIMIT - } else { - 0 - }) as u32, - timestamp: header.timestamp, - l1Height: input.taiko.l1_header.number, - minTier: block_proposed.meta.minTier, - blobUsed: block_proposed.meta.blobUsed, - parentMetaHash: block_proposed.meta.parentMetaHash, - sender: block_proposed.meta.sender, - }) - } + BlockProposedFork::Hekla(block_proposed) => BlockMetaDataFork::Hekla(BlockMetadata { + l1Hash: input.taiko.l1_header.hash_slow(), + difficulty: block_proposed.meta.difficulty, + blobHash: tx_list_hash, + extraData: bytes_to_bytes32(&header.extra_data).into(), + depositsHash: keccak(Vec::::new().abi_encode()).into(), + coinbase: header.beneficiary, + id: header.number, + gasLimit: (header.gas_limit + - if input.chain_spec.is_taiko() { + ANCHOR_GAS_LIMIT + } else { + 0 + }) as u32, + timestamp: header.timestamp, + l1Height: input.taiko.l1_header.number, + minTier: block_proposed.meta.minTier, + blobUsed: block_proposed.meta.blobUsed, + parentMetaHash: block_proposed.meta.parentMetaHash, + sender: block_proposed.meta.sender, + }), BlockProposedFork::Ontake(block_proposed_v2) => { BlockMetaDataFork::Ontake(BlockMetadataV2 { anchorBlockHash: input.taiko.l1_header.hash_slow(), @@ -177,12 +175,9 @@ impl ProtocolInstance { ); } - let verifier_address = (*input + let verifier_address = input .chain_spec - .verifier_address - .get(&proof_type) - .unwrap_or(&None)) - .unwrap_or_default(); + .get_fork_verifier_address(input.taiko.block_proposed.block_number(), proof_type)?; let pi = ProtocolInstance { transition: Transition { @@ -202,7 +197,8 @@ impl ProtocolInstance { // Sanity check if input.chain_spec.is_taiko() { ensure!( - pi.block_metadata.match_block_proposal(&input.taiko.block_proposed), + pi.block_metadata + .match_block_proposal(&input.taiko.block_proposed), format!( "block hash mismatch, expected: {:?}, got: {:?}", input.taiko.block_proposed, pi.block_metadata diff --git a/provers/sgx/setup/src/app_args.rs b/provers/sgx/setup/src/app_args.rs index 459fd04a..c67e4ad7 100644 --- a/provers/sgx/setup/src/app_args.rs +++ b/provers/sgx/setup/src/app_args.rs @@ -37,6 +37,10 @@ pub struct BootstrapArgs { #[arg(long, default_value = "taiko_a7")] pub network: String, + + /// block_num to get the verifier address for different fork + #[arg(long, default_value = "0")] + pub block_num: u64, } fn get_default_raiko_user_config_path(subdir: &str) -> PathBuf { diff --git a/provers/sgx/setup/src/setup_bootstrap.rs b/provers/sgx/setup/src/setup_bootstrap.rs index 2ae7a419..1ea49c32 100644 --- a/provers/sgx/setup/src/setup_bootstrap.rs +++ b/provers/sgx/setup/src/setup_bootstrap.rs @@ -59,15 +59,15 @@ pub(crate) async fn setup_bootstrap( // clean check file remove_instance_id(&config_dir)?; let bootstrap_proof = bootstrap(secret_dir, gramine_cmd()).await?; + let verifier_address = taiko_chain_spec.get_fork_verifier_address( + bootstrap_args.block_num, + VerifierType::SGX, + )?; let register_id = register_sgx_instance( &bootstrap_proof.quote, &l1_chain_spec.rpc, l1_chain_spec.chain_id, - taiko_chain_spec - .verifier_address - .get(&VerifierType::SGX) - .unwrap() - .unwrap(), + verifier_address, ) .await .map_err(|e| anyhow::Error::msg(e.to_string()))?;