Skip to content

Commit

Permalink
first trial
Browse files Browse the repository at this point in the history
  • Loading branch information
Keszey Dániel authored and Keszey Dániel committed Oct 18, 2024
1 parent e1f6420 commit 5e2729c
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 54 deletions.
67 changes: 43 additions & 24 deletions bin/reth/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![allow(missing_docs)]

// We use jemalloc for performance reasons.
#[cfg(all(feature = "jemalloc", unix))]
#[global_allocator]
Expand All @@ -12,6 +11,9 @@ use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle};
use reth_node_ethereum::EthereumNode;
use reth_tasks::TaskManager;

// Define a list of suffixes for chain IDs and RPC ports
const SUFFIXES: [char; 2] = ['A', 'B'/* , 'C'*/]; // Add more suffixes as needed, like C

fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let tasks = TaskManager::current();
Expand All @@ -22,34 +24,51 @@ fn main() -> eyre::Result<()> {
..NetworkArgs::default()
};

let chain_spec = ChainSpecBuilder::default()
.chain(gwyneth::exex::CHAIN_ID.into())
.genesis(
serde_json::from_str(include_str!(
"../../../crates/ethereum/node/tests/assets/genesis.json"
))
.unwrap(),
)
.cancun_activated()
.build();
let mut gwyneth_nodes = Vec::new();

for suffix in SUFFIXES.iter() {
let chain_id = match suffix {
'A' => gwyneth::exex::CHAIN_ID_A,
'B' => gwyneth::exex::CHAIN_ID_B,
// 'C' => gwyneth::exex::CHAIN_ID_C, // Add this constant in your exex.rs
_ => panic!("Unsupported chain ID suffix"),
};

let node_config = NodeConfig::test()
.with_chain(chain_spec.clone())
.with_network(network_config.clone())
.with_unused_ports()
.with_rpc(RpcServerArgs::default().with_unused_ports().with_static_l2_rpc_ip_and_port(chain_spec.chain.id()));
let chain_spec = ChainSpecBuilder::default()
.chain(chain_id.into())
.genesis(
serde_json::from_str(include_str!(
"../../../crates/ethereum/node/tests/assets/genesis.json"
))
.unwrap(),
)
.cancun_activated()
.build();

let NodeHandle { node: gwyneth_node, node_exit_future: _ } =
NodeBuilder::new(node_config.clone())
.gwyneth_node(exec.clone(), chain_spec.chain.id())
.node(GwynethNode::default())
.launch()
.await?;
let node_config = NodeConfig::test()
.with_chain(chain_spec.clone())
.with_network(network_config.clone())
.with_unused_ports()
.with_rpc(
RpcServerArgs::default()
.with_unused_ports()
.with_static_l2_rpc_ip_and_port(chain_spec.chain.id(), *suffix)
);

let NodeHandle { node: gwyneth_node, node_exit_future: _ } =
NodeBuilder::new(node_config.clone())
.gwyneth_node(exec.clone(), chain_spec.chain.id())
.node(GwynethNode::default())
.launch()
.await?;

gwyneth_nodes.push(gwyneth_node);
}

let handle = builder
.node(EthereumNode::default())
.install_exex("Rollup", move |ctx| async {
Ok(gwyneth::exex::Rollup::new(ctx, gwyneth_node).await?.start())
Ok(gwyneth::exex::Rollup::new(ctx, gwyneth_nodes).await?.start())
})
.launch()
.await?;
Expand All @@ -69,4 +88,4 @@ mod tests {
#[command(flatten)]
args: T,
}
}
}
31 changes: 24 additions & 7 deletions crates/gwyneth/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,35 @@ impl PayloadEnvelopeExt for ExecutionPayloadEnvelopeV3 {
}
}
pub trait RpcServerArgsExEx {
fn with_static_l2_rpc_ip_and_port(self, chain_id: u64) -> Self;
fn with_static_l2_rpc_ip_and_port(self, chain_id: u64, suffix: char) -> Self;
}

impl RpcServerArgsExEx for RpcServerArgs {
fn with_static_l2_rpc_ip_and_port(mut self, chain_id: u64) -> Self {
fn with_static_l2_rpc_ip_and_port(mut self, chain_id: u64, suffix: char) -> Self {
self.http = true;
// On the instance the program is running, we wanna have 10111 exposed as the (exex) L2's
// RPC port.
self.http_addr = Ipv4Addr::new(0, 0, 0, 0).into();
self.http_port = 10110u16;
self.ws_port = 10111u16;
self.ipcpath = format!("{}-{}", constants::DEFAULT_IPC_ENDPOINT, chain_id);

// Set HTTP and WS ports based on suffix
match suffix {
'A' => {
self.http_port = 10110u16;
self.ws_port = 10111u16;
},
'B' => {
self.http_port = 20110u16;
self.ws_port = 20111u16;
},
'C' => {
self.http_port = 30110u16;
self.ws_port = 30111u16;
},
// Obviously add more if needed more chain
_ => panic!("Unsupported suffix: {}", suffix),
}

// Set IPC path
self.ipcpath = format!("{}-{}-{}", constants::DEFAULT_IPC_ENDPOINT, chain_id, suffix);

self
}
}
60 changes: 37 additions & 23 deletions crates/gwyneth/src/exex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use reth_transaction_pool::{
use RollupContract::{BlockProposed, RollupContractEvents};

const ROLLUP_CONTRACT_ADDRESS: Address = address!("9fCF7D13d10dEdF17d0f24C62f0cf4ED462f65b7");
pub const CHAIN_ID: u64 = 167010;
pub const CHAIN_ID_A: u64 = 167010;
pub const CHAIN_ID_B: u64 = 267010;
const INITIAL_TIMESTAMP: u64 = 1710338135;

pub type GwynethFullNode = FullNode<
Expand Down Expand Up @@ -69,18 +70,22 @@ sol!(RollupContract, "TaikoL1.json");

pub struct Rollup<Node: reth_node_api::FullNodeComponents> {
ctx: ExExContext<Node>,
node: GwynethFullNode,
engine_api: EngineApiContext<GwynethEngineTypes>,
nodes: Vec<GwynethFullNode>,
engine_apis: Vec<EngineApiContext<GwynethEngineTypes>>,
}

impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
pub async fn new(ctx: ExExContext<Node>, node: GwynethFullNode) -> eyre::Result<Self> {
let engine_api = EngineApiContext {
engine_api_client: node.auth_server_handle().http_client(),
canonical_stream: node.provider.canonical_state_stream(),
_marker: PhantomData::<GwynethEngineTypes>,
};
Ok(Self { ctx, node, /* payload_event_stream, */ engine_api })
pub async fn new(ctx: ExExContext<Node>, nodes: Vec<GwynethFullNode>) -> eyre::Result<Self> {
let mut engine_apis = Vec::new();
for node in &nodes {
let engine_api = EngineApiContext {
engine_api_client: node.auth_server_handle().http_client(),
canonical_stream: node.provider.canonical_state_stream(),
_marker: PhantomData::<GwynethEngineTypes>,
};
engine_apis.push(engine_api);
}
Ok(Self { ctx, nodes, /* payload_event_stream, */ engine_apis })
}

pub async fn start(mut self) -> eyre::Result<()> {
Expand All @@ -91,7 +96,13 @@ impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
}

if let Some(committed_chain) = notification.committed_chain() {
self.commit(&committed_chain).await?;
let nodes = &self.nodes;
let engine_apis = &self.engine_apis;
for i in 0..nodes.len() {
let node = &nodes[i];
let engine_api = &engine_apis[i];
self.commit(&committed_chain, node, engine_api).await?;
}
self.ctx.events.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?;
}
}
Expand All @@ -103,13 +114,14 @@ impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
///
/// This function decodes all transactions to the rollup contract into events, executes the
/// corresponding actions and inserts the results into the database.
pub async fn commit(&mut self, chain: &Chain) -> eyre::Result<()> {
pub async fn commit(
&mut self,
chain: &Chain,
node: &GwynethFullNode,
engine_api: &EngineApiContext<GwynethEngineTypes>,
) -> eyre::Result<()> {
let events = decode_chain_into_rollup_events(chain);
for (block, _, event) in events {
// TODO: Don't emit ProposeBlock event but directely
// read the function call RollupContractCalls to extract Txs
// let _call = RollupContractCalls::abi_decode(tx.input(), true)?;

if let RollupContractEvents::BlockProposed(BlockProposed {
blockId: block_number,
meta,
Expand Down Expand Up @@ -148,15 +160,16 @@ impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
let payload_id = builder_attrs.inner.payload_id();
let parrent_beacon_block_root =
builder_attrs.inner.parent_beacon_block_root.unwrap();

// trigger new payload building draining the pool
self.node.payload_builder.new_payload(builder_attrs).await.unwrap();
node.payload_builder.new_payload(builder_attrs).await.unwrap();

// wait for the payload builder to have finished building
let mut payload =
EthBuiltPayload::new(payload_id, SealedBlock::default(), U256::ZERO);
loop {
let result = self.node.payload_builder.best_payload(payload_id).await;
let result = node.payload_builder.best_payload(payload_id).await;

// TODO: There seems to be no result when there's an empty tx list
if let Some(result) = result {
if let Ok(new_payload) = result {
payload = new_payload;
Expand All @@ -174,11 +187,12 @@ impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
}
break;
}

// trigger resolve payload via engine api
self.engine_api.get_payload_v3_value(payload_id).await?;
engine_api.get_payload_v3_value(payload_id).await?;

// submit payload to engine api
let block_hash = self
.engine_api
let block_hash = engine_api
.submit_payload(
payload.clone(),
parrent_beacon_block_root,
Expand All @@ -188,7 +202,7 @@ impl<Node: reth_node_api::FullNodeComponents> Rollup<Node> {
.await?;

// trigger forkchoice update via engine api to commit the block to the blockchain
self.engine_api.update_forkchoice(block_hash, block_hash).await?;
engine_api.update_forkchoice(block_hash, block_hash).await?;
}
}

Expand Down

0 comments on commit 5e2729c

Please sign in to comment.