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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
prover/
.git/
contracts/node_modules/
ops/reth-cross-test/
ops/publicnode/
docs/
Comment on lines +2 to +6
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read-only verification: find COPY/ADD references to newly ignored paths.
# Expected result: no COPY/ADD usage that depends on ignored directories.

set -euo pipefail

echo "== Dockerfiles mentioning potentially ignored paths =="
rg -n -C2 --iglob '*Dockerfile*' --iglob '*.dockerfile' \
  '(\.git/|contracts/node_modules/|ops/reth-cross-test/|ops/publicnode/|docs/)'

echo
echo "== docker-compose files with build contexts likely requiring ignored paths =="
rg -n -C2 --iglob '*compose*.yml' --iglob '*compose*.yaml' \
  '(build:|context:|dockerfile:)'

Repository: morph-l2/morph

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Find all Docker-related files
echo "=== Finding all Dockerfile and docker-compose files ==="
fd -t f -e Dockerfile -e dockerfile
fd -t f -name '*compose*.yml' -o -name '*compose*.yaml'

# List all files found
echo ""
echo "=== All docker-compose files ==="
fd -t f \( -name '*compose*.yml' -o -name '*compose*.yaml' \)

# Count Dockerfiles
echo ""
echo "=== Dockerfile count ==="
fd -t f -e Dockerfile -e dockerfile | wc -l

Repository: morph-l2/morph

Length of output: 854


🏁 Script executed:

#!/bin/bash
# Search for COPY, ADD, and build context references in Docker files
echo "=== Searching for COPY/ADD in Dockerfiles ==="
rg '^\s*(COPY|ADD)' -t Dockerfile

echo ""
echo "=== Searching for build/context in docker-compose files ==="
rg '(build:|context:)' -t yaml

Repository: morph-l2/morph

Length of output: 2271


🏁 Script executed:

#!/bin/bash
# Read each Dockerfile for references to ignored paths
echo "=== Content of Dockerfiles ==="
for dockerfile in \
  ops/docker/go-rust-builder.Dockerfile \
  ops/docker/intermediate/go-rust-alpine-builder.Dockerfile \
  ops/docker/intermediate/go-rust-builder.Dockerfile \
  ops/docker/intermediate/go-ubuntu-builder.Dockerfile; do
  echo ""
  echo "### $dockerfile ###"
  cat -n "$dockerfile"
done

Repository: morph-l2/morph

Length of output: 5562


🏁 Script executed:

#!/bin/bash
# Check for indirect references to ignored paths in Dockerfiles (ENV, RUN, WORKDIR, etc.)
echo "=== Searching for any reference to ignored paths in Dockerfiles ==="
rg '(\.git|contracts/node_modules|ops/reth-cross-test|ops/publicnode|/docs)' ops/docker/ --no-heading

Repository: morph-l2/morph

Length of output: 125


🏁 Script executed:

#!/bin/bash
# Check the ops/publicnode/docker-compose.yml file since it's in an ignored directory
echo "=== ops/publicnode/docker-compose.yml content ==="
cat -n ops/publicnode/docker-compose.yml

Repository: morph-l2/morph

Length of output: 1708


🏁 Script executed:

#!/bin/bash
# Check if the dockerfiles referenced in ops/publicnode/docker-compose.yml exist
echo "=== Checking referenced Dockerfiles ==="
ls -la ops/publicnode/Dockerfile.geth-nccc ops/publicnode/Dockerfile.node 2>&1

# Also check what files are in ops/publicnode/
echo ""
echo "=== Files in ops/publicnode/ ==="
find ops/publicnode -type f | head -20

Repository: morph-l2/morph

Length of output: 686


🏁 Script executed:

#!/bin/bash
# Search for any other references to ops/publicnode dockerfiles or usage
echo "=== Searching for references to ops/publicnode dockerfiles ==="
rg 'ops/publicnode' --no-heading -i | head -30

Repository: morph-l2/morph

Length of output: 291


🏁 Script executed:

#!/bin/bash
# Read the Dockerfiles in ops/publicnode to understand the build dependency
echo "=== ops/publicnode/Dockerfile.geth-nccc ==="
cat -n ops/publicnode/Dockerfile.geth-nccc

echo ""
echo "=== ops/publicnode/Dockerfile.node ==="
cat -n ops/publicnode/Dockerfile.node

echo ""
echo "=== Check what's in ops/publicnode/Makefile ==="
cat -n ops/publicnode/Makefile

Repository: morph-l2/morph

Length of output: 4323


The .dockerignore change breaks ops/publicnode/ builds.

Excluding ops/publicnode/ from .dockerignore will prevent Docker from locating ops/publicnode/Dockerfile.geth-nccc and ops/publicnode/Dockerfile.node, which are actively referenced by ops/publicnode/docker-compose.yml with context: ../... When make run-holesky-node executes docker-compose up, the build will fail because the dockerfile paths are no longer available in the build context. Either remove ops/publicnode/ from .dockerignore or update the docker-compose references to use absolute paths or alternative contexts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.dockerignore around lines 2 - 6, The .dockerignore entry excluding
ops/publicnode/ prevents Docker from seeing ops/publicnode/Dockerfile.geth-nccc
and ops/publicnode/Dockerfile.node (referenced by
ops/publicnode/docker-compose.yml and invoked by the make run-holesky-node
flow), causing docker-compose build failures; fix by either removing
ops/publicnode/ from .dockerignore so Docker’s build context includes those
Dockerfiles, or update ops/publicnode/docker-compose.yml to reference accessible
paths (use absolute paths or adjust build.context and dockerfile fields so
Docker can locate Dockerfile.geth-nccc and Dockerfile.node during the make
run-holesky-node/docker-compose up sequence).

5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ devnet-down:
cd ops/docker && docker compose -f docker-compose-4nodes.yml down
.PHONY: devnet-down

devnet-clean-build: devnet-down devnet-l1-clean
docker volume ls --filter name=docker-* --format='{{.Name}}' | xargs -r docker volume rm
devnet-clean-build: devnet-l1-clean
cd ops/docker && docker compose -f docker-compose-4nodes.yml down --volumes --remove-orphans
docker volume ls --filter name=docker_ --format='{{.Name}}' | xargs docker volume rm 2>/dev/null || true
rm -rf ops/l2-genesis/.devnet
rm -rf ops/docker/.devnet
rm -rf ops/docker/consensus/beacondata ops/docker/consensus/validatordata ops/docker/consensus/genesis.ssz
Expand Down
2 changes: 1 addition & 1 deletion ops/docker/Dockerfile.l1-beacon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=linux/amd64 ubuntu:20.04 as chain-genesis
FROM --platform=linux/amd64 ubuntu:22.04 as chain-genesis
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🌐 Web query:

`For these images, what is the default USER in image metadata?

  • gcr.io/prysmaticlabs/prysm/beacon-chain:v4.2.1
  • ethereum/client-go:v1.14.11`

💡 Result:

The default USER in the Docker image metadata for both images is "root". For gcr.io/prysmaticlabs/prysm/beacon-chain:v4.2.1, the image configuration explicitly states "User": "root" (from metadata of similar v4.1.1 image, as v4.2.1 uses the same Bazel-built distroless-like structure without a non-root USER instruction). For ethereum/client-go:v1.14.11, the Dockerfile is based on alpine:latest with no USER instruction, so it defaults to root (standard for Alpine-based Go static binaries).

Citations:


Add explicit non-root USER directive to comply with DS-0002

Both inherited base images (gcr.io/prysmaticlabs/prysm/beacon-chain:v4.2.1 and ethereum/client-go:v1.14.11) default to running as root. Add an explicit non-root USER directive in each stage to satisfy DS-0002 security requirements.

🧰 Tools
🪛 Trivy (0.69.3)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ops/docker/Dockerfile.l1-beacon` at line 1, The Dockerfile stages currently
inherit root from base images; for each stage that uses
gcr.io/prysmaticlabs/prysm/beacon-chain:v4.2.1 and ethereum/client-go:v1.14.11
(e.g., the chain-genesis stage), add an explicit non-root USER directive: create
a non-root group/user (RUN groupadd -r <grp> && useradd -r -g <grp> -u 1000
<user>) and chown any runtime directories, then switch to USER <user> after
those RUN steps; ensure the USER directive appears in each stage (referencing
the chain-genesis stage and any other FROM stages that use those images) so no
stage runs as root.

RUN apt-get update && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime && apt-get install build-essential curl wget git make pkg-config -y
RUN curl -o prysmctl -fLO https://github.com/prysmaticlabs/prysm/releases/download/v4.2.1/prysmctl-v4.2.1-linux-amd64
RUN chmod +x prysmctl
Expand Down
5 changes: 4 additions & 1 deletion ops/docker/Dockerfile.oracle
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM rust:1.70 as builder
FROM rust:1.88-slim as builder

RUN apt-get -qq update && apt-get -qq install -y --no-install-recommends \
pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*
Comment on lines +1 to +4
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Run the runtime image as non-root

Line 11-14 keeps the container default user as root, which weakens container isolation. Please add a non-root user in the app stage and switch to it before CMD.

🔧 Proposed fix
 FROM ubuntu:22.04 as app
+RUN useradd --system --create-home --uid 10001 morph && \
+    mkdir -p /app && chown -R morph:morph /app
 COPY --from=builder /gas-oracle/app/target/release/app /
+USER morph

 CMD ["./app"]
🧰 Tools
🪛 Trivy (0.69.3)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ops/docker/Dockerfile.oracle` around lines 1 - 4, Add a non-root user in the
final runtime stage (the `app` stage) and switch to it before CMD: create a
group/user (e.g., group and user named app), set ownership of the application
directory (chown -R app:app /app or similar), set WORKDIR to that directory, and
add USER app before the CMD instruction so the container does not run as root;
ensure any files copied from the `builder` stage are owned/accessible by that
user.


COPY ./gas-oracle /gas-oracle

Expand Down
5 changes: 5 additions & 0 deletions ops/docker/docker-compose-4nodes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ services:
- MORPH_NODE_L1_ETH_RPC=${L1_ETH_RPC}
- MORPH_NODE_SYNC_DEPOSIT_CONTRACT_ADDRESS=${MORPH_PORTAL:-0x6900000000000000000000000000000000000001}
- MORPH_NODE_L1_CONFIRMATIONS=0
- MORPH_NODE_ROLLUP_ADDRESS=${MORPH_ROLLUP:-0x6900000000000000000000000000000000000010}
- MORPH_NODE_SYNC_START_HEIGHT=${MORPH_NODE_SYNC_START_HEIGHT:-1}
- MORPH_NODE_UPGRADE_BATCH_TIME=${BATCH_UPGRADE_TIME}
volumes:
Expand Down Expand Up @@ -266,6 +267,7 @@ services:
- MORPH_NODE_L1_ETH_RPC=${L1_ETH_RPC}
- MORPH_NODE_SYNC_DEPOSIT_CONTRACT_ADDRESS=${MORPH_PORTAL:-0x6900000000000000000000000000000000000001}
- MORPH_NODE_L1_CONFIRMATIONS=0
- MORPH_NODE_ROLLUP_ADDRESS=${MORPH_ROLLUP:-0x6900000000000000000000000000000000000010}
- MORPH_NODE_SYNC_START_HEIGHT=${MORPH_NODE_SYNC_START_HEIGHT:-1}
- MORPH_NODE_UPGRADE_BATCH_TIME=${BATCH_UPGRADE_TIME}
volumes:
Expand Down Expand Up @@ -295,6 +297,7 @@ services:
- MORPH_NODE_L1_ETH_RPC=${L1_ETH_RPC}
- MORPH_NODE_SYNC_DEPOSIT_CONTRACT_ADDRESS=${MORPH_PORTAL:-0x6900000000000000000000000000000000000001}
- MORPH_NODE_L1_CONFIRMATIONS=0
- MORPH_NODE_ROLLUP_ADDRESS=${MORPH_ROLLUP:-0x6900000000000000000000000000000000000010}
- MORPH_NODE_SYNC_START_HEIGHT=${MORPH_NODE_SYNC_START_HEIGHT:-1}
- MORPH_NODE_UPGRADE_BATCH_TIME=${BATCH_UPGRADE_TIME}
volumes:
Expand Down Expand Up @@ -324,6 +327,7 @@ services:
- MORPH_NODE_L1_ETH_RPC=${L1_ETH_RPC}
- MORPH_NODE_SYNC_DEPOSIT_CONTRACT_ADDRESS=${MORPH_PORTAL:-0x6900000000000000000000000000000000000001}
- MORPH_NODE_L1_CONFIRMATIONS=0
- MORPH_NODE_ROLLUP_ADDRESS=${MORPH_ROLLUP:-0x6900000000000000000000000000000000000010}
- MORPH_NODE_SYNC_START_HEIGHT=${MORPH_NODE_SYNC_START_HEIGHT:-1}
- MORPH_NODE_UPGRADE_BATCH_TIME=${BATCH_UPGRADE_TIME}
volumes:
Expand Down Expand Up @@ -378,6 +382,7 @@ services:
- MORPH_NODE_L1_ETH_RPC=${L1_ETH_RPC}
- MORPH_NODE_SYNC_DEPOSIT_CONTRACT_ADDRESS=${MORPH_PORTAL:-0x6900000000000000000000000000000000000001}
- MORPH_NODE_L1_CONFIRMATIONS=0
- MORPH_NODE_ROLLUP_ADDRESS=${MORPH_ROLLUP:-0x6900000000000000000000000000000000000010}
- MORPH_NODE_SYNC_START_HEIGHT=${MORPH_NODE_SYNC_START_HEIGHT:-1}
volumes:
- ".devnet/node4:${NODE_DATA_DIR}"
Expand Down
2 changes: 1 addition & 1 deletion ops/docker/go-rust-builder.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG GO_VERSION=1.24.0
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41

FROM ubuntu:20.04
FROM ubuntu:22.04

RUN apt-get update && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime

Expand Down
2 changes: 1 addition & 1 deletion ops/docker/intermediate/go-rust-builder.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG GO_VERSION=1.24.0
ARG RUST_VERSION=nightly-2023-12-03
ARG CARGO_CHEF_TAG=0.1.41

FROM ubuntu:20.04
FROM ubuntu:22.04

RUN apt-get update --fix-missing && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime

Expand Down
2 changes: 1 addition & 1 deletion ops/docker/intermediate/go-ubuntu-builder.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG GO_VERSION=1.24

FROM ubuntu:20.04
FROM ubuntu:22.04

RUN apt-get update --fix-missing && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime

Expand Down
5 changes: 4 additions & 1 deletion ops/l2-genesis/morph-chain-ops/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
EmeraldTime: emeraldTime,
TerminalTotalDifficulty: big.NewInt(0),
Morph: params.MorphConfig{
UseZktrie: true,
UseZktrie: false,
MaxTxPayloadBytesPerBlock: &maxTxPayloadBytesPerBlock,
FeeVaultAddress: &sequencerFeeVaultReceipt,
},
JadeForkTime: new(uint64),
}

gasLimit := config.L2GenesisBlockGasLimit
Expand All @@ -88,6 +89,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
var baseFee *big.Int
if config.L2GenesisBlockBaseFeePerGas != nil {
baseFee = config.L2GenesisBlockBaseFeePerGas.ToInt()
} else {
baseFee = big.NewInt(1_000_000)
}
Comment on lines 89 to 94
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there's documentation or other references for expected L2 base fee defaults
rg -n -C3 'BaseFee|baseFee|base_fee' --type go ops/l2-genesis/

# Check if any deploy configs explicitly set L2GenesisBlockBaseFeePerGas
fd -e json -e yaml | xargs rg -l 'L2GenesisBlockBaseFeePerGas' 2>/dev/null | head -5 | xargs -I{} sh -c 'echo "=== {} ===" && cat {}'

Repository: morph-l2/morph

Length of output: 8973


🏁 Script executed:

# Search for deploy config files and see what base fee values they use
fd -e json -e toml -e yaml | xargs rg -l 'l2GenesisBlockBaseFeePerGas|L2GenesisBlockBaseFeePerGas' 2>/dev/null

# Check for any comments or documentation about this field
rg -B5 -A5 'L2GenesisBlockBaseFeePerGas' ops/l2-genesis/morph-chain-ops/genesis/config.go

# Look at the actual usage in NewL2StorageConfig to understand the purpose
rg -B10 -A10 'l1BaseFee' ops/l2-genesis/morph-chain-ops/genesis/config.go

Repository: morph-l2/morph

Length of output: 1555


🏁 Script executed:

# Read the test deploy config to see what base fee value is used
cat ops/l2-genesis/morph-chain-ops/genesis/testdata/test-deploy-config-full.json | jq '.l2GenesisBlockBaseFeePerGas // "NOT_SET"'

# Check if there are other deploy config examples
fd -type f \( -name '*deploy*' -o -name '*config*' \) -path '*/testdata/*' | head -10

# Look for any comments in genesis.go about why this default was chosen
head -100 ops/l2-genesis/morph-chain-ops/genesis/genesis.go | tail -50

Repository: morph-l2/morph

Length of output: 1846


🏁 Script executed:

# Verify the hex to decimal conversion
python3 << 'EOF'
test_value = 0x3b9aca00
print(f"Test config value: 0x3b9aca00 = {test_value} wei = {test_value / 1e9} gwei")
default_value = 1_000_000
print(f"Code default: {default_value} wei = {default_value / 1e9} gwei")
print(f"Ratio: {test_value / default_value}x difference")
EOF

# Search for other deploy config examples
find ops/l2-genesis -name '*.json' | head -20

# Check if there are comments or related issues about this
rg -B3 -A3 '1_000_000|1000000' ops/l2-genesis/morph-chain-ops/genesis/

Repository: morph-l2/morph

Length of output: 5035


🏁 Script executed:

# Extract base fee values from all deploy configs
for config in ops/l2-genesis/deploy-config/*.json; do
  echo "=== $(basename $config) ==="
  jq '.l2GenesisBlockBaseFeePerGas // "NOT_SET"' "$config"
done

# Also check git blame for the 1_000_000 line to understand when it was added
cd ops/l2-genesis/morph-chain-ops/genesis && git log -p --all -S '1_000_000' -- genesis.go | head -80

Repository: morph-l2/morph

Length of output: 322


🏁 Script executed:

# Look for any comments or context around this change in genesis.go
rg -B10 'baseFee = big.NewInt' ops/l2-genesis/morph-chain-ops/genesis/genesis.go

# Search for any comments or documentation about base fee defaults
rg -i 'base.*fee.*default|default.*base.*fee' ops/l2-genesis/

# Check git log more carefully (with different approach)
git -C ops/l2-genesis log --oneline --all -- morph-chain-ops/genesis/genesis.go | head -20

Repository: morph-l2/morph

Length of output: 777


🏁 Script executed:

# Final check: look at the actual definition of this value and nearby code patterns
rg -B5 -A5 'defaultL2GasLimit' ops/l2-genesis/morph-chain-ops/genesis/genesis.go

# Check if there are any test failures or expectations about base fee
rg 'baseFee.*1_000_000|1_000_000.*baseFee' ops/l2-genesis/

Repository: morph-l2/morph

Length of output: 812


Fix the base fee default: should be 1,000,000,000 wei (1 gwei), not 1,000,000 wei (0.001 gwei).

The default baseFee value of 1,000,000 wei is incorrect by three orders of magnitude. The test deploy config expects 1,000,000,000 wei (0x3b9aca00 = 1 gwei), which aligns with Ethereum L2 base fee patterns. The current default of 0.001 gwei is economically unrealistic and contradicts the test expectations. Additionally, all six production and staging deploy configs (mainnet, devnet, testnet, holesky, hoodi, qanet) omit this field and rely on this buggy default, affecting all environments.

Change line 93 from baseFee = big.NewInt(1_000_000) to baseFee = big.NewInt(1_000_000_000).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ops/l2-genesis/morph-chain-ops/genesis/genesis.go` around lines 89 - 94, The
default baseFee value is off by three orders of magnitude; in the genesis
construction code where baseFee is set when config.L2GenesisBlockBaseFeePerGas
== nil (the variable baseFee in genesis.go), replace the BigInt default of
1_000_000 with 1_000_000_000 (1 gwei / 0x3b9aca00) so environments that omit
L2GenesisBlockBaseFeePerGas (e.g., mainnet/devnet/testnet/holesky/hoodi/qanet)
use the correct 1 gwei default.


difficulty := config.L2GenesisBlockDifficulty
Expand Down
Loading