Skip to content

Commit 76216a4

Browse files
colinlyguocolinlyguojonastheis
authored
feat: integrate l2geth in docker-compose e2e tests (#227)
* feat: integrate l2geth in docker-compose e2e tests * support local genesis * address comments * fix CI * update scripts * increase log level * update gas limits * update reth commit * cargo.lock * fix compile errors * add initial test * fix lint * launch l2geth sequencer and read active signer from L1 * launch l2geth follower * fix issue with custom genesis where fields are missing and mixed up * adjust chain id to arbitrary number to avoid conflict with named chain * rollup node follower can follow chain produced by l2geth sequencer * configure rollup node sequencer correctly and connect to other nodes * add health check for l1-node to make sure it is fully set up before l2 nodes start * refactor DockerComposeEnv and add more convenience functions for tests to control sequencer. RN sequencer and l2geth sequencer start without producing blocks automatically. * fix CI * remove todos * avoid building Docker image when only Docker integration test changes --------- Co-authored-by: colinlyguo <[email protected]> Co-authored-by: jonastheis <[email protected]>
1 parent f37cea0 commit 76216a4

23 files changed

+779
-246
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ alloy-consensus = { version = "1.0.13", default-features = false }
123123
alloy-eips = { version = "1.0.13", default-features = false }
124124
alloy-json-rpc = { version = "1.0.13", default-features = false }
125125
alloy-network = { version = "1.0.13", default-features = false }
126-
alloy-primitives = { version = "1.2.0", default-features = false }
126+
alloy-primitives = { version = "1.3.1", default-features = false }
127127
alloy-provider = { version = "1.0.13", default-features = false }
128128
alloy-rpc-client = { version = "1.0.13", default-features = false }
129129
alloy-rpc-types-engine = { version = "1.0.13", default-features = false }
@@ -185,7 +185,7 @@ scroll-wire = { path = "crates/scroll-wire" }
185185
scroll-migration = { path = "crates/database/migration" }
186186

187187
# misc
188-
arbitrary = { version = "1.4", default-features = false }
188+
arbitrary = { version = "1.4", default-features = false, features = ["derive"] }
189189
async-trait = "0.1"
190190
auto_impl = "1.2"
191191
bitvec = { version = "1.0", default-features = false }

Dockerfile.test

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
FROM rust:1.88.0 AS chef
2+
3+
ARG CARGO_FEATURES=""
4+
5+
# Install basic packages
6+
RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config
7+
RUN cargo install cargo-chef --locked --version 0.1.71
8+
9+
FROM chef AS planner
10+
WORKDIR /app
11+
12+
COPY . .
13+
# Hacky: Replace tests with dummy stub to avoid workspace member issues of top-level Cargo.toml.
14+
# This is needed because within the Docker integration tests we don't need the tests crate
15+
# and want to avoid rebuilding it on every change.
16+
RUN mkdir -p tests/src && \
17+
echo '[package]' > tests/Cargo.toml && \
18+
echo 'name = "tests"' >> tests/Cargo.toml && \
19+
echo 'version = "0.0.1"' >> tests/Cargo.toml && \
20+
echo 'edition = "2021"' >> tests/Cargo.toml && \
21+
echo '' >> tests/Cargo.toml && \
22+
echo '[lib]' >> tests/Cargo.toml && \
23+
echo 'name = "tests"' >> tests/Cargo.toml && \
24+
echo 'path = "src/lib.rs"' >> tests/Cargo.toml && \
25+
echo 'pub fn dummy() {}' > tests/src/lib.rs
26+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
27+
cargo chef prepare --recipe-path /recipe.json
28+
29+
FROM chef AS builder
30+
WORKDIR /app
31+
COPY --from=planner /recipe.json recipe.json
32+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
33+
cargo chef cook --release --recipe-path recipe.json
34+
35+
COPY . .
36+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
37+
cargo build ${CARGO_FEATURES:+--features $CARGO_FEATURES} --release --target-dir=/app-target
38+
39+
# Release
40+
FROM debian:bookworm-slim
41+
42+
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl sqlite3 && \
43+
rm -rf /var/lib/apt/lists/*
44+
45+
WORKDIR /app
46+
47+
COPY --from=builder /app-target/release/rollup-node /bin/
48+
49+
EXPOSE 30303 30303/udp 9001 8545 8546
50+
51+
ENTRYPOINT ["rollup-node"]

Dockerfile.test.dockerignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# exclude everything
2+
*
3+
4+
# include source files
5+
!/bin
6+
!/crates
7+
!/testing
8+
!book.toml
9+
!Cargo.lock
10+
!Cargo.toml
11+
!Cross.toml
12+
!deny.toml
13+
!Makefile
14+

crates/node/src/args.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ impl ScrollRollupNodeConfig {
211211
db.insert_genesis_block(genesis_hash)
212212
.await
213213
.expect("failed to insert genesis block (custom chain)");
214+
215+
tracing::info!(target: "scroll::node::args", ?genesis_hash, "Overwriting genesis hash for custom chain");
214216
}
215217

216218
// Wrap the database in an Arc

crates/node/tests/e2e.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,9 +1322,10 @@ async fn test_custom_genesis_block_production_and_propagation() -> eyre::Result<
13221322
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
13231323
"l1MessageQueueV2Address": "0x000000000000000000000000000000000003dead",
13241324
"scrollChainAddress": "0x000000000000000000000000000000000003dead",
1325-
"l2SystemConfigAddress": "0x000000000000000000000000000000000003dead",
1325+
"l2SystemConfigAddress": "0x0000000000000000000000000000000dddd3dead",
1326+
"systemContractAddress": "0x110000000000000000000000000000000003dead",
13261327
"numL1MessagesPerBlock": 10,
1327-
"l1MessageQueueV2DeploymentBlock": 12345
1328+
"startL1Block": 12345
13281329
}
13291330
}
13301331
},

crates/primitives/src/node/config.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,27 +96,59 @@ impl NodeConfig {
9696
return Ok(Self::from_named_chain(named_chain));
9797
}
9898

99+
// Note: It is important to make sure the chain id is not a named chain accidentally.
100+
// For example, a custom `chain id=1337` will be treated as a named chain as it
101+
// matches the dev chain. https://github.com/scroll-tech/rollup-node/issues/303
99102
// If not a named chain, extract the configuration from the chain spec
100103
let config = chain_spec.chain_config();
101104

102105
let genesis = chain_spec.genesis();
103-
let l1_message_queue_v2_deployment_block = genesis
106+
107+
// let l1_message_queue_v2_deployment_block = genesis
108+
// .config
109+
// .extra_fields
110+
// .get("scroll")
111+
// .and_then(|scroll| scroll.get("l1Config"))
112+
// .and_then(|l1_config| l1_config.get("l1MessageQueueV2DeploymentBlock"))
113+
// .and_then(|v| v.as_u64())
114+
// .ok_or_else(|| eyre::eyre!("Invalid or missing 'l1MessageQueueV2DeploymentBlock'"))?;
115+
116+
let start_l1_block = genesis
104117
.config
105118
.extra_fields
106119
.get("scroll")
107120
.and_then(|scroll| scroll.get("l1Config"))
108-
.and_then(|l1_config| l1_config.get("l1MessageQueueV2DeploymentBlock"))
121+
.and_then(|l1_config| l1_config.get("startL1Block"))
109122
.and_then(|v| v.as_u64())
110-
.ok_or_else(|| eyre::eyre!("Invalid or missing 'l1MessageQueueV2DeploymentBlock'"))?;
123+
.ok_or_else(|| eyre::eyre!("Invalid or missing 'startL1Block'"))?;
124+
125+
let system_contract_address = genesis
126+
.config
127+
.extra_fields
128+
.get("scroll")
129+
.and_then(|scroll| scroll.get("l1Config"))
130+
.and_then(|l1_config| l1_config.get("systemContractAddress"))
131+
.and_then(|v| v.as_str())
132+
.and_then(|s| s.parse().ok())
133+
.ok_or_else(|| eyre::eyre!("Invalid or missing 'systemContractAddress'"))?;
134+
135+
// TODO:
136+
// - config.l1_config.l2_system_config_address is not used here.
137+
// - start_l1_block is not present currently in the config.
138+
// - system_contract_address is not extracted from the config in https://github.com/scroll-tech/reth/blob/scroll/crates/scroll/chainspec/src/genesis.rs#L20
139+
// - do we need: l1_message_queue_v2_deployment_block? maybe instead we could use
140+
// v2_message_queue_starting_index
141+
// - ultimately we want to make sure all relevant config is extracted from `ScrollChainInfo`
142+
// and not partially here. see https://github.com/scroll-tech/rollup-node/issues/303
111143

112144
Ok(Self {
113145
address_book: ScrollAddressBook {
114146
rollup_node_contract_address: config.l1_config.scroll_chain_address,
115147
v1_message_queue_address: config.l1_config.l1_message_queue_address,
116148
v2_message_queue_address: config.l1_config.l1_message_queue_v2_address,
117-
system_contract_address: config.l1_config.l2_system_config_address,
149+
system_contract_address,
118150
},
119-
start_l1_block: l1_message_queue_v2_deployment_block,
151+
start_l1_block,
120152
})
121153
}
122154

tests/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ tokio = { workspace = true, features = ["rt", "time"] }
1717
eyre = { workspace = true }
1818
getrandom = { workspace = true }
1919
tracing = { workspace = true }
20+
reth-tracing = { workspace = true }
21+
serde = { workspace = true }
22+
serde_json = "1.0"

tests/discovery-secret

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/docker-compose.test.yml

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,91 @@
1-
version: '3.8'
2-
31
services:
2+
l1-node:
3+
image: ghcr.io/foundry-rs/foundry:latest
4+
container_name: l1-node
5+
entrypoint: [ "bash", "/launch_l1.bash" ]
6+
ports:
7+
- "8544:8545"
8+
volumes:
9+
- ./launch_l1.bash:/launch_l1.bash:ro
10+
healthcheck:
11+
test: ["CMD", "bash", "-c", "[ \"$(cast storage 0x55B150d210356452e4E79cCb6B778b4e1B167091 0x67 --rpc-url http://localhost:8545)\" = \"0x000000000000000000000000b674ff99cca262c99d3eab5b32796a99188543da\" ]"]
12+
interval: 3s
13+
timeout: 10s
14+
retries: 30
15+
start_period: 0s
16+
417
rollup-node-sequencer:
518
build:
619
context: ../
7-
dockerfile: Dockerfile
20+
dockerfile: Dockerfile.test
821
container_name: rollup-node-sequencer
922
entrypoint: ["bash", "/launch_rollup_node_sequencer.bash"]
1023
environment:
11-
- ENV=dev
1224
- RUST_LOG=info
1325
ports:
1426
- "8545:8545" # JSON-RPC
15-
- "8546:8546" # WebSocket
1627
- "6060:6060" # Metrics
1728
volumes:
1829
- ./launch_rollup_node_sequencer.bash:/launch_rollup_node_sequencer.bash:ro
19-
- ./discovery-secret:/l2reth/discovery-secret:ro
30+
- ./l2reth-genesis-e2e.json:/l2reth/l2reth-genesis-e2e.json:ro
2031
- l2reth-sequencer:/l2reth
21-
networks:
22-
- test-scroll-network
32+
depends_on:
33+
l1-node:
34+
condition: service_healthy
2335

2436
rollup-node-follower:
2537
build:
2638
context: ../
27-
dockerfile: Dockerfile
39+
dockerfile: Dockerfile.test
2840
container_name: rollup-node-follower
2941
entrypoint: ["bash", "/launch_rollup_node_follower.bash"]
3042
environment:
31-
- ENV=dev
3243
- RUST_LOG=info
3344
ports:
34-
- "8547:8545" # JSON-RPC
35-
- "8548:8546" # WebSocket
45+
- "8546:8545" # JSON-RPC
3646
- "6061:6060" # Metrics
3747
volumes:
3848
- ./launch_rollup_node_follower.bash:/launch_rollup_node_follower.bash:ro
49+
- ./l2reth-genesis-e2e.json:/l2reth/l2reth-genesis-e2e.json:ro
3950
- l2reth-follower:/l2reth
40-
networks:
41-
- test-scroll-network
4251
depends_on:
43-
- rollup-node-sequencer
52+
l1-node:
53+
condition: service_healthy
4454

45-
networks:
46-
test-scroll-network:
47-
driver: bridge
55+
l2geth-sequencer:
56+
image: scrolltech/l2geth:scroll-v5.9.4
57+
platform: linux/amd64
58+
container_name: l2geth-sequencer
59+
entrypoint: ["bash", "/launch_l2geth.bash"]
60+
ports:
61+
- "8547:8545" # JSON-RPC
62+
- "6062:6060" # Metrics
63+
volumes:
64+
- ./l2geth-genesis-e2e.json:/l2geth-genesis-e2e.json:ro
65+
- ./launch_l2geth_sequencer.bash:/launch_l2geth.bash:ro
66+
- l2geth-sequencer:/l2geth
67+
depends_on:
68+
l1-node:
69+
condition: service_healthy
70+
71+
l2geth-follower:
72+
image: scrolltech/l2geth:scroll-v5.9.4
73+
platform: linux/amd64
74+
container_name: l2geth-follower
75+
entrypoint: ["bash", "/launch_l2geth.bash"]
76+
ports:
77+
- "8548:8545" # JSON-RPC
78+
- "6063:6060" # Metrics
79+
volumes:
80+
- ./l2geth-genesis-e2e.json:/l2geth-genesis-e2e.json:ro
81+
- ./launch_l2geth_follower.bash:/launch_l2geth.bash:ro
82+
- l2geth-follower:/l2geth
83+
depends_on:
84+
l1-node:
85+
condition: service_healthy
4886

4987
volumes:
5088
l2reth-sequencer:
5189
l2reth-follower:
90+
l2geth-sequencer:
91+
l2geth-follower:

0 commit comments

Comments
 (0)