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

Simplify BatcherDb #81

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
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
25 changes: 7 additions & 18 deletions host/src/bin/op-derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ impl RpcDb {
}

impl BatcherDb for RpcDb {
fn validate(&self) -> Result<()> {
Ok(())
}

fn get_full_op_block(&mut self, block_no: u64) -> Result<BlockInput<OptimismTxEssence>> {
let mut provider = new_provider(
op_cache_path(&self.cache, block_no),
Expand Down Expand Up @@ -390,7 +394,7 @@ impl BatcherDb for RpcDb {
Ok(header)
}

fn get_full_eth_block(&mut self, block_no: u64) -> Result<BlockInput<EthereumTxEssence>> {
fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput<EthereumTxEssence>> {
let query = BlockQuery { block_no };
let mut provider = new_provider(
eth_cache_path(&self.cache, block_no),
Expand Down Expand Up @@ -430,23 +434,8 @@ impl BatcherDb for RpcDb {
receipts,
}
};
self.mem_db.full_eth_block.insert(block_no, block.clone());
self.mem_db.full_eth_block.insert(block_no, block);
provider.save()?;
Ok(block)
}

fn get_eth_block_header(&mut self, block_no: u64) -> Result<Header> {
let mut provider = new_provider(
eth_cache_path(&self.cache, block_no),
self.eth_rpc_url.clone(),
)?;
let header: Header = provider
.get_partial_block(&BlockQuery { block_no })?
.try_into()?;
self.mem_db
.eth_block_header
.insert(block_no, header.clone());
provider.save()?;
Ok(header)
self.mem_db.get_full_eth_block(block_no)
}
}
161 changes: 85 additions & 76 deletions lib/src/optimism/batcher_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ pub struct BlockInput<E: TxEssence> {
}

pub trait BatcherDb {
fn validate(&self) -> Result<()>;
fn get_full_op_block(&mut self, block_no: u64) -> Result<BlockInput<OptimismTxEssence>>;
fn get_op_block_header(&mut self, block_no: u64) -> Result<Header>;
fn get_full_eth_block(&mut self, block_no: u64) -> Result<BlockInput<EthereumTxEssence>>;
fn get_eth_block_header(&mut self, block_no: u64) -> Result<Header>;
fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput<EthereumTxEssence>>;
}

#[derive(Debug, Clone, Deserialize, Serialize)]
Expand Down Expand Up @@ -72,28 +72,92 @@ impl Default for MemDb {
}

impl BatcherDb for MemDb {
fn get_full_op_block(&mut self, block_no: u64) -> Result<BlockInput<OptimismTxEssence>> {
let op_block = self.full_op_block.remove(&block_no).unwrap();
assert_eq!(block_no, op_block.block_header.number);

// Validate tx list
{
let mut tx_trie = MptNode::default();
for (tx_no, tx) in op_block.transactions.iter().enumerate() {
let trie_key = tx_no.to_rlp();
tx_trie.insert_rlp(&trie_key, tx)?;
fn validate(&self) -> Result<()> {
for (block_no, op_block) in &self.full_op_block {
ensure!(
*block_no == op_block.block_header.number,
"Block number mismatch"
);

// Validate tx list
{
let mut tx_trie = MptNode::default();
for (tx_no, tx) in op_block.transactions.iter().enumerate() {
let trie_key = tx_no.to_rlp();
tx_trie.insert_rlp(&trie_key, tx)?;
}
ensure!(
tx_trie.hash() == op_block.block_header.transactions_root,
"Invalid op block transaction data!"
);
}

// Validate receipts
ensure!(
tx_trie.hash() == op_block.block_header.transactions_root,
"Invalid op block transaction data!"
op_block.receipts.is_none(),
"Op blocks should not contain receipts"
);
}

// Validate receipts
ensure!(
op_block.receipts.is_none(),
"Op blocks should not contain receipts"
);
for (block_no, op_block) in &self.op_block_header {
ensure!(*block_no == op_block.number, "Block number mismatch");
}

for (block_no, eth_block) in &self.full_eth_block {
ensure!(
*block_no == eth_block.block_header.number,
"Block number mismatch"
);

// Validate tx list
{
let mut tx_trie = MptNode::default();
for (tx_no, tx) in eth_block.transactions.iter().enumerate() {
let trie_key = tx_no.to_rlp();
tx_trie.insert_rlp(&trie_key, tx)?;
}
ensure!(
tx_trie.hash() == eth_block.block_header.transactions_root,
"Invalid eth block transaction data!"
);
}

// Validate receipts
if eth_block.receipts.is_some() {
let mut receipt_trie = MptNode::default();
for (tx_no, receipt) in eth_block.receipts.as_ref().unwrap().iter().enumerate() {
let trie_key = tx_no.to_rlp();
receipt_trie.insert_rlp(&trie_key, receipt)?;
}
ensure!(
receipt_trie.hash() == eth_block.block_header.receipts_root,
"Invalid eth block receipt data!"
);
} else {
let can_contain_deposits = deposits::can_contain(
&OPTIMISM_CHAIN_SPEC.deposit_contract,
&eth_block.block_header.logs_bloom,
);
let can_contain_config = system_config::can_contain(
&OPTIMISM_CHAIN_SPEC.system_config_contract,
&eth_block.block_header.logs_bloom,
);
ensure!(
!can_contain_deposits,
"Eth block has no receipts, but bloom filter indicates it has deposits"
);
ensure!(
!can_contain_config,
"Eth block has no receipts, but bloom filter indicates it has config updates"
);
}
}

Ok(())
}

fn get_full_op_block(&mut self, block_no: u64) -> Result<BlockInput<OptimismTxEssence>> {
let op_block = self.full_op_block.remove(&block_no).unwrap();

Ok(op_block)
}
Expand All @@ -103,67 +167,12 @@ impl BatcherDb for MemDb {
.op_block_header
.remove(&block_no)
.context("not or no longer in db")?;
assert_eq!(block_no, op_block.number);

Ok(op_block)
}

fn get_full_eth_block(&mut self, block_no: u64) -> Result<BlockInput<EthereumTxEssence>> {
let eth_block = self.full_eth_block.remove(&block_no).unwrap();
assert_eq!(block_no, eth_block.block_header.number);

// Validate tx list
{
let mut tx_trie = MptNode::default();
for (tx_no, tx) in eth_block.transactions.iter().enumerate() {
let trie_key = tx_no.to_rlp();
tx_trie.insert_rlp(&trie_key, tx)?;
}
ensure!(
tx_trie.hash() == eth_block.block_header.transactions_root,
"Invalid eth block transaction data!"
);
}

// Validate receipts
if eth_block.receipts.is_some() {
let mut receipt_trie = MptNode::default();
for (tx_no, receipt) in eth_block.receipts.as_ref().unwrap().iter().enumerate() {
let trie_key = tx_no.to_rlp();
receipt_trie.insert_rlp(&trie_key, receipt)?;
}
ensure!(
receipt_trie.hash() == eth_block.block_header.receipts_root,
"Invalid eth block receipt data!"
);
} else {
let can_contain_deposits = deposits::can_contain(
&OPTIMISM_CHAIN_SPEC.deposit_contract,
&eth_block.block_header.logs_bloom,
);
let can_contain_config = system_config::can_contain(
&OPTIMISM_CHAIN_SPEC.system_config_contract,
&eth_block.block_header.logs_bloom,
);
ensure!(
!can_contain_deposits,
"Eth block has no receipts, but bloom filter indicates it has deposits"
);
ensure!(
!can_contain_config,
"Eth block has no receipts, but bloom filter indicates it has config updates"
);
}

Ok(eth_block)
}

fn get_eth_block_header(&mut self, block_no: u64) -> Result<Header> {
let eth_block = self
.eth_block_header
.remove(&block_no)
.context("not or no longer in db")?;
assert_eq!(block_no, eth_block.number);
fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput<EthereumTxEssence>> {
let eth_block = self.full_eth_block.get(&block_no).unwrap();

Ok(eth_block)
}
Expand Down
8 changes: 6 additions & 2 deletions lib/src/optimism/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ pub struct DeriveMachine<D> {
impl<D: BatcherDb> DeriveMachine<D> {
/// Creates a new instance of DeriveMachine.
pub fn new(chain_config: &ChainConfig, mut derive_input: DeriveInput<D>) -> Result<Self> {
derive_input.db.validate()?;

let op_block_no = derive_input.op_head_block_no;

// read system config from op_head (seq_no/epoch_no..etc)
Expand Down Expand Up @@ -279,8 +281,10 @@ impl<D: BatcherDb> DeriveMachine<D> {
let l1_epoch_header = self
.derive_input
.db
.get_eth_block_header(op_batch.essence.epoch_num)
.context("eth block not found")?;
.get_full_eth_block(op_batch.essence.epoch_num)
.context("eth block not found")?
.block_header
.clone();
ensure!(
new_op_head.mix_hash == l1_epoch_header.mix_hash,
"Invalid op block mix hash"
Expand Down
Loading