Skip to content
Open
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
100 changes: 100 additions & 0 deletions crates/flashblocks-rpc/tests/assets/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"config": {
"chainId": 8453,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"mergeNetsplitBlock": 0,
"bedrockBlock": 0,
"regolithTime": 0,
"terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": true,
"optimism": {
"eip1559Elasticity": 6,
"eip1559Denominator": 50
}
},
"nonce": "0x0",
"timestamp": "0x0",
"extraData": "0x00",
"gasLimit": "0x1c9c380",
"difficulty": "0x0",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0x14dc79964da2c08b23698b3d3cc7ca32193d9955": {
"balance": "0xd3c21bcecceda1000000"
},
"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65": {
"balance": "0xd3c21bcecceda1000000"
},
"0x1cbd3b2770909d4e10f157cabc84c7264073c9ec": {
"balance": "0xd3c21bcecceda1000000"
},
"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f": {
"balance": "0xd3c21bcecceda1000000"
},
"0x2546bcd3c84621e976d8185a91a922ae77ecec30": {
"balance": "0xd3c21bcecceda1000000"
},
"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc": {
"balance": "0xd3c21bcecceda1000000"
},
"0x70997970c51812dc3a010c7d01b50e0d17dc79c8": {
"balance": "0xd3c21bcecceda1000000"
},
"0x71be63f3384f5fb98995898a86b02fb2426c5788": {
"balance": "0xd3c21bcecceda1000000"
},
"0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199": {
"balance": "0xd3c21bcecceda1000000"
},
"0x90f79bf6eb2c4f870365e785982e1f101e93b906": {
"balance": "0xd3c21bcecceda1000000"
},
"0x976ea74026e726554db657fa54763abd0c3a0aa9": {
"balance": "0xd3c21bcecceda1000000"
},
"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc": {
"balance": "0xd3c21bcecceda1000000"
},
"0x9c41de96b2088cdc640c6182dfcf5491dc574a57": {
"balance": "0xd3c21bcecceda1000000"
},
"0xa0ee7a142d267c1f36714e4a8f75612f20a79720": {
"balance": "0xd3c21bcecceda1000000"
},
"0xbcd4042de499d14e55001ccbb24a551f3b954096": {
"balance": "0xd3c21bcecceda1000000"
},
"0xbda5747bfd65f08deb54cb465eb87d40e51b197e": {
"balance": "0xd3c21bcecceda1000000"
},
"0xcd3b766ccdd6ae721141f452c550ca635964ce71": {
"balance": "0xd3c21bcecceda1000000"
},
"0xdd2fd4581271e230360230f9337d5c0430bf44c0": {
"balance": "0xd3c21bcecceda1000000"
},
"0xdf3e18d64bc6a983f673ab319ccae4f1a57c7097": {
"balance": "0xd3c21bcecceda1000000"
},
"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": {
"balance": "0xd3c21bcecceda1000000"
},
"0xfabb0ac9d68b0b445fb7357272ff202c5651694a": {
"balance": "0xd3c21bcecceda1000000"
}
},
"number": "0x0"
}
190 changes: 190 additions & 0 deletions crates/flashblocks-rpc/tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use alloy_consensus::Receipt;
use alloy_genesis::Genesis;
use alloy_primitives::map::HashMap;
use alloy_primitives::{address, b256, bytes, Address, Bytes, B256};
use alloy_provider::RootProvider;
use alloy_rpc_client::RpcClient;
use alloy_rpc_types_engine::PayloadId;
use base_reth_flashblocks_rpc::rpc::{EthApiExt, EthApiOverrideServer};
use base_reth_flashblocks_rpc::state::FlashblocksState;
use base_reth_flashblocks_rpc::subscription::{Flashblock, FlashblocksReceiver, Metadata};
use op_alloy_consensus::OpDepositReceipt;
use op_alloy_network::Optimism;
use reth::args::{DiscoveryArgs, NetworkArgs, RpcServerArgs};
use reth::builder::{Node, NodeBuilder, NodeConfig, NodeHandle};
use reth::chainspec::Chain;
use reth::core::exit::NodeExitFuture;
use reth::tasks::TaskManager;
use reth_optimism_chainspec::OpChainSpecBuilder;
use reth_optimism_node::args::RollupArgs;
use reth_optimism_node::OpNode;
use reth_optimism_primitives::OpReceipt;
use reth_provider::providers::BlockchainProvider;
use rollup_boost::{ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1};
use std::any::Any;
use std::net::SocketAddr;
use std::sync::{Arc, Once};
use tokio::sync::{mpsc, oneshot};

pub const ALICE: Address = address!("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266");
pub const BOB: Address = address!("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
pub const CHARLIE: Address = address!("0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC");

pub const BLOCK_INFO_TXN: Bytes = bytes!("0x7ef90104a06c0c775b6b492bab9d7e81abdf27f77cafb698551226455a82f559e0f93fea3794deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8b0098999be000008dd00101c1200000000000000020000000068869d6300000000015f277f000000000000000000000000000000000000000000000000000000000d42ac290000000000000000000000000000000000000000000000000000000000000001abf52777e63959936b1bf633a2a643f0da38d63deffe49452fed1bf8a44975d50000000000000000000000005050f69a9786f081509234f1a7f4684b5e5b76c9000000000000000000000000");
pub const BLOCK_INFO_TXN_HASH: B256 =
b256!("0xba56c8b0deb460ff070f8fca8e2ee01e51a3db27841cc862fdd94cc1a47662b6");

pub struct NodeContext {
sender: mpsc::Sender<(Flashblock, oneshot::Sender<()>)>,
http_api_addr: SocketAddr,
_node_exit_future: NodeExitFuture,
_node: Box<dyn Any + Sync + Send>,
_task_manager: TaskManager,
}

impl NodeContext {
pub async fn send_payload(&self, payload: Flashblock) -> eyre::Result<()> {
let (tx, rx) = oneshot::channel();
self.sender.send((payload, tx)).await?;
rx.await?;
Ok(())
}

pub async fn provider(&self) -> eyre::Result<RootProvider<Optimism>> {
let url = format!("http://{}", self.http_api_addr);
let client = RpcClient::builder().http(url.parse()?);
Ok(RootProvider::<Optimism>::new(client))
}
}

static INIT_TRACING: Once = Once::new();

fn init_logging_once() {
INIT_TRACING.call_once(|| {
reth_tracing::init_test_tracing();
});
}

pub async fn setup_node() -> eyre::Result<NodeContext> {
init_logging_once();
let tasks = TaskManager::current();
let exec = tasks.executor();
const BASE_SEPOLIA_CHAIN_ID: u64 = 84532;

let genesis: Genesis = serde_json::from_str(include_str!("../assets/genesis.json"))
.expect("Genesis object can't be constructed from file ../assets/genesis.json");
let chain_spec = Arc::new(
OpChainSpecBuilder::base_mainnet()
.genesis(genesis)
.ecotone_activated()
.chain(Chain::from(BASE_SEPOLIA_CHAIN_ID))
.build(),
);

let network_config = NetworkArgs {
discovery: DiscoveryArgs {
disable_discovery: true,
..DiscoveryArgs::default()
},
..NetworkArgs::default()
};

let node_config = NodeConfig::new(chain_spec.clone())
.with_network(network_config.clone())
.with_rpc(RpcServerArgs::default().with_unused_ports().with_http())
.with_unused_ports();

let node = OpNode::new(RollupArgs::default());

let (sender, mut receiver) = mpsc::channel::<(Flashblock, oneshot::Sender<()>)>(100);

let NodeHandle {
node,
node_exit_future,
} = NodeBuilder::new(node_config.clone())
.testing_node(exec.clone())
.with_types_and_provider::<OpNode, BlockchainProvider<_>>()
.with_components(node.components_builder())
.with_add_ons(node.add_ons())
.extend_rpc_modules(move |ctx| {
let flashblocks_state = Arc::new(FlashblocksState::new(ctx.provider().clone()));
flashblocks_state.start();

let api_ext = EthApiExt::new(
ctx.registry.eth_api().clone(),
ctx.registry.eth_handlers().filter.clone(),
flashblocks_state.clone(),
);

ctx.modules.replace_configured(api_ext.into_rpc())?;

tokio::spawn(async move {
while let Some((payload, tx)) = receiver.recv().await {
flashblocks_state.on_flashblock_received(payload);
tx.send(()).unwrap();
}
});

Ok(())
})
.launch()
.await?;

let http_api_addr = node
.rpc_server_handle()
.http_local_addr()
.ok_or_else(|| eyre::eyre!("Failed to get http api address"))?;

Ok(NodeContext {
sender,
http_api_addr,
_node_exit_future: node_exit_future,
_node: Box::new(node),
_task_manager: tasks,
})
}

pub fn create_base_flashblock(block_number: u64, transactions: Vec<Bytes>) -> Flashblock {
let mut receipts = HashMap::default();
receipts.insert(
BLOCK_INFO_TXN_HASH,
OpReceipt::Deposit(OpDepositReceipt {
inner: Receipt {
status: true.into(),
cumulative_gas_used: 21000,
logs: vec![],
},
deposit_nonce: Some(4012992u64),
deposit_receipt_version: None,
}),
);

Flashblock {
payload_id: PayloadId::new([0; 8]),
index: block_number,
base: Some(ExecutionPayloadBaseV1 {
parent_beacon_block_root: B256::default(),
parent_hash: B256::default(),
fee_recipient: Address::ZERO,
prev_randao: B256::default(),
block_number,
gas_limit: 30_000_000,
timestamp: block_number,
extra_data: Bytes::new(),
base_fee_per_gas: alloy_primitives::U256::ZERO,
}),
diff: ExecutionPayloadFlashblockDeltaV1 {
transactions: {
let mut txs = vec![BLOCK_INFO_TXN];
txs.extend(transactions);
txs
},
..Default::default()
},
metadata: Metadata {
block_number,
receipts,
..Default::default()
},
}
}
Loading