Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
31 changes: 27 additions & 4 deletions prover/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ morph-prove = { path = "bin/host" }

[workspace.dependencies.revm]
git = "https://github.com/morph-l2/revm"
branch = "release/v42"
branch = "emerald"
default-features = false
features = [
"morph-default-handler",
Expand All @@ -108,7 +108,7 @@ features = [

[workspace.dependencies.revm-primitives]
git = "https://github.com/morph-l2/revm"
branch = "release/v42"
branch = "emerald"
default-features = false
features = [
"morph-default-handler",
Expand Down
14 changes: 13 additions & 1 deletion prover/crates/core/src/hardfork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ static HARDFORK_HEIGHTS: Lazy<HashMap<u64, HashMap<SpecId, u64>>> = Lazy::new(||
(SpecId::CURIE, 0),
(SpecId::MORPH203, 0),
(SpecId::VIRIDIAN, 0),
(SpecId::EMERALD, 0),
]),
);
map.insert(
Expand All @@ -32,6 +33,7 @@ static HARDFORK_HEIGHTS: Lazy<HashMap<u64, HashMap<SpecId, u64>>> = Lazy::new(||
(SpecId::CURIE, 0),
(SpecId::MORPH203, 0),
(SpecId::VIRIDIAN, 0),
(SpecId::EMERALD, 0),
]),
);
map.insert(
Expand All @@ -41,6 +43,7 @@ static HARDFORK_HEIGHTS: Lazy<HashMap<u64, HashMap<SpecId, u64>>> = Lazy::new(||
(SpecId::CURIE, 0),
(SpecId::MORPH203, 0),
(SpecId::VIRIDIAN, 0),
(SpecId::EMERALD, 0),
]),
);

Expand All @@ -54,6 +57,7 @@ pub struct HardforkConfig {
curie_block: u64,
morph203_block: u64,
viridian_block: u64,
emerald_block: u64,
}

impl HardforkConfig {
Expand All @@ -65,6 +69,7 @@ impl HardforkConfig {
curie_block: heights.get(&SpecId::CURIE).copied().unwrap_or(0),
morph203_block: heights.get(&SpecId::MORPH203).copied().unwrap_or(0),
viridian_block: heights.get(&SpecId::VIRIDIAN).copied().unwrap_or(0),
emerald_block: heights.get(&SpecId::EMERALD).copied().unwrap_or(0),
}
} else {
dev_warn!(
Expand Down Expand Up @@ -93,14 +98,21 @@ impl HardforkConfig {
self
}

/// Set the Emerald block number.
pub fn set_emerald_block(&mut self, emerald_block: u64) -> &mut Self {
self.emerald_block = emerald_block;
self
}

/// Get the hardfork spec id for a block number.
pub fn get_spec_id(&self, block_number: u64) -> SpecId {
match block_number {
n if n < self.bernoulli_block => SpecId::PRE_BERNOULLI,
n if n < self.curie_block => SpecId::BERNOULLI,
n if n < self.morph203_block => SpecId::CURIE,
n if n < self.viridian_block => SpecId::MORPH203,
_ => SpecId::VIRIDIAN,
n if n < self.emerald_block => SpecId::VIRIDIAN,
_ => SpecId::EMERALD,
}
}

Expand Down
1 change: 1 addition & 0 deletions prover/crates/primitives/src/types/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub struct TransactionTrace {
/// authorization list
#[serde(rename = "authorizationList")]
#[serde_as(as = "DefaultOnNull")]
#[serde(default)]
pub(crate) authorization_list: AuthorizationList,
/// signature v
pub(crate) v: U64,
Expand Down
140 changes: 140 additions & 0 deletions prover/testdata/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/bin/bash

# Script to fetch block traces and verify them with Rust prover
# Usage: ./verify.sh <start_block> <end_block> [rpc_url]
# Example: ./verify.sh 10 20 http://localhost:8545

set -e

Comment on lines +7 to +8

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:

cat -n prover/testdata/verify.sh | head -150

Repository: morph-l2/morph

Length of output: 5002


🏁 Script executed:

cat > /tmp/test_set_e.sh << 'EOF'
#!/bin/bash
set -e

echo "Test 1: Command substitution with failing command"
VAR=$(false)
echo "After failed command substitution, VAR='$VAR', \$?=$?"
echo "Script did not abort!"

echo ""
echo "Test 2: Direct failed command"
false
echo "This should not print"
EOF

bash /tmp/test_set_e.sh
echo "Exit code: $?"

Repository: morph-l2/morph

Length of output: 120


🏁 Script executed:

cat > /tmp/test_set_e_detailed.sh << 'EOF'
#!/bin/bash
set -e

echo "Starting test with set -e"
RESULT=$(false)
echo "After failed command substitution in assignment"
echo "RESULT='$RESULT'"
echo "Still running!"
EOF

bash /tmp/test_set_e_detailed.sh 2>&1
echo "Script exit code: $?"

Repository: morph-l2/morph

Length of output: 103


🏁 Script executed:

# Check if there are any related issues, test results, or comments
rg -i "verify\.sh|cast rpc|morph_getBlockTrace" --max-count=20 -B2 -A2

Repository: morph-l2/morph

Length of output: 1486


🌐 Web query:

cast rpc foundry exit code behavior error handling

💡 Result:

Short answer

  • cast rpc: it performs a raw JSON-RPC call and prints the provider response; on transport/JSON errors it will print the error and the process will exit non‑zero. [1][2]
  • Caveat: some cast subcommands historically did not surface missing/invalid RPC configuration as a non‑zero failure (e.g. cast logs returned empty output instead of an error) — this has been filed/handled as a Foundry bug in the repo. So behavior can vary by subcommand/version. [3]

What to do if you need reliable exit codes

  • Use a recent Foundry release (or check changelog) — many cast fixes land in point releases. [4]
  • Inspect stdout/stderr and the process exit status in your wrapper script; treat empty output as a potential RPC/configuration failure if you rely on it.
  • For scripting, prefer explicit RPC flags (--rpc-url/ETH_RPC_URL) and test the endpoint first (e.g., cast rpc web3_clientVersion). [2]

Sources

  1. cast rpc reference (per‑command docs showing rpc usage/options). [2]
  2. Foundry cast reference / getfoundry docs (shows rpc options and typical behavior). [4]
  3. GitHub issue: "cast logs doesn't fail when the RPC URL is not set" (example where a subcommand silently returned empty output). [3]

🏁 Script executed:

cat > /tmp/test_if_set_e.sh << 'EOF'
#!/bin/bash
set -e

echo "Test: if statement with failing command in condition"
if RESULT=$(false); then
  echo "Condition succeeded"
else
  echo "Condition failed"
fi

echo "Script continued after if statement!"
EOF

bash /tmp/test_if_set_e.sh 2>&1
echo "Exit code: $?"

Repository: morph-l2/morph

Length of output: 177


🏁 Script executed:

cat > /tmp/simulate_verify.sh << 'EOF'
#!/bin/bash
set -e

echo "Simulating current verify.sh pattern"
echo ""

SUCCESS_COUNT=0
FAIL_COUNT=0

for ((block=1; block<=3; block++)); do
  echo -n "Block $block: "
  
  # Simulate cast rpc - fails on block 2
  if [ $block -eq 2 ]; then
    TRACE=$(false 2>/dev/null)  # Simulating cast rpc failure
  else
    TRACE="success_data"
  fi
  
  if [ $? -eq 0 ] && [ -n "$TRACE" ]; then
    echo "✓ Success"
    SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
  else
    echo "✗ Failed"
    FAIL_COUNT=$((FAIL_COUNT + 1))
  fi
done

echo ""
echo "Results: SUCCESS=$SUCCESS_COUNT, FAIL=$FAIL_COUNT"
EOF

bash /tmp/simulate_verify.sh 2>&1
echo "Exit code: $?"

Repository: morph-l2/morph

Length of output: 136


set -e causes script to abort on first RPC failure instead of continuing with error tracking

When cast rpc fails and returns a non-zero exit code, the assignment TRACE=$(cast rpc ...) on line 63 triggers the set -e exit immediately, terminating the loop before the if [ $? -eq 0 ] check on line 65 is reached. This prevents the FAIL_COUNT logic from executing and stops processing of remaining blocks.

Wrap the assignment in an if statement to suppress set -e for that command and allow the loop to continue:

if TRACE=$(cast rpc morph_getBlockTraceByNumberOrHash "$BLOCK_HEX" --rpc-url "$RPC_URL" 2>/dev/null); then
  if [ -n "$TRACE" ] && [ "$TRACE" != "null" ]; then
    if [ "$FIRST" = false ]; then
      echo "," >> "$TEMP_FILE"
    fi
    FIRST=false
    echo -n "    $TRACE" >> "$TEMP_FILE"
    echo "✓ Success"
    SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
  else
    echo "✗ Failed (empty or null response)"
    FAIL_COUNT=$((FAIL_COUNT + 1))
  fi
else
  echo "✗ Failed (RPC error)"
  FAIL_COUNT=$((FAIL_COUNT + 1))
fi

Also applies to: 56-81

🤖 Prompt for AI Agents
In prover/testdata/verify.sh around lines 7 and 56-81, the global set -e causes
the script to exit immediately when assigning TRACE=$(cast rpc ...), preventing
the subsequent if/FAIL_COUNT logic from running; change the code to wrap the
cast rpc assignment in an if statement (if TRACE=$(cast rpc ...); then ... else
... fi) so the command's failure is handled locally, increment FAIL_COUNT on RPC
errors, and preserve existing handling for empty/null responses so the loop
continues for remaining blocks.

# Check if required commands exist
command -v cast >/dev/null 2>&1 || { echo "Error: 'cast' command not found. Please install foundry."; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "Error: 'jq' command not found. Please install jq."; exit 1; }

# Parse arguments
if [ $# -lt 2 ]; then
echo "Usage: $0 <start_block> <end_block> [rpc_url]"
echo "Example: $0 10 20 http://localhost:8545"
exit 1
fi

START_BLOCK=$1
END_BLOCK=$2
RPC_URL=${3:-"http://localhost:8545"}

# Validate block numbers
if ! [[ "$START_BLOCK" =~ ^[0-9]+$ ]] || ! [[ "$END_BLOCK" =~ ^[0-9]+$ ]]; then
echo "Error: Block numbers must be integers"
exit 1
fi

if [ "$START_BLOCK" -gt "$END_BLOCK" ]; then
echo "Error: Start block must be less than or equal to end block"
exit 1
fi

# Create output directory if it doesn't exist
OUTPUT_DIR="./generated"
mkdir -p "$OUTPUT_DIR"

OUTPUT_FILE="$OUTPUT_DIR/block_traces_${START_BLOCK}_${END_BLOCK}.json"
TEMP_FILE="$OUTPUT_DIR/temp_traces.json"

echo "Fetching block traces from block $START_BLOCK to $END_BLOCK..."
echo "RPC URL: $RPC_URL"
echo "Output file: $OUTPUT_FILE"
echo ""

# Initialize the JSON array
echo "[" > "$TEMP_FILE"

FIRST=true
SUCCESS_COUNT=0
FAIL_COUNT=0

# Iterate through blocks
for ((block=$START_BLOCK; block<=$END_BLOCK; block++)); do
# Convert block number to hex
BLOCK_HEX=$(printf "0x%x" $block)

echo -n "Fetching block $block (${BLOCK_HEX})... "

# Fetch the block trace
TRACE=$(cast rpc morph_getBlockTraceByNumberOrHash "$BLOCK_HEX" --rpc-url "$RPC_URL" 2>/dev/null)

if [ $? -eq 0 ] && [ -n "$TRACE" ] && [ "$TRACE" != "null" ]; then
# Add comma separator if not first element
if [ "$FIRST" = false ]; then
echo "," >> "$TEMP_FILE"
fi
FIRST=false

# Wrap the trace in an array and append to file
echo " [" >> "$TEMP_FILE"
echo " $TRACE" >> "$TEMP_FILE"
echo -n " ]" >> "$TEMP_FILE"

echo "✓ Success"
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
else
echo "✗ Failed (empty or null response)"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
done

# Close the JSON array
echo "" >> "$TEMP_FILE"
echo "]" >> "$TEMP_FILE"

# Validate and format JSON
echo ""
echo "Validating and formatting JSON..."
if jq empty "$TEMP_FILE" 2>/dev/null; then
jq '.' "$TEMP_FILE" > "$OUTPUT_FILE"
rm "$TEMP_FILE"
echo "✓ JSON is valid and formatted"
else
echo "✗ Error: Invalid JSON generated"
echo "Temp file saved at: $TEMP_FILE"
exit 1
fi

echo ""
echo "Summary:"
echo " Total blocks: $((END_BLOCK - START_BLOCK + 1))"
echo " Successfully fetched: $SUCCESS_COUNT"
echo " Failed: $FAIL_COUNT"
echo " Output file (absolute): $(cd "$(dirname "$OUTPUT_FILE")" && pwd)/$(basename "$OUTPUT_FILE")"
echo ""

# If all blocks failed, exit
if [ "$SUCCESS_COUNT" -eq 0 ]; then
echo "Error: No blocks were successfully fetched"
exit 1
fi

# Run Rust verification
echo "================================================"
echo "Running Rust verification..."
echo "================================================"
echo ""

cd "$(dirname "$0")/.."

# Update OUTPUT_FILE path to be relative to prover directory
OUTPUT_FILE_FOR_RUST="./testdata/$OUTPUT_FILE"

RUST_LOG=info TRUSTED_SETUP_4844=./configs/4844_trusted_setup.txt cargo run --release -- --block-path "$OUTPUT_FILE_FOR_RUST"

RUST_EXIT_CODE=$?

echo ""
echo "================================================"
if [ $RUST_EXIT_CODE -eq 0 ]; then
echo "✓ Verification completed successfully!"
else
echo "✗ Verification failed with exit code $RUST_EXIT_CODE"
fi
echo "================================================"

exit $RUST_EXIT_CODE