Skip to content

Commit

Permalink
Merge pull request #34 from ethereum-optimism/refcell/derivation-test…
Browse files Browse the repository at this point in the history
…-fixtures
  • Loading branch information
0xKitsune authored Jul 25, 2024
2 parents e344099 + b5d6004 commit b0d7a84
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 22 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ op-alloy-consensus = "0.1.2"
alloy = { version = "0.1.4", features = [
"rpc",
"rpc-types-trace",
"consensus",
"providers"
] }
foundry-common = { git = "https://github.com/foundry-rs/foundry", default-features = true, rev = "7c4482fc9541f11b57575e2d8bf7bd190b61bda6" }
Expand Down
103 changes: 101 additions & 2 deletions crates/op-test-vectors/src/derivation.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,107 @@
//! Module containing the derivation test fixture.
use alloy::consensus::Blob;
use alloy::primitives::{Bytes, B256};
use serde::{Deserialize, Serialize};

/// The derivation fixture is the top-level object that contains
/// everything needed to run a derivation test.
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct DerivationFixture {}
#[derive(Serialize, Deserialize, Debug, Default, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct DerivationFixture {
/// A list of L1 Blocks to derive from.
pub l1_blocks: Vec<FixtureBlock>,
/// A list of L2 Output Roots to assert against.
pub l2_output_roots: Vec<B256>,
}

/// A fixture block is a minimal block with associated data including blobs
/// to derive from.
#[derive(Serialize, Deserialize, Debug, Default, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct FixtureBlock {
/// The block number.
pub number: u64,
/// The block hash.
pub hash: B256,
/// The block timestamp.
pub timestamp: u64,
/// Block Transactions.
/// EIP-2718 encoded raw transactions
pub transactions: Vec<Bytes>,
/// Blobs for this block.
pub blobs: Vec<Box<Blob>>,
}

#[cfg(test)]
mod tests {
use super::*;
use alloy::primitives::{b256, bytes};

fn ref_blocks() -> Vec<FixtureBlock> {
vec![
FixtureBlock {
number: 1,
hash: b256!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
timestamp: 102,
transactions: vec![
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
],
blobs: vec![],
},
FixtureBlock {
number: 2,
hash: b256!("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
timestamp: 104,
transactions: vec![
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
],
blobs: vec![],
},
FixtureBlock {
number: 2,
hash: b256!("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
timestamp: 106,
transactions: vec![
bytes!("02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"),
],
blobs: vec![],
},
]
}

fn ref_l2_output_roots() -> Vec<B256> {
vec![
b256!("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"),
b256!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
]
}

#[test]
fn test_derivation_fixture() {
let fixture_str = include_str!("./testdata/derivation_fixture.json");
let fixture: DerivationFixture = serde_json::from_str(fixture_str).unwrap();
let expected = DerivationFixture {
l1_blocks: ref_blocks(),
l2_output_roots: ref_l2_output_roots(),
};
assert_eq!(fixture, expected);
}

#[test]
fn test_fixture_block() {
let fixture_str = include_str!("./testdata/fixture_block.json");
let fixture: FixtureBlock = serde_json::from_str(fixture_str).unwrap();
assert_eq!(fixture.number, 1);
assert_eq!(
fixture.hash,
b256!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
);
assert_eq!(fixture.timestamp, 102);
assert_eq!(fixture.transactions.len(), 1);
assert_eq!(fixture.blobs.len(), 0);
}
}
62 changes: 43 additions & 19 deletions crates/op-test-vectors/src/execution.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! Module containing the execution test fixture.
use std::collections::HashMap;
use alloy::primitives::{Address, Bloom, B256, U256};
use alloy::rpc::types::trace::geth::AccountState;
use alloy::rpc::types::{Log, TransactionReceipt};
use anvil_core::eth::block::Block;
use anvil_core::eth::transaction::{TypedReceipt, TypedTransaction};
use serde::{Deserialize, Serialize};
use color_eyre::eyre;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// The execution fixture is the top-level object that contains
/// everything needed to run an execution test.
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionFixture {
/// The execution environment sets up the current block context.
pub env: ExecutionEnvironment,
Expand All @@ -33,7 +34,7 @@ pub struct ExecutionFixture {
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionEnvironment {
/// The current block coinbase.
/// The current block coinbase.
pub current_coinbase: Address,
/// The current block difficulty.
pub current_difficulty: U256,
Expand Down Expand Up @@ -111,11 +112,19 @@ impl TryFrom<TransactionReceipt<TypedReceipt<Log>>> for ExecutionReceipt {
fn try_from(receipt: TransactionReceipt<TypedReceipt<Log>>) -> eyre::Result<Self> {
Ok(Self {
transaction_hash: receipt.transaction_hash,
root: receipt.state_root.ok_or_else(|| eyre::eyre!("missing state root"))?,
root: receipt
.state_root
.ok_or_else(|| eyre::eyre!("missing state root"))?,
contract_address: receipt.contract_address,
gas_used: U256::from(receipt.gas_used),
block_hash: receipt.block_hash.ok_or_else(|| eyre::eyre!("missing block hash"))?,
transaction_index: U256::from(receipt.transaction_index.ok_or_else(|| eyre::eyre!("missing transaction index"))?),
block_hash: receipt
.block_hash
.ok_or_else(|| eyre::eyre!("missing block hash"))?,
transaction_index: U256::from(
receipt
.transaction_index
.ok_or_else(|| eyre::eyre!("missing transaction index"))?,
),
inner: receipt.inner,
})
}
Expand All @@ -129,41 +138,54 @@ mod tests {
#[test]
fn test_serialize_execution_environment() {
let expected_env = include_str!("./testdata/environment.json");
let env = serde_json::from_str::<ExecutionEnvironment>(expected_env).expect("failed to parse environment");
let env = serde_json::from_str::<ExecutionEnvironment>(expected_env)
.expect("failed to parse environment");
let serialized_env = serde_json::to_string(&env).expect("failed to serialize environment");
let serialized_value = serde_json::from_str::<Value>(&serialized_env).expect("failed to parse serialized environment");
let expected_value = serde_json::from_str::<Value>(expected_env).expect("failed to parse expected environment");
let serialized_value = serde_json::from_str::<Value>(&serialized_env)
.expect("failed to parse serialized environment");
let expected_value = serde_json::from_str::<Value>(expected_env)
.expect("failed to parse expected environment");
assert_eq!(serialized_value, expected_value);
}

#[test]
fn test_serialize_execution_result() {
let expected_result = include_str!("./testdata/result.json");
let execution_result = serde_json::from_str::<ExecutionResult>(expected_result).expect("failed to parse result");
let serialized_result = serde_json::to_string(&execution_result).expect("failed to serialize result");
let serialized_value = serde_json::from_str::<Value>(&serialized_result).expect("failed to parse serialized result");
let expected_value = serde_json::from_str::<Value>(expected_result).expect("failed to parse expected result");
let execution_result = serde_json::from_str::<ExecutionResult>(expected_result)
.expect("failed to parse result");
let serialized_result =
serde_json::to_string(&execution_result).expect("failed to serialize result");
let serialized_value = serde_json::from_str::<Value>(&serialized_result)
.expect("failed to parse serialized result");
let expected_value = serde_json::from_str::<Value>(expected_result)
.expect("failed to parse expected result");
assert_eq!(serialized_value, expected_value);
}

#[test]
fn test_exec_receipt_try_from_tx_receipt() {
let tx_receipt_str = include_str!("./testdata/tx_receipt.json");
let tx_receipt: TransactionReceipt<TypedReceipt<Log>> = serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
let exec_receipt = ExecutionReceipt::try_from(tx_receipt.clone()).expect("failed to convert tx receipt to exec receipt");
let tx_receipt: TransactionReceipt<TypedReceipt<Log>> =
serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
let exec_receipt = ExecutionReceipt::try_from(tx_receipt.clone())
.expect("failed to convert tx receipt to exec receipt");
assert_eq!(exec_receipt.transaction_hash, tx_receipt.transaction_hash);
assert_eq!(exec_receipt.root, tx_receipt.state_root.unwrap());
assert_eq!(exec_receipt.contract_address, tx_receipt.contract_address);
assert_eq!(exec_receipt.gas_used, U256::from(tx_receipt.gas_used));
assert_eq!(exec_receipt.block_hash, tx_receipt.block_hash.unwrap());
assert_eq!(exec_receipt.transaction_index, U256::from(tx_receipt.transaction_index.unwrap()));
assert_eq!(
exec_receipt.transaction_index,
U256::from(tx_receipt.transaction_index.unwrap())
);
assert_eq!(exec_receipt.inner, tx_receipt.inner);
}

#[test]
fn test_exec_receipt_try_from_missing_root() {
let tx_receipt_str = include_str!("./testdata/tx_receipt.json");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> = serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> =
serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
tx_receipt.state_root = None;
let exec_receipt = ExecutionReceipt::try_from(tx_receipt);
assert!(exec_receipt.is_err());
Expand All @@ -172,7 +194,8 @@ mod tests {
#[test]
fn test_exec_receipt_try_from_missing_block_hash() {
let tx_receipt_str = include_str!("./testdata/tx_receipt.json");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> = serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> =
serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
tx_receipt.block_hash = None;
let exec_receipt = ExecutionReceipt::try_from(tx_receipt);
assert!(exec_receipt.is_err());
Expand All @@ -181,7 +204,8 @@ mod tests {
#[test]
fn test_exec_receipt_try_from_missing_tx_index() {
let tx_receipt_str = include_str!("./testdata/tx_receipt.json");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> = serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
let mut tx_receipt: TransactionReceipt<TypedReceipt<Log>> =
serde_json::from_str(tx_receipt_str).expect("failed to parse tx receipt");
tx_receipt.transaction_index = None;
let exec_receipt = ExecutionReceipt::try_from(tx_receipt);
assert!(exec_receipt.is_err());
Expand Down
7 changes: 6 additions & 1 deletion crates/op-test-vectors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#![doc = include_str!("../README.md")]
#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)]
#![warn(
missing_debug_implementations,
missing_docs,
unreachable_pub,
rustdoc::all
)]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

Expand Down
38 changes: 38 additions & 0 deletions crates/op-test-vectors/src/testdata/derivation_fixture.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"l2OutputRoots": [
"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
],
"l1Blocks": [
{
"number": 1,
"hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"timestamp": 102,
"transactions": [
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5",
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5",
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"
],
"blobs": []
},
{
"number": 2,
"hash": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"timestamp": 104,
"transactions": [
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5",
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"
],
"blobs": []
},
{
"number": 2,
"hash": "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"timestamp": 106,
"transactions": [
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"
],
"blobs": []
}
]
}
9 changes: 9 additions & 0 deletions crates/op-test-vectors/src/testdata/fixture_block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"number": 1,
"hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"timestamp": 102,
"transactions": [
"0x02f870018307c100808476d0a39c82565f94388c818ca8b9251b393131c08a736a67ccb1929787b60572b2eb6c9080c001a033bee682348fa78ffc1027bc9981e7dc60eca03af909c4eb05720e781fdae179a01ccf85367c246082fa09ef748d3b07c90752c2b59034a6b881cf99aca586eaf5"
],
"blobs": []
}
27 changes: 27 additions & 0 deletions crates/op-test-vectors/src/testdata/fixture_block_with_blob.json

Large diffs are not rendered by default.

0 comments on commit b0d7a84

Please sign in to comment.