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

Add Op L1 block info txn in op CL tester #420

Merged
merged 4 commits into from
Feb 11, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
/scripts/benchmark-results.*
/test/
/integration_logs
genesis.json

# editors
.code
Expand Down
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.

1 change: 1 addition & 0 deletions crates/op-rbuilder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ alloy-network.workspace = true
# op
op-alloy-consensus.workspace = true
op-alloy-rpc-types-engine.workspace = true
op-alloy-network.workspace = true

revm.workspace = true

Expand Down
32 changes: 27 additions & 5 deletions crates/op-rbuilder/src/integration/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ mod tests {
op_rbuilder::OpRbuilderConfig, op_reth::OpRethConfig, IntegrationFramework,
};
use crate::tester::{BlockGenerator, EngineApi};
use alloy_provider::{Provider, ProviderBuilder};
use alloy_rpc_types_eth::BlockTransactionsKind;
use op_alloy_network::Optimism;
use std::path::PathBuf;
use uuid::Uuid;

const BUILDER_PRIVATE_KEY: &str =
"0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";

#[tokio::test]
async fn integration_test_chain_produces_blocks() {
async fn integration_test_chain_produces_blocks() -> eyre::Result<()> {
// This is a simple test using the integration framework to test that the chain
// produces blocks.
let mut framework = IntegrationFramework::new().unwrap();
Expand All @@ -28,6 +31,7 @@ mod tests {
.data_dir(builder_data_dir)
.auth_rpc_port(1234)
.network_port(1235)
.http_port(1238)
.with_builder_private_key(BUILDER_PRIVATE_KEY);

// create the validation reth node
Expand All @@ -49,16 +53,34 @@ mod tests {
let validation_api = EngineApi::new("http://localhost:1236").unwrap();

let mut generator = BlockGenerator::new(&engine_api, Some(&validation_api), false, 1);
generator.init().await.unwrap();
generator.init().await?;

let provider = ProviderBuilder::new()
.network::<Optimism>()
.on_http("http://localhost:1238".parse()?);

for _ in 0..10 {
generator.generate_block().await.unwrap();
let block_hash = generator.generate_block().await?;

// query the block and the transactions inside the block
let block = provider
.get_block_by_hash(block_hash, BlockTransactionsKind::Hashes)
.await?
.expect("block");

for hash in block.transactions.hashes() {
let _ = provider
.get_transaction_receipt(hash)
.await?
.expect("receipt");
}
}

// there must be a line logging the monitoring transaction
op_rbuilder
.find_log_line("Committed block built by builder")
.await
.unwrap();
.await?;

Ok(())
}
}
5 changes: 5 additions & 0 deletions crates/op-rbuilder/src/integration/op_rbuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ impl OpRbuilderConfig {
self
}

pub fn http_port(mut self, port: u16) -> Self {
self.http_port = Some(port);
self
}

pub fn with_builder_private_key(mut self, private_key: &str) -> Self {
self.builder_private_key = Some(private_key.to_string());
self
Expand Down
43 changes: 41 additions & 2 deletions crates/op-rbuilder/src/tester/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use alloy_primitives::Address;
use alloy_primitives::Bytes;
use alloy_primitives::TxKind;
use alloy_primitives::B256;
use alloy_primitives::U256;
use alloy_primitives::{hex, U256};
use alloy_rpc_types_engine::ExecutionPayloadV1;
use alloy_rpc_types_engine::ExecutionPayloadV2;
use alloy_rpc_types_engine::PayloadAttributes;
Expand Down Expand Up @@ -181,6 +181,11 @@ pub async fn generate_genesis(output: Option<String>) -> eyre::Result<()> {
Ok(())
}

// L1 block info for OP mainnet block 124665056 (stored in input of tx at index 0)
//
// https://optimistic.etherscan.io/tx/0x312e290cf36df704a2217b015d6455396830b0ce678b860ebfcc30f41403d7b1
const FJORD_DATA: &[u8] = &hex!("440a5e200000146b000f79c500000000000000040000000066d052e700000000013ad8a3000000000000000000000000000000000000000000000000000000003ef1278700000000000000000000000000000000000000000000000000000000000000012fdf87b89884a61e74b322bbcf60386f543bfae7827725efaaf0ab1de2294a590000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985");

/// A system that continuously generates blocks using the engine API
pub struct BlockGenerator<'a> {
engine_api: &'a EngineApi,
Expand Down Expand Up @@ -308,6 +313,40 @@ impl<'a> BlockGenerator<'a> {
.as_secs();
let timestamp = timestamp + self.block_time_secs;

// Add L1 block info as the first transaction in every L2 block
// This deposit transaction contains L1 block metadata required by the L2 chain
// Currently using hardcoded data from L1 block 124665056
// If this info is not provided, Reth cannot decode the receipt for any transaction
// in the block since it also includes this info as part of the result.
// It does not matter if the to address (4200000000000000000000000000000000000015) is
// not deployed on the L2 chain since Reth queries the block to get the info and not the contract.
let block_info_tx: Bytes = {
let deposit_tx = TxDeposit {
source_hash: B256::default(),
from: address!("DeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001"),
to: TxKind::Call(address!("4200000000000000000000000000000000000015")),
mint: None,
value: U256::default(),
gas_limit: 210000,
is_system_transaction: true,
input: FJORD_DATA.into(),
};

// Create a temporary signer for the deposit
let signer = Signer::random();
let signed_tx = signer.sign_tx(OpTypedTransaction::Deposit(deposit_tx))?;
signed_tx.encoded_2718().into()
};

let transactions = if let Some(transactions) = transactions {
// prepend the block info transaction
let mut all_transactions = vec![block_info_tx];
all_transactions.extend(transactions.into_iter());
all_transactions
} else {
vec![block_info_tx]
};

let result = self
.engine_api
.update_forkchoice(
Expand All @@ -321,7 +360,7 @@ impl<'a> BlockGenerator<'a> {
prev_randao: B256::ZERO,
suggested_fee_recipient: Default::default(),
},
transactions,
transactions: Some(transactions),
no_tx_pool: Some(self.no_tx_pool),
gas_limit: Some(10000000000),
eip_1559_params: None,
Expand Down
Loading