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

feat(l2): integration test + SDK first version #1004

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"crates/l2/",
"crates/l2/prover",
"crates/l2/contracts",
"crates/l2/sdk",
]
resolver = "2"

Expand Down
3 changes: 1 addition & 2 deletions crates/blockchain/dev/docker-compose-dev.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

version: '3.2'
services:
ethereum_rust:
restart: always
container_name: ethereum_rust_l1
image: "ethereum_rust_dev"
build:
context: ../../../
Expand Down
4 changes: 4 additions & 0 deletions crates/l2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ c-kzg = "^1.0.3"
# risc0
risc0-zkvm = { version = "1.1.2" }

[dev-dependencies]
ethereum_rust-sdk = { path = "./sdk" }
rand = "0.8.5"


[lib]
path = "./l2.rs"
51 changes: 51 additions & 0 deletions crates/l2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM rust:1.80 AS chef

RUN apt-get update && apt-get install -y \
build-essential \
libclang-dev \
libc6 \
libssl-dev \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN cargo install cargo-chef

WORKDIR /ethereum_rust

FROM chef AS planner
COPY . .
# Determine the crates that need to be built from dependencies
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
COPY --from=planner /ethereum_rust/recipe.json recipe.json
# Build dependencies only, these remained cached
RUN cargo chef cook --release --recipe-path recipe.json

ENV ETH_RPC_URL=http://ethereum_rust_dev:8545
ENV L1_WATCHER_BRIDGE_ADDRESS=${L1_WATCHER_BRIDGE_ADDRESS}
ENV L1_WATCHER_TOPICS=${L1_WATCHER_TOPICS}
ENV L1_WATCHER_CHECK_INTERVAL_MS=${L1_WATCHER_CHECK_INTERVAL_MS}
ENV L1_WATCHER_MAX_BLOCK_STEP=${L1_WATCHER_MAX_BLOCK_STEP}
ENV L1_WATCHER_L2_PROPOSER_PRIVATE_KEY=${L1_WATCHER_L2_PROPOSER_PRIVATE_KEY}
ENV ENGINE_API_RPC_URL=${ENGINE_API_RPC_URL}
ENV ENGINE_API_JWT_PATH=${ENGINE_API_JWT_PATH}
ENV PROVER_SERVER_LISTEN_IP=${PROVER_SERVER_LISTEN_IP}
ENV PROVER_SERVER_LISTEN_PORT=${PROVER_SERVER_LISTEN_PORT}
ENV PROVER_PROVER_SERVER_ENDPOINT=${PROVER_PROVER_SERVER_ENDPOINT}
ENV PROVER_ELF_PATH=${PROVER_ELF_PATH}
ENV PROPOSER_ON_CHAIN_PROPOSER_ADDRESS=${PROPOSER_ON_CHAIN_PROPOSER_ADDRESS}
ENV PROPOSER_L1_ADDRESS=${PROPOSER_L1_ADDRESS}
ENV PROPOSER_L1_PRIVATE_KEY=${PROPOSER_L1_PRIVATE_KEY}
ENV PROPOSER_INTERVAL_MS=${PROPOSER_INTERVAL_MS}
ENV DEPLOYER_ADDRESS=${DEPLOYER_ADDRESS}
ENV DEPLOYER_PRIVATE_KEY=${DEPLOYER_PRIVATE_KEY}

COPY . .
RUN cargo build --release --features l2

FROM ubuntu:24.04
WORKDIR /usr/local/bin

COPY --from=builder ethereum_rust/target/release/ethereum_rust .
EXPOSE 1729
ENTRYPOINT [ "./ethereum_rust" ]
10 changes: 9 additions & 1 deletion crates/l2/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.DEFAULT_GOAL := help

.PHONY: help init down clean init-local-l1 down-local-l1 clean-local-l1 init-l2 down-l2 deploy-l1 deploy-block-executor deploy-inbox setup-prover
.PHONY: help init down clean init-local-l1 down-local-l1 clean-local-l1 init-l2 down-l2 deploy-l1 deploy-block-executor deploy-inbox setup-prover test

L2_GENESIS_FILE_PATH=../../test_data/genesis-l2.json

Expand All @@ -23,6 +23,7 @@ cli: ## 🛠️ Installs the L2 Lambda Ethereum Rust CLI
ETHEREUM_RUST_PATH=$(shell pwd)/../..
ETHEREUM_RUST_BIN_PATH=$(ETHEREUM_RUST_PATH)/target/release/ethereum_rust
ETHEREUM_RUST_DEV_DOCKER_COMPOSE_PATH=$(ETHEREUM_RUST_PATH)/crates/blockchain/dev/docker-compose-dev.yaml
ETHEREUM_RUST_L2_DOCKER_COMPOSE_PATH=./docker-compose-l2.yaml

ETHEREUM_RUST_L2_CONTRACTS_PATH=./contracts
L1_RPC_URL=http://localhost:8545
Expand Down Expand Up @@ -64,3 +65,10 @@ init-l2-prover: ## 🚀 Initializes the Prover

init-l2-prover-gpu: ## 🚀 Initializes the Prover with GPU support
cargo run --release --features "build_zkvm,cuda" --manifest-path ../../Cargo.toml --bin ethereum_rust_prover

# CI Testing

test:
docker compose -f ${ETHEREUM_RUST_L2_DOCKER_COMPOSE_PATH} up -d
cargo test --release testito
docker compose -f ${ETHEREUM_RUST_L2_DOCKER_COMPOSE_PATH} down
1 change: 1 addition & 0 deletions crates/l2/contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bytes = { version = "1.6.0", features = ["serde"] }
libsecp256k1 = "0.7.1"
keccak-hash = "0.10.0"
hex = "0.4.3"
tracing.workspace = true

ethereum_rust-l2 = { path = "../../l2" }
ethereum_rust-core = { path = "../../common" }
Expand Down
62 changes: 62 additions & 0 deletions crates/l2/contracts/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
FROM rust:1.80 AS chef

RUN apt-get update && apt-get install -y \
build-essential \
libclang-dev \
libc6 \
libssl-dev \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN cargo install cargo-chef

WORKDIR /ethereum_rust

FROM chef AS planner

COPY Cargo.toml ./Cargo.toml
COPY crates/blockchain/Cargo.toml crates/blockchain/Cargo.toml
COPY crates/blockchain/dev/Cargo.toml crates/blockchain/dev/Cargo.toml
COPY crates/common/Cargo.toml crates/common/Cargo.toml
COPY crates/networking/p2p/Cargo.toml crates/networking/p2p/Cargo.toml
COPY crates/networking/rpc/Cargo.toml crates/networking/rpc/Cargo.toml
COPY crates/storage/store/Cargo.toml crates/storage/store/Cargo.toml
COPY crates/vm/Cargo.toml crates/vm/Cargo.toml
COPY crates/storage/trie/Cargo.toml crates/storage/trie/Cargo.toml
COPY crates/common/rlp/Cargo.toml crates/common/rlp/Cargo.toml
COPY cmd/ethereum_rust/Cargo.toml cmd/ethereum_rust/Cargo.toml
COPY cmd/ef_tests/Cargo.toml cmd/ef_tests/Cargo.toml
COPY cmd/ef_tests/tests cmd/ef_tests/tests
COPY cmd/ethereum_rust_l2/Cargo.toml cmd/ethereum_rust_l2/Cargo.toml
COPY crates/vm/levm/Cargo.toml crates/vm/levm/Cargo.toml
COPY crates/vm/levm/bench/revm_comparison/Cargo.toml crates/vm/levm/bench/revm_comparison/Cargo.toml
COPY crates/l2/Cargo.toml crates/l2/Cargo.toml
COPY crates/l2/contracts/Cargo.toml crates/l2/contracts/Cargo.toml
COPY crates/l2/sdk/Cargo.toml crates/l2/sdk/Cargo.toml
COPY crates/l2/prover/Cargo.toml crates/l2/prover/Cargo.toml
COPY crates/l2/prover/zkvm/Cargo.toml crates/l2/prover/zkvm/Cargo.toml
COPY crates/l2/prover/zkvm/interface/Cargo.toml crates/l2/prover/zkvm/interface/Cargo.toml

# Determine the crates that need to be built from dependencies
RUN cargo chef prepare --bin ethereum_rust_l2_l1_deployer --recipe-path recipe.json

FROM chef AS builder
COPY --from=planner /ethereum_rust/recipe.json recipe.json
# Build dependencies only, these remained cached
RUN cargo chef cook --release --recipe-path recipe.json --manifest-path crates/l2/contracts/Cargo.toml --bin ethereum_rust_l2_l1_deployer

COPY . .
RUN cargo build --release --manifest-path crates/l2/contracts/Cargo.toml

FROM ubuntu:24.04
WORKDIR /usr/local/bin

RUN apt-get update && apt-get -y install git gnupg
RUN echo 'deb https://ppa.launchpadcontent.net/ethereum/ethereum/ubuntu noble main' > /etc/apt/sources.list.d/ethereum-ethereum-noble.list && \
echo 'deb-src https://ppa.launchpadcontent.net/ethereum/ethereum/ubuntu noble main' >> /etc/apt/sources.list.d/ethereum-ethereum-noble.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E66CB8FE57F8218E96B13446B50ABD2EE384B7D4
RUN apt-get update && apt-get -y install solc

COPY --from=builder ethereum_rust/target/release/ethereum_rust_l2_l1_deployer .

EXPOSE 1729
ENTRYPOINT [ "./ethereum_rust_l2_l1_deployer" ]
83 changes: 63 additions & 20 deletions crates/l2/contracts/deployer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ use ethereum_rust_l2::utils::{
use ethereum_types::{Address, H160, H256};
use keccak_hash::keccak;
use libsecp256k1::SecretKey;
use std::{process::Command, str::FromStr};
use std::{
path::{Path, PathBuf},
process::Command,
str::FromStr,
};
use tracing::warn;

// 0x4e59b44847b379578588920cA78FbF26c0B4956C
const DETERMINISTIC_CREATE2_ADDRESS: Address = H160([
Expand All @@ -18,11 +23,11 @@ const SALT: H256 = H256::zero();

#[tokio::main]
async fn main() {
let (deployer, deployer_private_key, eth_client) = setup();
download_contract_deps();
compile_contracts();
let (deployer, deployer_private_key, eth_client, contracts_path) = setup();
download_contract_deps(&contracts_path);
compile_contracts(&contracts_path);
let (on_chain_proposer, bridge_address) =
deploy_contracts(deployer, deployer_private_key, &eth_client).await;
deploy_contracts(deployer, deployer_private_key, &eth_client, &contracts_path).await;
initialize_contracts(
deployer,
deployer_private_key,
Expand All @@ -33,8 +38,11 @@ async fn main() {
.await;
}

fn setup() -> (Address, SecretKey, EthClient) {
read_env_file().expect("Failed to read .env file");
fn setup() -> (Address, SecretKey, EthClient, PathBuf) {
if let Err(e) = read_env_file() {
warn!("Failed to read .env file: {e}");
}

let eth_client = EthClient::new(&std::env::var("ETH_RPC_URL").expect("ETH_RPC_URL not set"));
let deployer = std::env::var("DEPLOYER_ADDRESS")
.expect("DEPLOYER_ADDRESS not set")
Expand All @@ -51,31 +59,49 @@ fn setup() -> (Address, SecretKey, EthClient) {
.as_fixed_bytes(),
)
.expect("Malformed DEPLOYER_PRIVATE_KEY (SecretKey::parse)");
let contracts_path = Path::new(
std::env::var("DEPLOYER_CONTRACTS_PATH")
.unwrap_or(".".to_string())
.as_str(),
)
.to_path_buf();

(deployer, deployer_private_key, eth_client)
(deployer, deployer_private_key, eth_client, contracts_path)
}

fn download_contract_deps() {
std::fs::create_dir_all("contracts/lib").expect("Failed to create contracts/lib");
fn download_contract_deps(contracts_path: &Path) {
std::fs::create_dir_all(contracts_path.join("lib")).expect("Failed to create contracts/lib");
Command::new("git")
.arg("clone")
.arg("https://github.com/OpenZeppelin/openzeppelin-contracts.git")
.arg("contracts/lib/openzeppelin-contracts")
.arg(
contracts_path
.join("lib/openzeppelin-contracts")
.to_str()
.unwrap(),
)
.spawn()
.expect("Failed to spawn git")
.wait()
.expect("Failed to wait for git");
}

fn compile_contracts() {
fn compile_contracts(contracts_path: &Path) {
// Both the contract path and the output path are relative to where the Makefile is.
assert!(
Command::new("solc")
.arg("--bin")
.arg("./contracts/src/l1/OnChainProposer.sol")
.arg(
contracts_path
.join("src/l1/OnChainProposer.sol")
.to_str()
.unwrap()
)
.arg("-o")
.arg("contracts/solc_out")
.arg(contracts_path.join("solc_out").to_str().unwrap())
.arg("--overwrite")
.arg("--allow-paths")
.arg(contracts_path.to_str().unwrap())
.spawn()
.expect("Failed to spawn solc")
.wait()
Expand All @@ -87,10 +113,17 @@ fn compile_contracts() {
assert!(
Command::new("solc")
.arg("--bin")
.arg("./contracts/src/l1/CommonBridge.sol")
.arg(
contracts_path
.join("src/l1/CommonBridge.sol")
.to_str()
.unwrap()
)
.arg("-o")
.arg("contracts/solc_out")
.arg(contracts_path.join("solc_out").to_str().unwrap())
.arg("--overwrite")
.arg("--allow-paths")
.arg(contracts_path.to_str().unwrap())
.spawn()
.expect("Failed to spawn solc")
.wait()
Expand All @@ -104,6 +137,7 @@ async fn deploy_contracts(
deployer: Address,
deployer_private_key: SecretKey,
eth_client: &EthClient,
contracts_path: &Path,
) -> (Address, Address) {
let overrides = Overrides {
gas_limit: Some(GAS_LIMIT_MINIMUM * GAS_LIMIT_ADJUSTMENT_FACTOR),
Expand All @@ -117,15 +151,22 @@ async fn deploy_contracts(
deployer_private_key,
overrides.clone(),
eth_client,
contracts_path,
)
.await;
println!(
"OnChainProposer deployed at address {:#x} with tx hash {:#x}",
on_chain_proposer_address, on_chain_proposer_deployment_tx_hash
);

let (bridge_deployment_tx_hash, bridge_address) =
deploy_bridge(deployer, deployer_private_key, overrides, eth_client).await;
let (bridge_deployment_tx_hash, bridge_address) = deploy_bridge(
deployer,
deployer_private_key,
overrides,
eth_client,
contracts_path,
)
.await;
println!(
"Bridge deployed at address {:#x} with tx hash {:#x}",
bridge_address, bridge_deployment_tx_hash
Expand All @@ -139,9 +180,10 @@ async fn deploy_on_chain_proposer(
deployer_private_key: SecretKey,
overrides: Overrides,
eth_client: &EthClient,
contracts_path: &Path,
) -> (H256, Address) {
let on_chain_proposer_init_code = hex::decode(
std::fs::read_to_string("./contracts/solc_out/OnChainProposer.bin")
std::fs::read_to_string(contracts_path.join("solc_out/OnChainProposer.bin"))
.expect("Failed to read on_chain_proposer_init_code"),
)
.expect("Failed to decode on_chain_proposer_init_code")
Expand All @@ -164,9 +206,10 @@ async fn deploy_bridge(
deployer_private_key: SecretKey,
overrides: Overrides,
eth_client: &EthClient,
contracts_path: &Path,
) -> (H256, Address) {
let mut bridge_init_code = hex::decode(
std::fs::read_to_string("./contracts/solc_out/CommonBridge.bin")
std::fs::read_to_string(contracts_path.join("solc_out/CommonBridge.bin"))
.expect("Failed to read bridge_init_code"),
)
.expect("Failed to decode bridge_init_code");
Expand Down
40 changes: 40 additions & 0 deletions crates/l2/docker-compose-l2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
include:
- ../blockchain/dev/docker-compose-dev.yaml

services:
contract_deployer:
container_name: contract_deployer
image: ethereum_rust_l2_contract_deployer
build:
context: ../../
dockerfile: ./crates/l2/contracts/Dockerfile
volumes:
- ./contracts:/contracts
env_file:
- .env
environment:
- ETH_RPC_URL=http://ethereum_rust_l1:8545
- DEPLOYER_CONTRACTS_PATH=/contracts
depends_on:
- ethereum_rust
restart: on-failure:3

ethereum_rust_l2:
restart: always
container_name: ethereum_rust_l2
image: "ethereum_rust_l2"
build:
context: ../../
dockerfile: ./crates/l2/Dockerfile
ports:
- 127.0.0.1:1729:1729
env_file:
- .env
environment:
- ETH_RPC_URL=http://ethereum_rust_l1:8545
volumes:
- ../../test_data/genesis-l2.json:/genesis-l2.json
command: --network /genesis-l2.json --http.addr 0.0.0.0 --http.port 1729
depends_on:
contract_deployer:
condition: service_completed_successfully
Loading
Loading