Skip to content
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ devnet/saved-cannon-data
devnet/init.log
devnet/l1-geth/
profiling/
devnet/mainnet.genesis.json
39 changes: 24 additions & 15 deletions devnet/3-op-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,31 @@ sed_inplace() {
fi
}

# Check if FORK_BLOCK is set
if [ -z "$FORK_BLOCK" ]; then
echo " ❌ FORK_BLOCK environment variable is not set"
echo "Please set FORK_BLOCK in your .env file"
exit 1
fi
# ========================================
# Genesis Preparation
# ========================================
if [ "$USE_FAKE_MAINNET" = "true" ]; then
# Fake mainnet mode: use unified script with mainnet genesis
source scripts/prepare-genesis.sh
_prepare_mainnet_genesis
else
# Original generated genesis logic
if [ -z "$FORK_BLOCK" ]; then
echo " ❌ FORK_BLOCK environment variable is not set"
echo "Please set FORK_BLOCK in your .env file"
exit 1
fi

FORK_BLOCK_HEX=$(printf "0x%x" "$FORK_BLOCK")
sed_inplace '/"config": {/,/}/ s/"optimism": {/"legacyXLayerBlock": '"$((FORK_BLOCK + 1))"',\n "optimism": {/' ./config-op/genesis.json
sed_inplace 's/"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"/"parentHash": "'"$PARENT_HASH"'"/' ./config-op/genesis.json
sed_inplace '/"70997970c51812dc3a010c7d01b50e0d17dc79c8": {/,/}/ s/"balance": "[^"]*"/"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"/' ./config-op/genesis.json
NEXT_BLOCK_NUMBER=$((FORK_BLOCK + 1))
NEXT_BLOCK_NUMBER_HEX=$(printf "0x%x" "$NEXT_BLOCK_NUMBER")
sed_inplace 's/"number": 0/"number": '"$NEXT_BLOCK_NUMBER"'/' ./config-op/rollup.json
cp ./config-op/genesis.json ./config-op/genesis-reth.json
sed_inplace 's/"number": "0x0"/"number": "'"$NEXT_BLOCK_NUMBER_HEX"'"/' ./config-op/genesis-reth.json
FORK_BLOCK_HEX=$(printf "0x%x" "$FORK_BLOCK")
sed_inplace '/"config": {/,/}/ s/"optimism": {/"legacyXLayerBlock": '"$((FORK_BLOCK + 1))"',\n "optimism": {/' ./config-op/genesis.json
sed_inplace 's/"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"/"parentHash": "'"$PARENT_HASH"'"/' ./config-op/genesis.json
sed_inplace '/"70997970c51812dc3a010c7d01b50e0d17dc79c8": {/,/}/ s/"balance": "[^"]*"/"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"/' ./config-op/genesis.json
NEXT_BLOCK_NUMBER=$((FORK_BLOCK + 1))
NEXT_BLOCK_NUMBER_HEX=$(printf "0x%x" "$NEXT_BLOCK_NUMBER")
sed_inplace 's/"number": 0/"number": '"$NEXT_BLOCK_NUMBER"'/' ./config-op/rollup.json
cp ./config-op/genesis.json ./config-op/genesis-reth.json
sed_inplace 's/"number": "0x0"/"number": "'"$NEXT_BLOCK_NUMBER_HEX"'"/' ./config-op/genesis-reth.json
fi

# Extract contract addresses from state.json and update .env file
echo "🔧 Extracting contract addresses from state.json..."
Expand Down
5 changes: 5 additions & 0 deletions devnet/example.env
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ SKIP_BUILD_PRESTATE=false
# Set to false if you need full mode with op-proposer, op-challenger, op-dispute-mon
MIN_RUN=true

# ==============================================================================
# Fake Mainnet Configuration
# ==============================================================================
USE_FAKE_MAINNET=false

# ==============================================================================
# Docker & Network Configuration
# ==============================================================================
Expand Down
233 changes: 233 additions & 0 deletions devnet/scripts/prepare-genesis.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#!/bin/bash
# ==============================================================================
# prepare-genesis.sh - Unified genesis preparation script
# ==============================================================================
# Supports two modes:
# 1. Mainnet genesis mode (USE_FAKE_MAINNET=true)
# - Downloads and uses real mainnet genesis data (6.6GB+)
# - Requires MIN_RUN=true
# 2. Generated genesis mode (default)
# - Uses genesis generated by op-deployer
#
# Usage:
# source scripts/prepare-genesis.sh # Called from 3-op-init.sh
# ./scripts/prepare-genesis.sh # Standalone execution
# ==============================================================================

set -e

MAINNET_GENESIS_URL="https://okg-pub-hk.oss-cn-hongkong.aliyuncs.com/cdn/chain/xlayer/snapshot/merged.genesis.json.mainnet.tar.gz"
MAINNET_GENESIS_PATH="mainnet.genesis.json"
TEST_ACCOUNT_ADDRESS="0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
TEST_ACCOUNT_BALANCE="0x52B7D2DCC80CD2E4000000" # 100,000 ETH

# ==============================================================================
# Helper Functions
# ==============================================================================
_sed_inplace() {
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "$@"
else
sed -i "$@"
fi
}

# ==============================================================================
# Download Mainnet Genesis
# ==============================================================================
_download_mainnet_genesis() {
if [ -f "$MAINNET_GENESIS_PATH" ]; then
echo "✅ Mainnet genesis already exists: $MAINNET_GENESIS_PATH"
return 0
fi

echo "📥 Downloading mainnet genesis..."
echo " URL: $MAINNET_GENESIS_URL"

local TAR_FILE="mainnet-genesis.tar.gz"

# Download
if ! curl -L --progress-bar "$MAINNET_GENESIS_URL" -o "$TAR_FILE"; then
echo "❌ ERROR: Failed to download mainnet genesis"
exit 1
fi

echo "📂 Extracting..."
tar -xzf "$TAR_FILE"

# Find and rename the extracted file
if [ -f "merged.genesis.json" ]; then
mv "merged.genesis.json" "$MAINNET_GENESIS_PATH"
elif [ -f "merged.genesis.json.mainnet" ]; then
mv "merged.genesis.json.mainnet" "$MAINNET_GENESIS_PATH"
else
echo "❌ ERROR: Extraction failed (genesis file not found in archive)"
rm -f "$TAR_FILE"
exit 1
fi

rm -f "$TAR_FILE"
echo "✅ Downloaded and extracted successfully"
}

# ==============================================================================
# Mainnet Genesis Mode
# ==============================================================================
_prepare_mainnet_genesis() {
echo ""
echo "🌐 Mainnet genesis mode enabled"

# 1. Enforce MIN_RUN requirement
if [ "$MIN_RUN" != "true" ]; then
echo ""
echo "❌ ERROR: Mainnet genesis requires MIN_RUN=true"
echo ""
echo "Reason:"
echo " • Mainnet genesis is too large (6.6GB+)"
echo " • Building op-program prestate would fail or timeout"
echo " • Dispute game features are not compatible with mainnet data"
echo ""
echo "Solution:"
echo " Set MIN_RUN=true in your .env file"
echo ""
exit 1
fi
echo "✅ MIN_RUN=true verified"

# 2. Download genesis if not exists
_download_mainnet_genesis

# Verify file size
GENESIS_SIZE_MB=$(du -m "$MAINNET_GENESIS_PATH" | cut -f1)
GENESIS_SIZE_GB=$(echo "scale=2; $GENESIS_SIZE_MB / 1024" | bc)
echo "✅ Found mainnet genesis ($GENESIS_SIZE_GB GB)"

# 3. Validate configuration
if [ -z "$FORK_BLOCK" ] || [ -z "$PARENT_HASH" ]; then
echo "❌ ERROR: FORK_BLOCK and PARENT_HASH must be set"
exit 1
fi

if [ -z "$CHAIN_ID" ]; then
echo "❌ ERROR: CHAIN_ID must be set"
exit 1
fi

NEXT_BLOCK=$((FORK_BLOCK + 1))
echo ""
echo "🎯 Configuration:"
echo " • CHAIN_ID: $CHAIN_ID"
echo " • FORK_BLOCK: $FORK_BLOCK"
echo " • PARENT_HASH: $PARENT_HASH"
echo " • Next block: $NEXT_BLOCK"
echo " • Test account: $TEST_ACCOUNT_ADDRESS"

# 4. Process genesis using embedded Python (optimized for large files)
echo ""
echo "🔧 Processing genesis (this may take 1-2 minutes)..."

mkdir -p "$CONFIG_DIR"

# Run embedded Python script
python3 - "$MAINNET_GENESIS_PATH" "$CONFIG_DIR/genesis.json" "$NEXT_BLOCK" "$PARENT_HASH" "$CHAIN_ID" "$TEST_ACCOUNT_ADDRESS" "$TEST_ACCOUNT_BALANCE" << 'PYTHON_EOF'
import json
import sys
import os
import time

def main():
input_file = sys.argv[1]
output_file = sys.argv[2]
next_block = int(sys.argv[3])
parent_hash = sys.argv[4]
chain_id = int(sys.argv[5])
test_account = sys.argv[6] if len(sys.argv) > 6 and sys.argv[6] else None
test_balance = sys.argv[7] if len(sys.argv) > 7 and sys.argv[7] else None

# Load genesis
file_size_gb = os.path.getsize(input_file) / (1024**3)
print(f" Loading genesis ({file_size_gb:.2f} GB)...")

with open(input_file, 'r') as f:
genesis = json.load(f)

account_count = len(genesis.get('alloc', {}))
print(f" ✓ Loaded {account_count:,} accounts")

# Update config fields
if 'config' not in genesis:
genesis['config'] = {}

# Replace chainId with configured value
old_chain_id = genesis['config'].get('chainId', 'unknown')
genesis['config']['chainId'] = chain_id
print(f" ✓ chainId: {old_chain_id} → {chain_id}")

genesis['config']['legacyXLayerBlock'] = next_block
genesis['config']['jovianTime'] = 0 # Enable Jovian upgrade
genesis['parentHash'] = parent_hash
genesis['number'] = 0 # Required for geth init

# Update timestamp to 15 minutes in the future (avoid conductor "unsafe head falling behind" error)
# This gives buffer time between init and service startup
current_timestamp = int(time.time()) + 15 * 60 # +15 minutes
genesis['timestamp'] = hex(current_timestamp)

print(f" ✓ legacyXLayerBlock: {next_block}")
print(f" ✓ jovianTime: 0 (Jovian upgrade enabled)")
print(f" ✓ parentHash: {parent_hash[:20]}...")
print(f" ✓ number: 0 (required for geth init)")
print(f" ✓ timestamp: {hex(current_timestamp)} (+15min from now)")

# Inject test account (enabled by default in mainnet mode)
if test_account and test_balance:
if 'alloc' not in genesis:
genesis['alloc'] = {}

account_key = test_account.lower()
if account_key.startswith('0x'):
account_key = account_key[2:]

if account_key in genesis['alloc']:
print(f" ⚠️ Account {test_account} exists, updating balance...")
genesis['alloc'][account_key]['balance'] = test_balance
else:
print(f" 💰 Injecting test account {test_account}...")
genesis['alloc'][account_key] = {"balance": test_balance}

balance_eth = int(test_balance, 16) / (10**18)
print(f" ✓ Test balance: {balance_eth:,.0f} ETH")

# Write genesis.json
print(f" Writing genesis.json...")
with open(output_file, 'w') as f:
json.dump(genesis, f, separators=(',', ':'))

# Create reth version (number as hex string "0x0")
reth_file = output_file.replace('.json', '-reth.json')
genesis['number'] = "0x0"

print(f" Writing genesis-reth.json...")
with open(reth_file, 'w') as f:
json.dump(genesis, f, separators=(',', ':'))

output_size_gb = os.path.getsize(output_file) / (1024**3)
print(f" ✓ Output size: {output_size_gb:.2f} GB")

if __name__ == '__main__':
main()
PYTHON_EOF

if [ $? -ne 0 ]; then
echo "❌ ERROR: Failed to process mainnet genesis"
exit 1
fi

# 5. Update rollup.json
_sed_inplace 's/"number": 0/"number": '"$NEXT_BLOCK"'/' ./config-op/rollup.json

echo ""
echo "✅ Mainnet genesis prepared"
echo " • Output: $CONFIG_DIR/genesis.json"
echo " • Reth version: $CONFIG_DIR/genesis-reth.json"
}