Skip to content

Commit

Permalink
TaikoProvider, TaikoSystemInfo, preflight
Browse files Browse the repository at this point in the history
  • Loading branch information
CeciliaZ030 committed Feb 11, 2024
1 parent 1e9ffe2 commit f3b6a0f
Show file tree
Hide file tree
Showing 13 changed files with 491 additions and 50 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ zeth-primitives = { path = "../primitives", features = ["revm", "ethers"] }
alloy-primitives = { version = "0.6", default-features = false, features = [
"rlp",
] }
rlp = { version = "0.5.2", default-features = false, optional = true}


[target.'cfg(not(target_os = "zkvm"))'.dependencies]
chrono = { version = "0.4", default-features = false }
Expand All @@ -35,6 +37,6 @@ bincode = "1.3"
serde_with = "3.1"

[features]
default = ["taiko"]
taiko = ["revm/taiko"]
default = ["taiko", "revm/taiko"]
taiko = ["revm/taiko", "dep:rlp"]
optimism = ["revm/optimism"]
4 changes: 2 additions & 2 deletions lib/src/builder/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use super::BlockBuilder;
pub(super) mod ethereum;
#[cfg(feature = "optimism")]
pub(super) mod optimism;
#[cfg(feature = "taiko")]
pub (super) mod taiko;
// #[cfg(feature = "taiko")]
pub(super) mod taiko;

pub trait TxExecStrategy<E: TxEssence> {
fn execute_transactions<D>(block_builder: BlockBuilder<D, E>) -> Result<BlockBuilder<D, E>>
Expand Down
140 changes: 121 additions & 19 deletions lib/src/builder/execute/taiko.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,37 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use core::{fmt::Debug, mem::take};
use core::str::from_utf8;
use core::{fmt::Debug, mem::take, str::from_utf8};

use alloy_primitives::hex::decode;
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{anyhow, bail, ensure, Context, Result};
use ethers_core::types::Transaction as EthersTransaction;
#[cfg(not(target_os = "zkvm"))]
use log::debug;
use revm::taiko;
use log::info;
use revm::{
interpreter::Host,
primitives::{Address, ResultAndState, SpecId, TransactTo, TxEnv},
Database, DatabaseCommit, Evm,
taiko, Database, DatabaseCommit, Evm,
};
use rlp::{Decodable, DecoderError, Rlp};
use ruint::aliases::U256;
use zeth_primitives::{
receipt::Receipt,
transactions::{
block::Header, receipt::Receipt, transactions::{
ethereum::{EthereumTxEssence, TransactionKind},
TxEssence,
},
trie::MptNode,
Bloom, Bytes, RlpBytes,
}, trie::MptNode, Bloom, Bytes, RlpBytes
};
use crate::consts::ChainSpec;
use crate::taiko::decode_anchor;

use super::{ethereum, TxExecStrategy};
use crate::{builder::BlockBuilder, consts, guest_mem_forget};
use crate::{
builder::{prepare::EthHeaderPrepStrategy, BlockBuilder, TaikoStrategy}, consts::{self, ChainSpec}, guest_mem_forget,
host::{preflight::{new_preflight_input, Data, Preflight},
provider::{new_provider, BlockQuery}, provider_db::ProviderDb}, taiko::{consts::{MAX_TX_LIST, MAX_TX_LIST_BYTES}, decode_anchor, provider::TaikoProvider}
};

/// Minimum supported protocol version: Bedrock (Block no. 105235063).
const MIN_SPEC_ID: SpecId = SpecId::KATLA; //Todo: change
const MIN_SPEC_ID: SpecId = SpecId::SHANGHAI /*change*/;

pub struct TkoTxExecStrategy {}

Expand Down Expand Up @@ -223,10 +224,8 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
receipt_trie
.insert_rlp(&trie_key, receipt)
.context("failed to insert receipt")?;

}



// Update result header with computed values
header.transactions_root = tx_trie.hash();
header.receipts_root = receipt_trie.hash();
Expand All @@ -251,7 +250,110 @@ pub fn fill_eth_tx_env(
// claim the anchor
tx_env.taiko.is_anchor = is_anchor;
// set the treasury address
tx_env.taiko.treasury = l2_chain_spec.l2_contract.unwrap();
tx_env.taiko.treasury = *crate::taiko::consts::testnet::L2_CONTRACT;

ethereum::fill_eth_tx_env(tx_env, essence, caller);
}

impl Preflight<EthereumTxEssence> for TaikoStrategy {
fn run_preflight(
chain_spec: ChainSpec,
cache_path: Option<std::path::PathBuf>,
rpc_url: Option<String>,
block_no: u64,
) -> Result<crate::host::preflight::Data<EthereumTxEssence>> {
let mut tp = TaikoProvider::new(None, None, cache_path, rpc_url)?;

// Fetch the parent block
let parent_block = tp.l2_provider.get_partial_block(&BlockQuery {
block_no: block_no - 1,
})?;

info!(
"Initial block: {:?} ({:?})",
parent_block.number.unwrap(),
parent_block.hash.unwrap()
);
let parent_header: Header = parent_block.try_into().context("invalid parent block")?;

// Fetch the target block
let mut block = tp.l2_provider.get_full_block(&BlockQuery { block_no })?;
let (anchor_tx, anchor_call) = tp.get_anchor(&block)?;
let (proposal_call, _) = tp.get_proposal(anchor_call.l1Height, block_no)?;

let mut l2_tx_list: Vec<EthersTransaction> = rlp_decode_list(&proposal_call.txList)?;
ensure!(proposal_call.txList.len() <= MAX_TX_LIST_BYTES, "tx list bytes must be not more than MAX_TX_LIST_BYTES");
ensure!(l2_tx_list.len() <= MAX_TX_LIST, "tx list size must be not more than MAX_TX_LISTs");

// TODO(Cecilia): reset to empty necessary if wrong?
// tracing::log for particular reason instead of uniform error handling?
// txs.clear();

info!(
"Inserted anchor {:?} in tx_list decoded from {:?}",
anchor_tx.hash,
proposal_call.txList
);
l2_tx_list.insert(0, anchor_tx);
block.transactions = l2_tx_list;

info!(
"Final block number: {:?} ({:?})",
block.number.unwrap(),
block.hash.unwrap()
);
info!("Transaction count: {:?}", block.transactions.len());


// Create the provider DB
let provider_db = ProviderDb::new(tp.l2_provider, parent_header.number);

// Create the input data
let input = new_preflight_input(block.clone(), parent_header.clone())?;
let transactions = input.transactions.clone();
let withdrawals = input.withdrawals.clone();

// Create the block builder, run the transactions and extract the DB
let mut builder = BlockBuilder::new(&chain_spec, input)
.with_db(provider_db)
.prepare_header::<EthHeaderPrepStrategy>()?
.execute_transactions::<TkoTxExecStrategy::TxExecStrategy>()?;
let provider_db = builder.mut_db().unwrap();

info!("Gathering inclusion proofs ...");

// Gather inclusion proofs for the initial and final state
let parent_proofs = provider_db.get_initial_proofs()?;
let proofs = provider_db.get_latest_proofs()?;

// Gather proofs for block history
let ancestor_headers = provider_db.get_ancestor_headers()?;

info!("Saving provider cache ...");

// Save the provider cache
provider_db.get_provider().save()?;

info!("Provider-backed execution is Done!");

Ok(Data {
db: provider_db.get_initial_db().clone(),
parent_header,
parent_proofs,
header: block.try_into().context("invalid block")?,
transactions,
withdrawals,
proofs,
ancestor_headers,
})

}
}

fn rlp_decode_list<T>(bytes: &[u8]) -> Result<Vec<T>, DecoderError>
where
T: Decodable,
{
let rlp = Rlp::new(bytes);
rlp.as_list()
}
15 changes: 7 additions & 8 deletions lib/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ use zeth_primitives::{
transactions::{ethereum::EthereumTxEssence, optimism::OptimismTxEssence, TxEssence},
trie::MptNode,
};

#[cfg(feature = "optimism")]
pub use self::execute::optimism::OpTxExecStrategy;
// #[cfg(feature = "taiko")]
pub use self::execute::taiko::TkoTxExecStrategy;
use crate::{
builder::{
execute::{ethereum::EthTxExecStrategy, TxExecStrategy},
Expand All @@ -31,12 +36,6 @@ use crate::{
mem_db::MemDb,
};

#[cfg(feature = "optimism")]
pub use self::execute::optimism::OpTxExecStrategy;

#[cfg(feature = "taiko")]
pub use self::execute::taiko::TkoTxExecStrategy;

mod execute;
mod finalize;
mod initialize;
Expand Down Expand Up @@ -150,9 +149,9 @@ impl BlockBuilderStrategy for OptimismStrategy {
}

/// The [BlockBuilderStrategy] for building an Optimism block.
#[cfg(feature = "taiko")]
// #[cfg(feature = "taiko")]
pub struct TaikoStrategy {}
#[cfg(feature = "taiko")]
// #[cfg(feature = "taiko")]
impl BlockBuilderStrategy for TaikoStrategy {
type TxEssence = EthereumTxEssence;
type DbInitStrategy = MemDbInitStrategy;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ pub static ETH_MAINNET_CHAIN_SPEC: Lazy<ChainSpec> = Lazy::new(|| {
});

/// The Taiko mainnet specification.
#[cfg(feature = "taiko")]
// #[cfg(feature = "taiko")]
pub static TKO_MAINNET_CHAIN_SPEC: Lazy<ChainSpec> = Lazy::new(|| {
ChainSpec {
chain_id: 1,
hard_forks: BTreeMap::from([
(SpecId::SHANGHAI, ForkCondition::Block(0)),
(SpecId::KATLA, ForkCondition::Block(0)),
(SpecId::SHANGHAI /*change*/, ForkCondition::Block(0)),
// previous versions not supported
(SpecId::CANCUN, ForkCondition::TBD),
]),
Expand All @@ -82,7 +82,7 @@ pub static TKO_MAINNET_CHAIN_SPEC: Lazy<ChainSpec> = Lazy::new(|| {
}
});

#[cfg(feature = "taiko")]
// #[cfg(feature = "taiko")]
pub use crate::taiko::consts::testnet::*;

/// The Optimism mainnet specification.
Expand Down
3 changes: 2 additions & 1 deletion lib/src/host/preflight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ where
}
}

fn new_preflight_input<E>(
///
pub fn new_preflight_input<E>(
block: EthersBlock<EthersTransaction>,
parent_header: Header,
) -> Result<Input<E>>
Expand Down
4 changes: 2 additions & 2 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate core;
extern crate alloc;
extern crate core;

#[cfg(not(target_os = "zkvm"))]
pub mod host;
Expand All @@ -24,7 +24,7 @@ pub mod input;
pub mod mem_db;
pub mod optimism;

#[cfg(feature = "taiko")]
// #[cfg(feature = "taiko")]
pub mod taiko;

mod utils;
Expand Down
39 changes: 39 additions & 0 deletions lib/src/taiko/consts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use core::str::FromStr;

use alloy_primitives::{uint, Address, U256};
use anyhow::{Result, anyhow, bail};
use once_cell::sync::Lazy;
use zeth_primitives::transactions::EthereumTransaction;

pub static ANCHOR_GAS_LIMIT: u64 = 250_000;
pub static MAX_TX_LIST: usize = 79;
Expand Down Expand Up @@ -79,3 +81,40 @@ pub mod internal_devnet_b {
.expect("invalid l2 signal service")
});
}

static GX1: Lazy<U256> =
Lazy::new(|| uint!(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798_U256));
static N: Lazy<U256> =
Lazy::new(|| uint!(0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141_U256));
static GX1_MUL_PRIVATEKEY: Lazy<U256> =
Lazy::new(|| uint!(0x4341adf5a780b4a87939938fd7a032f6e6664c7da553c121d3b4947429639122_U256));
static GX2: Lazy<U256> =
Lazy::new(|| uint!(0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5_U256));


/// check the anchor signature with fixed K value
pub fn check_anchor_signature(anchor: &EthereumTransaction) -> Result<()> {
let sign = &anchor.signature;
if sign.r == *GX1 {
return Ok(());
}
let msg_hash = anchor.essence.signing_hash();
let msg_hash: U256 = msg_hash.into();
if sign.r == *GX2 {
// when r == GX2 require s == 0 if k == 1
// alias: when r == GX2 require N == msg_hash + *GX1_MUL_PRIVATEKEY
if *N != msg_hash + *GX1_MUL_PRIVATEKEY {
bail!(
"r == GX2, but N != msg_hash + *GX1_MUL_PRIVATEKEY, N: {}, msg_hash: {}, *GX1_MUL_PRIVATEKEY: {}",
*N, msg_hash, *GX1_MUL_PRIVATEKEY
);
}
return Ok(());
}
Err(anyhow!(
"r != *GX1 && r != GX2, r: {}, *GX1: {}, GX2: {}",
sign.r,
*GX1,
*GX2
))
}
Loading

0 comments on commit f3b6a0f

Please sign in to comment.