datahaven/operator
Ahmad Kaouk 55e973b8f0
fix: change pallet_evm alias to EVM to fix eth_getCode (#213)
## Summary
- rename the FRAME alias for `pallet_evm` from `Evm` to `EVM` across the
mainnet, stagenet, and testnet runtimes
- adjust benchmarks, configuration modules, genesis builders, and
runtime tests to rely on the new alias
- keep precompile genesis setup and proxy/precompile tests aligned with
the updated names

  ## Context
Frontier’s `StorageOverrideHandler` (see
`fc_storage::StorageQuerier::account_code`) reads contract bytecode from
`pallet_evm::AccountCodes` using the constant `PALLET_EVM = b"EVM"` to
build the storage key:
  `twox_128("EVM") ++ twox_128("AccountCodes") ++ …`

Our runtimes exported `pallet_evm` as `Evm`, so substrate stored
bytecode under the *camel-cased* prefix (`twox_128("Evm")`). Every call
that ultimately hits the storage override—including `eth_getCode`,
`eth_call`, and state queries during replay—therefore failed to locate
code for *any* account (deployed contracts and precompiles alike).
Renaming the alias to `EVM` realigns the storage prefix with Frontier’s
  expectations so the override layers can pull bytecode correctly.

  ## Testing
  - `cargo check -p datahaven-node`
  - `cargo build --release -p datahaven-node`
- `eth_getCode 0x0000000000000000000000000000000000000802` → returns
`0x60006000fd`
  
## Storage Migration
Renaming a pallet alias changes the storage prefix for all pallet data.
Without migration, existing EVM data (smart contracts, account codes,
storage) would become inaccessible.

  **Migration details:**

  - **Type**: Multi-Block Migration (MBM)
- **Storage migrated**: `AccountCodes`, `AccountCodesMetadata`,
`AccountStorages`
  - **Migration ID**: `datahaven-evm-mbm` (version 0 → 1)

  **Testing the migration:**

  ```bash
  # Build runtime with try-runtime
cargo build --release --features try-runtime -p
datahaven-stagenet-runtime

  # Test against stagenet
try-runtime \
--runtime
./target/release/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.wasm
\
      on-runtime-upgrade \
      --blocktime 6000 \
      --checks all \
      --disable-spec-version-check \
      live --uri wss://dh-validator-0.datahaven-kt.xyz
```

  Test results from stagenet:
  -  Migration completes in 1 block
  -  PoV size: ~5.3 KB
  -  Weight consumption: <0.1% of block capacity
  -  All 39 keys successfully migrated

  ## ⚠️ Breaking Changes ⚠️
If you are manually computing storage keys for the EVM pallet (e.g., directly querying chain state), you must update your code to use the new storage prefix:
  - Old prefix: twox128("Evm") = 0x8b90cb...
  - New prefix: twox128("EVM") = 0x6a5e91...

  All EVM-facing interfaces remain unchanged.
2025-10-10 17:48:52 +00:00
..
.cargo refactor: 🐳 Improve docker caching (again) (#86) 2025-05-27 16:14:15 +00:00
benchmarking test: init benchmark infra (#110) 2025-08-06 13:44:42 +02:00
node fix: resolve srtool metadata hash build error (#219) 2025-10-10 15:04:03 +02:00
pallets feat: Bump client version to v0.2.0 & runtime spec_version to 200 (#194) 2025-09-29 23:35:12 +02:00
precompiles fix: change pallet_evm alias to EVM to fix eth_getCode (#213) 2025-10-10 17:48:52 +00:00
primitives feat: Bump client version to v0.2.0 & runtime spec_version to 200 (#194) 2025-09-29 23:35:12 +02:00
runtime fix: change pallet_evm alias to EVM to fix eth_getCode (#213) 2025-10-10 17:48:52 +00:00
scripts Revert "fix: 🔧 Fix build runtime srtool permission issue" (#221) 2025-10-10 18:15:22 +02:00
.dockerignore refactor: 🐳 Improve docker caching (again) (#86) 2025-05-27 16:14:15 +00:00
.gitignore test: Native token transfer e2e tests (#120) 2025-08-22 18:27:14 +02:00
Cargo.lock fix: change pallet_evm alias to EVM to fix eth_getCode (#213) 2025-10-10 17:48:52 +00:00
Cargo.toml feat: add preimage precompile (#211) 2025-10-09 13:16:46 +02:00
Dockerfile ci: remove sccache from image build for prod (#200) 2025-10-09 12:33:35 +00:00
LICENSE build: 🏗️ DataHaven operator setup (#6) 2025-03-17 17:57:14 +01:00
README.md chore: ♻️ Update README files (#206) 2025-10-06 18:12:55 +02:00
rust-toolchain.toml fix: 🔧 Add revision number to rust toolchain channel version to match with srtool image version (#209) 2025-10-07 11:34:21 +02:00

DataHaven Operator (Substrate Node) 🫎

The DataHaven operator is a Substrate-based blockchain node that serves as an EigenLayer AVS operator. It combines Substrate's modular framework with EVM compatibility (via Frontier) and cross-chain capabilities (via Snowbridge).

Overview

Built on the polkadot-sdk-solochain-template, this node implements:

  • EVM Compatibility: Full Ethereum compatibility via Frontier pallets
  • EigenLayer Integration: Operator registration and management via AVS contracts
  • External Validators: Dynamic validator set controlled by EigenLayer registry
  • Cross-chain Communication: Token and message passing via Snowbridge
  • Rewards System: Performance-based validator rewards from Ethereum

Project Structure

operator/
├── node/                          # Node implementation
│   ├── src/
│   │   ├── chain_spec.rs         # Chain specification & genesis config
│   │   ├── cli.rs                # CLI interface
│   │   ├── command.rs            # Command handlers
│   │   ├── rpc.rs                # RPC configuration
│   │   └── service.rs            # Node service setup
├── pallets/                       # Custom pallets
│   ├── external-validators/      # EigenLayer validator set management
│   ├── native-transfer/          # Cross-chain token transfers
│   └── rewards/                   # Validator rewards distribution
├── runtime/                       # Runtime configurations
│   ├── mainnet/                  # Mainnet runtime
│   ├── stagenet/                 # Stagenet runtime
│   └── testnet/                  # Testnet runtime (with fast-runtime feature)
└── scripts/                       # Utility scripts
    └── run-benchmarks.sh         # Runtime benchmarking automation

Prerequisites

Building

Development Build (Fast Runtime)

For local development with faster block times:

cargo build --release --features fast-runtime

This enables 3-second block times instead of the production 12-second blocks.

Production Build

For production or stagenet deployments:

cargo build --release

Running Tests

# Run all tests
cargo test

# Run tests for specific pallet
cargo test -p pallet-external-validators

# Run with output
cargo test -- --nocapture

Code Quality

# Format code
cargo fmt

# Lint with clippy
cargo clippy --all-targets --all-features

Benchmarking

DataHaven uses runtime benchmarking to generate accurate weight calculations for all pallets. The benchmarking process is automated using frame-omni-bencher.

Requirements

  • Latest Rust stable version
  • frame-omni-bencher: Install with cargo install frame-omni-bencher --profile=production

Running Benchmarks

Execute from the operator directory:

# Benchmark all pallets for testnet runtime (default)
./scripts/run-benchmarks.sh

# Benchmark specific runtime
./scripts/run-benchmarks.sh mainnet

# Custom steps and repetitions
./scripts/run-benchmarks.sh testnet 100 50

The script will:

  1. Discover all available pallets
  2. Build runtime WASM with runtime-benchmarks feature
  3. Generate weight files in runtime/{runtime}/src/weights/
  4. Provide summary of results

Parameters:

  • runtime: Runtime to benchmark (testnet, stagenet, mainnet). Default: testnet
  • steps: Number of steps. Default: 50
  • repeat: Number of repetitions. Default: 20

Zombienet Testing

Zombienet provides local multi-validator network testing.

Setup

  1. Install Zombienet:

    # Download binary from releases
    # Or install via npm
    npm install -g @zombienet/cli
    
  2. Spawn local network with four validators:

    zombienet -p native spawn test/config/zombie-datahaven-local.toml
    

This launches a local solochain with BABE consensus for testing validator coordination.

Docker Image

Build local Docker image for testing:

cd ../test
bun build:docker:operator

This creates datahavenxyz/datahaven:local using optimized caching:

  • sccache: Rust build caching
  • cargo-chef: Dependency layer caching
  • BuildKit cache mounts: External cache restoration

Type Generation

After runtime changes, regenerate Polkadot-API TypeScript types:

cd ../test
bun generate:types           # Production runtime
bun generate:types:fast      # Fast runtime (development)

Integration Testing

For full network integration tests with Ethereum, Snowbridge, and contracts:

cd ../test
bun cli launch               # Interactive launcher
bun test:e2e                 # Run E2E test suite

See the test directory for comprehensive testing documentation.

Custom Pallets

External Validators

Manages the dynamic validator set based on EigenLayer operator registry. Syncs validator changes from Ethereum to the Substrate consensus layer.

Location: pallets/external-validators/

Native Transfer

Handles cross-chain token transfers between Ethereum and DataHaven via Snowbridge messaging.

Location: pallets/native-transfer/

Rewards

Distributes performance-based rewards to validators, processing reward messages from the Ethereum RewardsRegistry contract.

Location: pallets/rewards/

Each pallet includes its own tests and benchmarks. See pallet-specific README files for details.