Skip to content

Commit

Permalink
proving blocks with reth fully working (with some caveats)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brechtpd committed Jun 14, 2024
1 parent 07a83cb commit 80adeea
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 152 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

4 changes: 1 addition & 3 deletions host/src/preflight.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use alloy_consensus::{
SignableTransaction, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEnvelope, TxLegacy,
};
use alloy_consensus::TxEnvelope;
pub use alloy_primitives::*;
use alloy_provider::{Provider, ReqwestProvider};
use alloy_rpc_types::{Block, BlockTransactions, Filter, Transaction as AlloyRpcTransaction};
Expand Down
93 changes: 11 additions & 82 deletions host/src/provider/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ use alloy_primitives::Bytes;
use raiko_lib::{builder::OptimisticDatabase, consts::ChainSpec, mem_db::MemDb};
use raiko_primitives::{Address, B256, U256};
use reth_primitives::Header;
use reth_provider::{
AccountReader, BlockHashReader, ProviderError, StateProvider, StateRootProvider,
};
use reth_provider::ProviderError;
use revm::{
db::BundleState,
primitives::{Account, AccountInfo, Bytecode, HashMap},
Database, DatabaseCommit, DatabaseRef,
Database, DatabaseCommit,
};
use tokio::runtime::Handle;

Expand Down Expand Up @@ -164,7 +162,6 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
type Error = ProviderError;

fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
//println!("address: {:?}", address);
// Check if the account is in the current database.
if let Ok(db_result) = self.current_db.basic(address) {
return Ok(db_result);
Expand Down Expand Up @@ -199,11 +196,11 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
self.async_executor
.block_on(self.provider.get_accounts(&[address]))
})
.map_err(|e| ProviderError::BestBlockNotFound)?
.map_err(|e| ProviderError::RPC(e.to_string()))?
.first()
.cloned()
.ok_or(HostError::RPC("No account".to_owned()))
.map_err(|e| ProviderError::BestBlockNotFound)?;
.map_err(|e| ProviderError::RPC(e.to_string()))?;

// Insert the account into the initial database.
self.initial_db
Expand Down Expand Up @@ -235,18 +232,18 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
}

// Makes sure the account is also always loaded
self.initial_db.basic(address).expect("Brecht");
self.initial_db.basic(address)?;

// Fetch the storage value
let value = tokio::task::block_in_place(|| {
self.async_executor
.block_on(self.provider.get_storage_values(&[(address, index)]))
})
.map_err(|e| ProviderError::BestBlockNotFound)?
.map_err(|e| ProviderError::RPC(e.to_string()))?
.first()
.copied()
.ok_or(HostError::RPC("No storage value".to_owned()))
.map_err(|e| ProviderError::BestBlockNotFound)?;
.map_err(|e| ProviderError::RPC(e.to_string()))?;
self.initial_db
.insert_account_storage(&address, index, value);
Ok(value)
Expand All @@ -256,7 +253,7 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
let block_number: u64 = number
.try_into()
.map_err(|_| HostError::Conversion("Could not convert U256 to u64".to_owned()))
.map_err(|e| ProviderError::BestBlockNotFound)?;
.map_err(|e| ProviderError::RPC(e.to_string()))?;

// Check if the block hash is in the current database.
if let Ok(block_hash) = self.initial_db.block_hash(number) {
Expand All @@ -280,14 +277,14 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
self.async_executor
.block_on(self.provider.get_blocks(&[(block_number, false)]))
})
.map_err(|e| ProviderError::BestBlockNotFound)?
.map_err(|e| ProviderError::RPC(e.to_string()))?
.first()
.ok_or(HostError::RPC("No block".to_owned()))
.map_err(|e| ProviderError::BestBlockNotFound)?
.map_err(|e| ProviderError::RPC(e.to_string()))?
.header
.hash
.ok_or_else(|| HostError::RPC("No block hash".to_owned()))
.map_err(|e| ProviderError::BestBlockNotFound)?
.map_err(|e| ProviderError::RPC(e.to_string()))?
.0
.into();
self.initial_db.insert_block_hash(block_number, block_hash);
Expand All @@ -299,74 +296,6 @@ impl<BDP: BlockDataProvider> Database for ProviderDb<BDP> {
}
}

impl<BDP: BlockDataProvider> DatabaseRef for ProviderDb<BDP> {
type Error = ProviderError;

fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
//println!("address: {}", address);

// Fetch the account
let account = &tokio::task::block_in_place(|| {
self.async_executor
.block_on(self.provider.get_accounts(&[address]))
})
.expect("brecht")
.first()
.cloned()
.ok_or(HostError::RPC("No account".to_owned()))
.expect("brecht");

// Insert the account into the initial database.
Ok(Some(account.clone()))
//self.basic(address).map_err(|err| ProviderError::FsPathError("hi".into()))
}

fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, Self::Error> {
// We use basic_ref to get the code from the provider.
unimplemented!()
}

fn storage_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
//println!("storage: {} {}", address, index);

// Fetch the storage value
let value = tokio::task::block_in_place(|| {
self.async_executor
.block_on(self.provider.get_storage_values(&[(address, index)]))
})
.expect("brecht")
.first()
.copied()
.ok_or(HostError::RPC("No storage value".to_owned()))
.expect("brecht");
Ok(value)
}

fn block_hash_ref(&self, number: U256) -> Result<B256, Self::Error> {
let block_number: u64 = number
.try_into()
.map_err(|_| HostError::Conversion("Could not convert U256 to u64".to_owned()))
.expect("brecht");

// Get the block hash from the provider.
let block_hash = tokio::task::block_in_place(|| {
self.async_executor
.block_on(self.provider.get_blocks(&[(block_number, false)]))
})
.expect("brecht")
.first()
.ok_or(HostError::RPC("No block".to_owned()))
.expect("brecht")
.header
.hash
.ok_or_else(|| HostError::RPC("No block hash".to_owned()))
.expect("brecht")
.0
.into();
Ok(block_hash)
}
}

impl<BDP: BlockDataProvider> DatabaseCommit for ProviderDb<BDP> {
fn commit(&mut self, changes: HashMap<Address, Account>) {
self.current_db.commit(changes);
Expand Down
85 changes: 41 additions & 44 deletions lib/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::{any::Any, mem};
use core::mem;
use std::sync::Arc;

use crate::utils::generate_transactions;
use crate::{
Expand All @@ -8,24 +9,21 @@ use crate::{
mem_db::{AccountState, DbAccount, MemDb},
};
use alloy_consensus::{Signed, Transaction, TxEnvelope};
use alloy_primitives::uint;
use alloy_rpc_types::{ConversionError, Parity, Signature, Transaction as AlloyTransaction};
use alloy_rpc_types::{ConversionError, Parity, Transaction as AlloyTransaction};
use anyhow::{bail, Context, Error, Result};
use raiko_primitives::{
keccak::keccak,
mpt::{MptNode, StateAccount},
RlpBytes,
};
use raiko_primitives::{keccak::keccak, mpt::StateAccount};
use raiko_primitives::{keccak::KECCAK_EMPTY, Bytes};
use reth_evm::execute::EthBlockOutput;
use reth_evm::execute::Executor;
use reth_evm_ethereum::execute::EthExecutorProvider;
use reth_evm_ethereum::taiko::TaikoData;
use reth_interfaces::executor::BlockValidationError;
use reth_primitives::transaction::Signature as RethSignature;
use reth_primitives::{
BlockBody, ChainSpecBuilder, Header, Receipts, TransactionSigned, B256, MAINNET, TAIKO_A7, U256,
BlockBody, ChainSpecBuilder, Header, TransactionSigned, B256, HOLESKY, MAINNET, TAIKO_A7,
TAIKO_MAINNET, U256,
};
use reth_provider::{BundleStateWithReceipts, OriginalValuesKnown, ProviderError};
use reth_provider::ProviderError;
use revm::primitives::{AccountInfo, Bytecode, HashMap, SpecId};
use revm::{db::BundleState, Database, DatabaseCommit};

Expand Down Expand Up @@ -112,22 +110,25 @@ impl<DB: Database<Error = ProviderError> + DatabaseCommit + OptimisticDatabase>
/// Executes all input transactions.
pub fn execute_transactions(&mut self, optimistic: bool) -> Result<()> {
let chain_spec = &self.input.chain_spec;
let chain_id = chain_spec.chain_id();
let is_taiko = chain_spec.is_taiko();

let total_difficulty = U256::ZERO;
let reth_chain_spec = if is_taiko {
ChainSpecBuilder::default()
.chain(TAIKO_A7.chain)
.genesis(TAIKO_A7.genesis.clone())
.shanghai_activated()
.build()
} else {
ChainSpecBuilder::default()
.chain(MAINNET.chain)
.genesis(MAINNET.genesis.clone())
.cancun_activated()
.build()
let reth_chain_spec = match chain_spec.name.as_str() {
"taiko_a7" => TAIKO_A7.clone(),
"taiko_mainnet" => TAIKO_MAINNET.clone(),
"ethereum" => {
//MAINNET.clone()
// TODO(Brecht): for some reason using the spec directly doesn't work
Arc::new(
ChainSpecBuilder::default()
.chain(MAINNET.chain)
.genesis(MAINNET.genesis.clone())
.cancun_activated()
.build(),
)
}
"holesky" => HOLESKY.clone(),
_ => unimplemented!(),
};

let header = self.header.as_mut().expect("Header is not initialized");
Expand All @@ -140,8 +141,6 @@ impl<DB: Database<Error = ProviderError> + DatabaseCommit + OptimisticDatabase>
bail!("Invalid protocol version: expected >= {MIN_SPEC_ID:?}, got {spec_id:?}")
}

//println!("spec_id: {spec_id:?}");

// generate the transactions from the tx list
// For taiko blocks, insert the anchor tx as the first transaction
let anchor_tx = if is_taiko {
Expand All @@ -161,12 +160,8 @@ impl<DB: Database<Error = ProviderError> + DatabaseCommit + OptimisticDatabase>
to_alloy_transaction(&tx).expect("can't convert to alloy");
alloy_transactions.push(alloy_tx);
}
//println!("transactions: {:?}", alloy_transactions);

let mut block = self.input.block.clone();

//println!("tx_list: {:?}, block: {:?}", alloy_transactions.len(), block.body.len());

// Convert alloy transactions to reth transactions and set them on the block
block.body = alloy_transactions
.into_iter()
Expand All @@ -191,25 +186,27 @@ impl<DB: Database<Error = ProviderError> + DatabaseCommit + OptimisticDatabase>

let executor = EthExecutorProvider::ethereum(reth_chain_spec.clone().into())
.eth_executor(self.db.take().unwrap())
.taiko_data(TaikoData {
l1_header: self.input.taiko.l1_header.clone(),
parent_header: self.input.parent_header.clone(),
l2_contract: self.input.chain_spec.l2_contract.unwrap_or_default(),
})
.optimistic(optimistic);
let EthBlockOutput {
state,
receipts: _,
gas_used,
db: full_state,
} = executor
.execute(
(
&block
.clone()
.with_recovered_senders()
.ok_or(BlockValidationError::SenderRecoveryError)
.expect("brecht"),
total_difficulty.into(),
)
.into(),
} = executor.execute(
(
&block
.clone()
.with_recovered_senders()
.ok_or(BlockValidationError::SenderRecoveryError)?,
total_difficulty.into(),
)
.expect("brecht");
.into(),
)?;

self.db = Some(full_state.database);

Expand Down Expand Up @@ -507,13 +504,13 @@ pub fn to_alloy_transaction(tx: &TxEnvelope) -> Result<AlloyTransaction, Error>
gas: tx.tx().gas_limit(),
max_fee_per_gas: Some(tx.tx().tx().max_fee_per_gas),
max_priority_fee_per_gas: Some(tx.tx().tx().max_priority_fee_per_gas),
max_fee_per_blob_gas: None,
max_fee_per_blob_gas: Some(tx.tx().tx().max_fee_per_blob_gas),
input: tx.tx().input().to_owned().into(),
signature: Some(to_alloy_signature(get_sig(tx))),
chain_id: tx.tx().chain_id(),
blob_versioned_hashes: None,
blob_versioned_hashes: Some(tx.tx().tx().blob_versioned_hashes.clone()),
access_list: Some(tx.tx().tx().access_list.clone()),
transaction_type: Some(3),
transaction_type: Some(tx.tx().tx_type() as u8),
..Default::default()
};
Ok(alloy_tx)
Expand Down
2 changes: 1 addition & 1 deletion lib/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use serde_with::serde_as;

use reth_primitives::{Block as RethBlock, Header};

use crate::consts::ChainSpec;
#[cfg(not(feature = "std"))]
use crate::no_std::*;
use crate::{consts::ChainSpec, serde_with::RlpHexBytes};

/// Represents the state of an account's storage.
/// The storage trie together with the used storage slots allow us to reconstruct all the
Expand Down
1 change: 0 additions & 1 deletion lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pub mod utils;

#[cfg(not(target_os = "zkvm"))]
mod time {
pub use core::ops::AddAssign;
pub use std::time::{Duration, Instant};
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/mem_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use anyhow::anyhow;
use raiko_primitives::{Address, B256, U256};
use reth_provider::ProviderError;
use revm::{
db::{AccountStatus, BundleState},
db::BundleState,
primitives::{Account, AccountInfo, Bytecode},
Database, DatabaseCommit,
};
Expand Down Expand Up @@ -272,7 +272,7 @@ impl Database for MemDb {
&number
)
})
.expect("Brecht");
.expect("block hash not found");
self.block_hashes
.get(&block_no)
.copied()
Expand Down
Loading

0 comments on commit 80adeea

Please sign in to comment.