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

[gwyneth] Add rbuilder to Dockerfile of EL #39

Draft
wants to merge 14 commits into
base: gwyneth
Choose a base branch
from
41 changes: 34 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef
WORKDIR /app

LABEL org.opencontainers.image.source=https://github.com/paradigmxyz/reth
LABEL org.opencontainers.image.licenses="MIT OR Apache-2.0"

# Install system dependencies
RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config
RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config git

# Builds a cargo-chef plan
FROM chef AS planner
Expand All @@ -29,24 +28,52 @@ ENV FEATURES $FEATURES

# Builds dependencies
RUN cargo chef cook --profile $BUILD_PROFILE --features "$FEATURES" --recipe-path recipe.json

# Build application
COPY . .
RUN cargo build --profile $BUILD_PROFILE --features "$FEATURES" --locked --bin reth

# ARG is not resolved in COPY so we have to hack around it by copying the
# binary to a temporary location
# Hack: Add a cache busting step (above steps are the more
# time consuming ones but we need to make sure the rbuilder is
# always freshly cloned and not cached !)
# Since the content of this file will change
# with each build, Docker will consider this
# layer (and all subsequent layers) as modified,
# forcing a re-execution of the following steps.
ADD https://worldtimeapi.org/api/ip /tmp/bustcache

# Clone and build rbuilder (gwyneth branch)
RUN git clone -b gwyneth_get_layer2_info https://github.com/taikoxyz/rbuilder.git /app/rbuilder
WORKDIR /app/rbuilder
RUN cargo build --release

# Copy binaries to a temporary location
RUN cp /app/target/$BUILD_PROFILE/reth /app/reth
RUN cp /app/rbuilder/target/release/rbuilder /app/rbuilder

# Use Ubuntu as the release image
FROM ubuntu AS runtime
FROM ubuntu:22.04 AS runtime
WORKDIR /app

# Copy reth over from the build stage
# Install necessary runtime dependencies and Rust/Cargo
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

# Install Rust and Cargo
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"

# Copy reth and rbuilder binaries over from the build stage
COPY --from=builder /app/reth /usr/local/bin
COPY --from=builder /app/rbuilder /usr/local/bin

# Copy the entire rbuilder repository
COPY --from=builder /app/rbuilder /app/rbuilder

# Copy licenses
COPY LICENSE-* ./

# Create start script
RUN echo '#!/bin/bash\nrbuilder run /app/rbuilder/config-gwyneth-reth.toml' > /app/start_rbuilder.sh && \
chmod +x /app/start_rbuilder.sh

EXPOSE 30303 30303/udp 9001 8545 8546
ENTRYPOINT ["/usr/local/bin/reth"]
6 changes: 3 additions & 3 deletions bin/reth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,11 @@ fn main() -> eyre::Result<()> {
.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())
.set_dev(true);
.with_rpc(RpcServerArgs::default().with_unused_ports().with_static_l2_rpc_ip_and_port(chain_spec.chain.id()));
// .set_dev(true);

let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
.testing_node(exec.clone())
.gwyneth_node(exec.clone(), chain_spec.chain.id())
.node(Default::default())
.launch()
.await?;
Expand Down
4 changes: 3 additions & 1 deletion bin/reth/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use reth::{
};
use reth_node_core::args::RpcServerArgs;
use reth_primitives::{Bytes, B256};
use reth_rpc_builder::constants;

use crate::traits::RpcServerArgsExEx;

Expand All @@ -40,12 +41,13 @@ where
}

impl RpcServerArgsExEx for RpcServerArgs {
fn with_static_l2_rpc_ip_and_port(mut self) -> Self {
fn with_static_l2_rpc_ip_and_port(mut self, chain_id: u64) -> 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);
self
}
}
2 changes: 1 addition & 1 deletion bin/reth/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ impl PayloadEnvelopeExt for ExecutionPayloadEnvelopeV3 {
}
}
pub trait RpcServerArgsExEx {
fn with_static_l2_rpc_ip_and_port(self) -> Self;
fn with_static_l2_rpc_ip_and_port(self, chain_id: u64) -> Self;
}
39 changes: 38 additions & 1 deletion crates/node/builder/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod states;

pub use states::*;

use std::sync::Arc;
use std::{fs, path::PathBuf, sync::Arc};

use futures::Future;
use reth_chainspec::ChainSpec;
Expand Down Expand Up @@ -175,6 +175,38 @@ impl<DB> NodeBuilder<DB> {
WithLaunchContext { builder: self, task_executor }
}

/// Creates an _ephemeral_ preconfigured node for testing purposes.
//#[cfg(feature = "test-utils")]
pub fn gwyneth_node(
mut self,
task_executor: TaskExecutor,
chain_id: u64,
) -> WithLaunchContext<NodeBuilder<Arc<reth_db::test_utils::TempDatabase<reth_db::DatabaseEnv>>>>
{
let folder_name = format!("/data/reth/gwyneth-{}/", chain_id);
let path = reth_node_core::dirs::MaybePlatformPath::<DataDirPath>::from(
PathBuf::from(folder_name.clone()),
);

println!("path: {:?}", folder_name);

fs::create_dir_all(folder_name).expect("gwyneth db dir creation failed");

self.config = self.config.with_datadir_args(reth_node_core::args::DatadirArgs {
datadir: path.clone(),
..Default::default()
});

let data_dir =
path.unwrap_or_chain_default(self.config.chain.chain, self.config.datadir.clone());

println!("data_dir: {:?}", data_dir);

let db = reth_db::test_utils::create_test_rw_db_with_path(data_dir.db());

WithLaunchContext { builder: self.with_database(db), task_executor }
}

/// Creates an _ephemeral_ preconfigured node for testing purposes.
//#[cfg(feature = "test-utils")]
pub fn testing_node(
Expand All @@ -185,6 +217,9 @@ impl<DB> NodeBuilder<DB> {
let path = reth_node_core::dirs::MaybePlatformPath::<DataDirPath>::from(
reth_db::test_utils::tempdir_path(),
);

println!("path: {:?}", path);

self.config = self.config.with_datadir_args(reth_node_core::args::DatadirArgs {
datadir: path.clone(),
..Default::default()
Expand All @@ -193,6 +228,8 @@ impl<DB> NodeBuilder<DB> {
let data_dir =
path.unwrap_or_chain_default(self.config.chain.chain, self.config.datadir.clone());

println!("data_dir: {:?}", data_dir);

let db = reth_db::test_utils::create_test_rw_db_with_path(data_dir.db());

WithLaunchContext { builder: self.with_database(db), task_executor }
Expand Down
69 changes: 69 additions & 0 deletions packages/protocol/scripts/L2_txn_simulation/sendTx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from web3 import Web3
from eth_abi import encode
import argparse

RPC_URL_L2 = 'http://127.0.0.1:' # Anything is fine for now as long as we dont have the L2 network, but if we have we can automate nonce and gas settings
w3_taiko_l2 = Web3(Web3.HTTPProvider(RPC_URL_L2))

# Some pre-loaded ETH addresses from Kurtosis private network (NO secret, no harm to use for private testnets!)
sender_addresses = ['0x8943545177806ED17B9F23F0a21ee5948eCaa776']
sender_pks = ['bcdf20249abf0ed6d944c0288fad489e33f66b3960d9e6229c1cd214ed3bbe31']

receiver = '0xf93Ee4Cf8c6c40b329b0c0626F28333c132CF241' # This address also has pre-loaded ETH addresses

parser = argparse.ArgumentParser()

parser.add_argument("-p", "--port", help="port on localhost",
type=str, required=True)
# parser.add_argument("-c", "--chainid", help="l2 chainId",
# type=int, required=True)

transaction_list = []

if __name__ == "__main__":
args = parser.parse_args()
port = args.port
w3_taiko_l2 = Web3(Web3.HTTPProvider(RPC_URL_L2+port))
chainId = 167010

# Build the new tx list
idx = 0
for sender in sender_addresses:
# Build the tx
transaction = {
'chainId': chainId,
'from': sender,
'to': receiver,
'value': w3_taiko_l2.to_wei('1', 'ether'),
'nonce': w3_taiko_l2.eth.get_transaction_count(sender),
'gas': 200000,
'maxFeePerGas': 2000000000, # w3_taiko_l2.eth.gas_price or something
'maxPriorityFeePerGas': 1000000000,
}

# Debug prints of balance
# # Get the balance
# balance_wei = w3_taiko_l2.eth.get_balance(sender)

# # Convert balance from Wei to Ether
# balance_eth = w3_taiko_l2.from_wei(balance_wei, 'ether')
# print("Balance before:", balance_eth)

# 2. Sign tx with a private key
signed_txn = w3_taiko_l2.eth.account.sign_transaction(transaction, sender_pks[idx])

# print("RawTransaction:")
# print(signed_txn.rawTransaction)
print("RawTransaction.hex():")
print(signed_txn.rawTransaction.hex())

txn_hash = w3_taiko_l2.eth.send_raw_transaction(signed_txn.rawTransaction)
print("Txn hash:")
print(txn_hash.hex())

# # Get the balance
# balance_wei = w3_taiko_l2.eth.get_balance(sender)

# # Convert balance from Wei to Ether
# balance_eth = w3_taiko_l2.from_wei(balance_wei, 'ether')
# print("Balance after:", balance_eth)
1 change: 1 addition & 0 deletions packages/protocol/scripts/confs/network_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ participants:
el_image: taiko_reth
cl_type: lighthouse
cl_image: sigp/lighthouse:latest
cl_extra_params: [--always-prepare-payload, --prepare-payload-lookahead, "12000"]
- el_type: reth
el_image: taiko_reth
cl_type: teku
Expand Down
71 changes: 56 additions & 15 deletions packages/protocol/scripts/setup_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ else
fi

# Check if the taiko_reth image exists
#if ! docker image inspect taiko_reth >/dev/null 2>&1; then
echo "Docker image taiko_reth does not exist. Building the image..."
if ! docker build ../../ -t taiko_reth; then
echo "Failed to build the Docker image taiko_reth."
exit 1
fi
#else
# echo "Docker image taiko_reth already exists."
#fi
# if ! docker image inspect taiko_reth >/dev/null 2>&1; then
echo "Docker image taiko_reth does not exist. Building the image..."
if ! docker build ../../ -t taiko_reth; then
echo "Failed to build the Docker image taiko_reth."
exit 1
fi
# else
# echo "Docker image taiko_reth already exists."
# fi

# Function to install Kurtosis on macOS
install_kurtosis_mac() {
Expand Down Expand Up @@ -86,20 +86,17 @@ fi
echo "Running Kurtosis command..."
KURTOSIS_OUTPUT=$(kurtosis run github.com/adaki2004/ethereum-package --args-file ./scripts/confs/network_params.yaml)

# Print the entire Kurtosis output for debugging
# # Print the entire Kurtosis output for debugging
# echo "Kurtosis Output:"
# echo "$KURTOSIS_OUTPUT"

# Extract the "User Services" section
USER_SERVICES_SECTION=$(echo "$KURTOSIS_OUTPUT" | awk '/^========================================== User Services ==========================================/{flag=1;next}/^$/{flag=0}flag')

# Print the "User Services" section for debugging
echo "User Services Section:"
echo "$USER_SERVICES_SECTION"

# Extract the dynamic port assigned to the rpc service for "el-1-reth-lighthouse"
RPC_PORT=$(echo "$USER_SERVICES_SECTION" | grep -A 5 "el-1-reth-lighthouse" | grep "rpc: 8545/tcp" | sed -E 's/.* -> 127.0.0.1:([0-9]+).*/\1/')

if [ -z "$RPC_PORT" ]; then
echo "Failed to extract RPC port from User Services section."
exit 1
Expand All @@ -108,6 +105,52 @@ else
echo "$RPC_PORT" > /tmp/kurtosis_rpc_port
fi

# Extract the Starlark output section
STARLARK_OUTPUT=$(echo "$KURTOSIS_OUTPUT" | awk '/^Starlark code successfully run. Output was:/{flag=1; next} /^$/{flag=0} flag')

# Extract the beacon_http_url for cl-1-lighthouse-reth
BEACON_HTTP_URL=$(echo "$STARLARK_OUTPUT" | jq -r '.all_participants[] | select(.cl_context.beacon_service_name == "cl-1-lighthouse-reth") | .cl_context.beacon_http_url')

if [ -z "$BEACON_HTTP_URL" ]; then
echo "Failed to extract beacon_http_url for cl-1-lighthouse-reth."
exit 1
else
echo "Extracted beacon_http_url: $BEACON_HTTP_URL"
echo "$BEACON_HTTP_URL" > /tmp/kurtosis_beacon_http_url
fi

# Find the correct Docker container
CONTAINER_ID=$(docker ps --format '{{.ID}} {{.Names}}' | grep 'el-1-reth-lighthouse--' | awk '{print $1}')

if [ -z "$CONTAINER_ID" ]; then
echo "Failed to find the el-1-reth-lighthouse container."
exit 1
else
echo "Found container ID: $CONTAINER_ID"
fi

# Check if the file exists in the container
FILE_PATH="/app/rbuilder/config-gwyneth-reth.toml"
if ! docker exec "$CONTAINER_ID" test -f "$FILE_PATH"; then
echo "File $FILE_PATH does not exist in the container."
exit 1
fi

# Update the cl_node_url in the file, regardless of its current content
ESCAPED_URL=$(echo "$BEACON_HTTP_URL" | sed 's/[\/&]/\\&/g')
UPDATE_COMMAND="sed -i '/^cl_node_url[[:space:]]*=/c\cl_node_url = [\"$ESCAPED_URL\"]' $FILE_PATH"

if docker exec "$CONTAINER_ID" sh -c "$UPDATE_COMMAND"; then
echo "Successfully updated $FILE_PATH in the container."
else
echo "Failed to update $FILE_PATH in the container."
exit 1
fi

# Verify the change
VERIFY_COMMAND="grep 'cl_node_url' $FILE_PATH"
VERIFICATION=$(docker exec "$CONTAINER_ID" sh -c "$VERIFY_COMMAND")
echo "Updated line in $FILE_PATH: $VERIFICATION"
# Load the .env file and extract the PRIVATE_KEY
if [ -f .env ]; then
export $(grep -v '^#' .env | xargs)
Expand All @@ -116,12 +159,10 @@ else
echo ".env file not found. Please create a .env file with your PRIVATE_KEY."
exit 1
fi

if [ -z "$PRIVATE_KEY" ]; then
echo "PRIVATE_KEY not found in the .env file."
exit 1
fi

# Run the forge foundry script using the extracted RPC port and PRIVATE_KEY
FORGE_COMMAND="forge script --rpc-url http://127.0.0.1:$RPC_PORT scripts/DeployL1Locally.s.sol -vvvv --broadcast --private-key $PRIVATE_KEY --legacy"
echo "Running forge foundry script..."
Expand Down