Skip to content

Feat: pbft to rollup sequencer, include P2P & block produce#847

Open
tomatoishealthy wants to merge 3 commits intomainfrom
feat/pbft_to_singleSeq
Open

Feat: pbft to rollup sequencer, include P2P & block produce#847
tomatoishealthy wants to merge 3 commits intomainfrom
feat/pbft_to_singleSeq

Conversation

@tomatoishealthy
Copy link
Contributor

@tomatoishealthy tomatoishealthy commented Dec 30, 2025

Summary by CodeRabbit

  • New Features

    • Adds L2 block V2 support with block retrieval, application, and conversion between formats.
  • Tests

    • Adds a Docker-based sequencer test environment, multi-stage test images, a test runner, and a transaction generator for multi-node testing.
  • Documentation

    • Adds a README note clarifying the test directory and usage guidance.

@tomatoishealthy tomatoishealthy requested a review from a team as a code owner December 30, 2025 03:24
@tomatoishealthy tomatoishealthy requested review from secmgt and removed request for a team December 30, 2025 03:24
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Adds L2 Block V2 support to the executor with request/apply/get methods and conversion utilities, extends the retryable client with block-related RPCs, and adds Docker-based sequencer test infrastructure including build files, entrypoints, a test runner, and a tx generator.

Changes

Cohort / File(s) Summary
Executor L2 V2 APIs & Converters
node/core/executor.go
Add RequestBlockDataV2, ApplyBlockV2, GetBlockByNumber, GetLatestBlockV2 and conversions: ethBlockToBlockV2, blockV2ToExecutableL2Data, executableL2DataToBlockV2. Implements sequencer-mode V2 block flow and Geth↔V2 type bridging.
Retryable RPC Client
node/types/retryable_client.go
Add BlockByNumber and AssembleL2BlockV2 with exponential-backoff retry logic; refine HeaderByNumber error handling to distinguish retryable errors.
Docker build & runtime for tests
ops/docker-sequencer-test/Dockerfile.l2-geth-test, ops/docker-sequencer-test/Dockerfile.l2-node-test
Multi-stage Dockerfiles to build Geth and Morph node/test binaries for sequencer integration tests.
Compose, entrypoint, and README
ops/docker-sequencer-test/docker-compose.override.yml, ops/docker-sequencer-test/entrypoint-l2.sh, ops/docker-sequencer-test/README.md
Add docker-compose override for test services, Geth entrypoint script to init & run geth with JWT/CORS/API flags, and a README note about test-only artifacts.
Test orchestration & tx generator
ops/docker-sequencer-test/run-test.sh, ops/docker-sequencer-test/scripts/tx-generator.sh
Introduce a comprehensive test runner (build/start/stop/status/tests/upgrades) and a continuous tx-generator script that manages nonces and submits transactions to L2 RPC.

Sequence Diagram(s)

sequenceDiagram
    actor Sequencer
    participant Executor
    participant RetryableClient
    participant L1
    participant Blockchain
    participant Conversion as "Type Converters"

    Sequencer->>Executor: RequestBlockDataV2(parentHash)
    Executor->>RetryableClient: BlockByNumber(parent) (with retry)
    RetryableClient->>L1: Fetch L1 messages
    L1-->>RetryableClient: L1 messages
    Executor->>RetryableClient: AssembleL2BlockV2(transactions) (with retry)
    RetryableClient-->>Executor: ExecutableL2Data
    Executor->>Conversion: executableL2DataToBlockV2()
    Conversion-->>Executor: BlockV2
    Executor-->>Sequencer: (BlockV2, collectedFlag)

    rect rgba(200,230,255,0.5)
    Sequencer->>Executor: ApplyBlockV2(block)
    Executor->>Conversion: blockV2ToExecutableL2Data()
    Conversion-->>Executor: ExecutableL2Data
    Executor->>Blockchain: NewL2Block(ExecutableL2Data)
    Blockchain-->>Executor: apply result
    Executor->>Executor: update metrics / indexes
    end

    Sequencer->>Executor: GetBlockByNumber(height)
    Executor->>Blockchain: BlockByNumber(height)
    Blockchain-->>Executor: eth.Block
    Executor->>Conversion: ethBlockToBlockV2()
    Conversion-->>Executor: BlockV2
    Executor-->>Sequencer: BlockV2
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • twcctop
  • chengwenxi

Poem

🐇 In tests we hop where blocks renew,

V2 bits stitched and marshaled through,
Docker drums and RPC streams sing,
Transactions tumble, nonce in spring,
A rabbit cheers: the sequencer grew!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title mentions 'pbft to rollup sequencer' and 'block produce', but the actual changes focus on L2NodeV2 interface implementation and type conversion utilities in the executor, which is only part of the broader architecture change. Clarify whether the title should emphasize the V2 block format implementation/executor changes or provide more specific language about the architectural transition from PBFT to sequencer mode.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/pbft_to_singleSeq

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (10)
ops/docker-sequencer-test/Dockerfile.l2-node-test (2)

24-26: Consider removing the -x flag from go mod download.

The -x flag enables verbose output during dependency downloads, which can clutter build logs. Unless you specifically need this for debugging, consider removing it for cleaner output.

🔎 Proposed change
-RUN go mod download -x
+RUN go mod download

38-38: Consider using a smaller base image for the runtime stage.

The runtime stage uses the same go-ubuntu-builder image as the builder, which includes the full Go toolchain (~500MB+). Since the runtime only needs the compiled binaries, consider using a smaller base image like ubuntu:22.04 or debian:stable-slim to reduce the final image size.

🔎 Proposed change
-FROM ghcr.io/morph-l2/go-ubuntu-builder:go-1.24-ubuntu
+FROM ubuntu:22.04
ops/docker-sequencer-test/Dockerfile.l2-geth-test (1)

13-13: Consider using a smaller base image for the runtime stage.

Similar to the node Dockerfile, the runtime stage uses the full go-ubuntu-builder image, which includes the Go toolchain. Consider using a smaller base image like ubuntu:22.04 since only the compiled geth binary is needed at runtime.

🔎 Proposed change
-FROM ghcr.io/morph-l2/go-ubuntu-builder:go-1.24-ubuntu
+FROM ubuntu:22.04
ops/docker-sequencer-test/scripts/tx-generator.sh (3)

9-9: Unused variable: PRIVATE_KEY is defined but never used.

The PRIVATE_KEY variable is set but the script uses eth_sendTransaction which relies on the node to sign transactions from an unlocked account. Consider removing this unused variable or documenting why it's present.

🔎 Proposed change
-PRIVATE_KEY="${PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80}"

25-36: Consider using jq for more robust JSON parsing.

The functions use grep and cut to parse JSON responses, which is fragile and may break if the response format changes. Consider using jq for more reliable JSON parsing.

🔎 Proposed improvement
 get_nonce() {
     curl -s -X POST -H "Content-Type: application/json" \
         --data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionCount\",\"params\":[\"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\",\"latest\"],\"id\":1}" \
-        "$L2_RPC" | grep -o '"result":"[^"]*"' | cut -d'"' -f4
+        "$L2_RPC" | jq -r '.result'
 }

 get_block_number() {
     curl -s -X POST -H "Content-Type: application/json" \
         --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
-        "$L2_RPC" | grep -o '"result":"[^"]*"' | cut -d'"' -f4
+        "$L2_RPC" | jq -r '.result'
 }

42-44: Add error handling for initial nonce retrieval.

If get_nonce fails or returns an empty/invalid value, the script will continue with an incorrect nonce. Consider adding a check to ensure the nonce is valid before entering the main loop.

🔎 Proposed improvement
 NONCE_HEX=$(get_nonce)
+if [ -z "$NONCE_HEX" ] || [ "$NONCE_HEX" = "0x" ]; then
+    echo "Failed to get initial nonce"
+    exit 1
+fi
 NONCE=$((NONCE_HEX))
ops/docker-sequencer-test/run-test.sh (4)

277-278: Hardcoded private key should be configured via environment variable.

While this is the well-known Anvil/Hardhat default test account private key, hardcoding it triggers security scanners and makes it harder to use different keys for different test scenarios.

🔎 Proposed fix
     # Set sequencer private key
-    export SEQUENCER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
+    # Default to Anvil/Hardhat test account #0 if not specified
+    export SEQUENCER_PRIVATE_KEY="${SEQUENCER_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80}"

320-321: Add a comment explaining the absolute value trick.

The ${diff#-} parameter expansion removes a leading minus sign to compute absolute value. This is non-obvious and would benefit from a brief comment for maintainability.

+    # Compute absolute difference (${diff#-} removes leading minus)
     local diff=$((block0 - block1))
     if [ ${diff#-} -le 2 ]; then

402-411: TX generator uses duplicate hardcoded private key.

This is the same key hardcoded on line 278. If the earlier suggestion to use $SEQUENCER_PRIVATE_KEY is adopted, this should also reference the environment variable for consistency.

🔎 Proposed fix
     (
         while true; do
             RANDOM_ADDR="0x$(openssl rand -hex 20)"
-            cast send --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
+            cast send --private-key "$SEQUENCER_PRIVATE_KEY" \
                 --rpc-url "$L2_RPC" \
                 --value 1wei \
                 "$RANDOM_ADDR" 2>/dev/null || true
             sleep ${TX_INTERVAL:-5}
         done
     ) &

472-476: Inconsistent indentation on line 475.

Line 475 has an extra leading space compared to adjacent lines, which affects readability.

     echo "Node 1:         Block $(get_block_number http://127.0.0.1:8645)"
     echo "Node 2:         Block $(get_block_number http://127.0.0.1:8745)"
     echo "Node 3:         Block $(get_block_number http://127.0.0.1:8845)"
-     echo "Node 0 (seq-0): Block $(get_block_number http://127.0.0.1:8545)"
+    echo "Node 0 (seq-0): Block $(get_block_number http://127.0.0.1:8545)"
     echo "Sentry:         Block $(get_block_number http://127.0.0.1:8945 2>/dev/null || echo 'N/A')"
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee14af and 1920450.

📒 Files selected for processing (9)
  • node/core/executor.go
  • node/types/retryable_client.go
  • ops/docker-sequencer-test/Dockerfile.l2-geth-test
  • ops/docker-sequencer-test/Dockerfile.l2-node-test
  • ops/docker-sequencer-test/README.md
  • ops/docker-sequencer-test/docker-compose.override.yml
  • ops/docker-sequencer-test/entrypoint-l2.sh
  • ops/docker-sequencer-test/run-test.sh
  • ops/docker-sequencer-test/scripts/tx-generator.sh
🧰 Additional context used
🧬 Code graph analysis (4)
ops/docker-sequencer-test/scripts/tx-generator.sh (1)
ops/docker-sequencer-test/run-test.sh (1)
  • get_block_number (53-60)
ops/docker-sequencer-test/entrypoint-l2.sh (1)
prover/crates/utils/src/metrics/registry.rs (1)
  • init (27-105)
node/core/executor.go (1)
node/types/errors.go (2)
  • ErrInvalidL1MessageOrder (10-10)
  • ErrWrongBlockNumber (30-30)
ops/docker-sequencer-test/run-test.sh (1)
ops/docker-sequencer-test/scripts/tx-generator.sh (1)
  • get_block_number (32-36)
🪛 GitHub Actions: Tx-submitter
node/types/retryable_client.go

[error] 262-262: rc.authClient.AssembleL2BlockV2 undefined (type *authclient.Client has no field or method AssembleL2BlockV2)

🪛 Gitleaks (8.30.0)
ops/docker-sequencer-test/run-test.sh

[high] 278-278: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Shellcheck (0.11.0)
ops/docker-sequencer-test/run-test.sh

[warning] 68-68: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 309-309: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 317-317: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 318-318: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 337-337: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 346-346: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 349-349: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 350-350: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 364-364: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 382-382: Declare and assign separately to avoid masking return values.

(SC2155)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: check
  • GitHub Check: check
  • GitHub Check: test
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (go)
🔇 Additional comments (12)
node/types/retryable_client.go (3)

175-187: Good fix: Adds missing retry logic to HeaderByNumber.

This change brings HeaderByNumber in line with the other retryable methods by adding proper logging and retry-on-error handling that was previously missing.


189-205: BlockByNumber method exists and is correctly implemented.

The ethClient.BlockByNumber method from github.com/morph-l2/go-ethereum/ethclient is available with the signature (ctx context.Context, number *big.Int) (*types.Block, error). The implementation correctly calls this method with proper retry logic and error handling, consistent with other methods in the RetryableClient.


260-276: The AssembleL2BlockV2 method cannot be verified from this repository alone as it belongs to an external dependency.

The method is called on authClient which is of type *authclient.Client from the external package github.com/morph-l2/go-ethereum/ethclient/authclient (version v1.10.14-0.20251219060125-03910bc750a2). The code in this repository is well-integrated with proper error handling, but verification of the method's existence in the external go-ethereum fork requires inspecting that repository directly. The usage pattern is consistent with the existing AssembleL2Block V1 method, which functions successfully.

node/core/executor.go (6)

429-471: Implementation depends on fixing AssembleL2BlockV2.

This method is well-structured and follows the same patterns as RequestBlockData. However, it depends on AssembleL2BlockV2 (line 456), which currently fails to compile due to the missing method in the auth client (see issue in node/types/retryable_client.go).


495-497: Verify that nil batch hash is correct for sequencer mode.

The comment on line 495 states "no batch hash in sequencer mode for now", and nil is passed as the batch hash parameter. Please confirm this is the intended behavior and whether batch hashing will be added in the future.


513-520: LGTM!

Clean implementation that fetches a block by number and converts it to the V2 format. Error handling is appropriate.


524-531: LGTM!

Correctly uses nil to fetch the latest block, which is the standard Ethereum JSON-RPC convention.


571-619: LGTM!

The bidirectional conversion functions are well-implemented with proper nil checks and ensure that the Transactions field is never nil (important for JSON serialization). The field mappings appear complete and symmetric.


536-568: No action needed. The ethBlockToBlockV2 function correctly excludes WithdrawTrieRoot because this field is not available in the eth.Block or eth.Header types. The reference to line 592 (blockV2ToExecutableL2Data) is a different conversion that operates on BlockV2 (which already has WithdrawTrieRoot), not on raw eth.Block data. The function properly converts only the fields available from the Ethereum block structure.

Likely an incorrect or invalid review comment.

ops/docker-sequencer-test/entrypoint-l2.sh (1)

18-31: Security note: Wildcard CORS and vhosts are acceptable for testing only.

The configuration uses wildcard values for CORS origins (lines 21, 27) and vhosts (lines 22, 30). While this is acceptable for a test environment, ensure these settings are never used in production as they allow unrestricted access from any origin or host.

ops/docker-sequencer-test/docker-compose.override.yml (1)

26-27: Hardcoded private key is acceptable for testing only.

The default SEQUENCER_PRIVATE_KEY is the first Hardhat test account, which is publicly known. This is acceptable for a test environment but ensure this configuration is never used in any environment with real value.

ops/docker-sequencer-test/run-test.sh (1)

53-60: Robust get_block_number implementation - consider reusing in tx-generator.sh.

This implementation handles the RPC URL parameter and hex-to-decimal conversion gracefully. The version in ops/docker-sequencer-test/scripts/tx-generator.sh (lines 31-35) lacks the hex conversion and RPC URL parameter. Consider extracting this as a shared utility or updating the other script for consistency.

Comment on lines +62 to +76
wait_for_block() {
local target_height=$1
local rpc_url="${2:-$L2_RPC}"

log_info "Waiting for block $target_height..."
while true; do
local current=$(get_block_number "$rpc_url")
if [ "$current" -ge "$target_height" ]; then
log_success "Reached block $current"
return 0
fi
echo -ne "\r Current block: $current / $target_height"
sleep 2
done
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

wait_for_block can hang indefinitely without a timeout.

Unlike wait_for_rpc which has a max_retries parameter, this function has an unbounded while true loop. If the target block is never reached (e.g., due to network issues or a stalled chain), the script will hang forever.

🔎 Proposed fix to add a timeout
 wait_for_block() {
     local target_height=$1
     local rpc_url="${2:-$L2_RPC}"
+    local max_wait=${3:-600}  # Default 10 minute timeout
+    local waited=0
     
     log_info "Waiting for block $target_height..."
-    while true; do
+    while [ $waited -lt $max_wait ]; do
         local current=$(get_block_number "$rpc_url")
         if [ "$current" -ge "$target_height" ]; then
             log_success "Reached block $current"
             return 0
         fi
         echo -ne "\r  Current block: $current / $target_height"
         sleep 2
+        waited=$((waited + 2))
     done
+    log_error "Timeout waiting for block $target_height (current: $current)"
+    return 1
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
wait_for_block() {
local target_height=$1
local rpc_url="${2:-$L2_RPC}"
log_info "Waiting for block $target_height..."
while true; do
local current=$(get_block_number "$rpc_url")
if [ "$current" -ge "$target_height" ]; then
log_success "Reached block $current"
return 0
fi
echo -ne "\r Current block: $current / $target_height"
sleep 2
done
}
wait_for_block() {
local target_height=$1
local rpc_url="${2:-$L2_RPC}"
local max_wait=${3:-600} # Default 10 minute timeout
local waited=0
log_info "Waiting for block $target_height..."
while [ $waited -lt $max_wait ]; do
local current=$(get_block_number "$rpc_url")
if [ "$current" -ge "$target_height" ]; then
log_success "Reached block $current"
return 0
fi
echo -ne "\r Current block: $current / $target_height"
sleep 2
waited=$((waited + 2))
done
log_error "Timeout waiting for block $target_height (current: $current)"
return 1
}
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 68-68: Declare and assign separately to avoid masking return values.

(SC2155)

🤖 Prompt for AI Agents
In ops/docker-sequencer-test/run-test.sh around lines 62 to 76, wait_for_block
uses an unbounded while true loop and can hang forever; modify it to accept an
optional max_retries or timeout parameter (e.g., third arg or default value),
increment a retry counter inside the loop and break when retries exceed the
limit, log an error/timeout message and return non-zero (or exit) on timeout,
and keep the existing success path unchanged so the function returns 0 when the
target block is reached.

Comment on lines +85 to +91
local upgrade_file="$MORPH_ROOT/../tendermint/upgrade/upgrade.go"
if [ -f "$upgrade_file" ]; then
sed -i '' "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
log_success "Updated upgrade height in $upgrade_file"
else
log_warn "upgrade.go not found at $upgrade_file"
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

sed -i '' is macOS-specific and will fail on Linux.

The empty string argument after -i is required on macOS but causes errors on GNU sed (Linux). This will break in Linux-based CI environments.

🔎 Proposed fix for cross-platform compatibility
     local upgrade_file="$MORPH_ROOT/../tendermint/upgrade/upgrade.go"
     if [ -f "$upgrade_file" ]; then
-        sed -i '' "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
+        # Cross-platform sed in-place edit
+        if [[ "$OSTYPE" == "darwin"* ]]; then
+            sed -i '' "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
+        else
+            sed -i "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
+        fi
         log_success "Updated upgrade height in $upgrade_file"
     else
         log_warn "upgrade.go not found at $upgrade_file"
     fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
local upgrade_file="$MORPH_ROOT/../tendermint/upgrade/upgrade.go"
if [ -f "$upgrade_file" ]; then
sed -i '' "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
log_success "Updated upgrade height in $upgrade_file"
else
log_warn "upgrade.go not found at $upgrade_file"
fi
local upgrade_file="$MORPH_ROOT/../tendermint/upgrade/upgrade.go"
if [ -f "$upgrade_file" ]; then
# Cross-platform sed in-place edit
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
else
sed -i "s/UpgradeBlockHeight int64 = [0-9]*/UpgradeBlockHeight int64 = $height/" "$upgrade_file"
fi
log_success "Updated upgrade height in $upgrade_file"
else
log_warn "upgrade.go not found at $upgrade_file"
fi
🤖 Prompt for AI Agents
In ops/docker-sequencer-test/run-test.sh around lines 85–91, the sed call uses
the macOS-only form `sed -i ''` which fails on Linux; change it to a
cross-platform in-place edit approach: detect the platform (e.g., via uname -s)
and set a variable for the sed inplace flag (use `-i ''` on Darwin/macOS and
`-i` or `-i.bak` on Linux), then run sed with that variable and remove any
created backup file if used (or use a portable fallback like perl -pi -e).
Update the script to use that variable in the sed invocation so the upgrade.go
replacement works on both macOS and Linux.

Comment on lines +50 to +52
# Generate random recipient address
RANDOM_SUFFIX=$(od -An -N4 -tx1 /dev/urandom | tr -d ' ')
TO_ADDR="0x000000000000000000000000000000${RANDOM_SUFFIX}"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix: Random address generation produces invalid length.

The generated address is 40 characters total (38 hex digits after "0x") instead of the required 42 characters (40 hex digits). This will cause transaction failures.

  • Line 51 generates 4 bytes = 8 hex characters
  • Line 52 adds a 30-character prefix
  • Total: "0x" + 30 + 8 = 40 characters (need 42)
🔎 Proposed fix
-    RANDOM_SUFFIX=$(od -An -N4 -tx1 /dev/urandom | tr -d ' ')
-    TO_ADDR="0x000000000000000000000000000000${RANDOM_SUFFIX}"
+    RANDOM_SUFFIX=$(od -An -N8 -tx1 /dev/urandom | tr -d ' ')
+    TO_ADDR="0x00000000000000000000000000${RANDOM_SUFFIX}"

This generates 8 bytes (16 hex chars) and uses a 24-char prefix for a total of 42 chars.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Generate random recipient address
RANDOM_SUFFIX=$(od -An -N4 -tx1 /dev/urandom | tr -d ' ')
TO_ADDR="0x000000000000000000000000000000${RANDOM_SUFFIX}"
# Generate random recipient address
RANDOM_SUFFIX=$(od -An -N8 -tx1 /dev/urandom | tr -d ' ')
TO_ADDR="0x00000000000000000000000000${RANDOM_SUFFIX}"
🤖 Prompt for AI Agents
In ops/docker-sequencer-test/scripts/tx-generator.sh around lines 50 to 52, the
random recipient address is built with a 30-hex-digit prefix plus 4 bytes (8 hex
chars), producing a 40-char address instead of the required 42-char (40 hex
digits). Change the generation to use 8 random bytes (od -An -N8 -tx1 ...) so
you get 16 hex chars and reduce the hardcoded zero prefix to 24 hex digits,
resulting in "0x" + 24 zeros + 16 random hex chars to produce a 42-character
address.

@tomatoishealthy tomatoishealthy changed the title Feat: pbft to single sequencer, include P2P & block produce Feat: pbft to rollup sequencer, include P2P & block produce Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant