every.channel/evolution/proposals/ECP-0093-ecp-forge-op-stack-sepolia-observation-testnet.md

6.1 KiB

ECP-0093: ecp-forge OP Stack Sepolia testnet and observation consensus rail

Status: Draft

Problem / context

every.channel now has additive Ethereum-compatible commitments and signatures, but it does not yet have:

  • a concrete chain-operator path for bringing up a real OP Stack testnet on ecp-forge,
  • a repo-owned bootstrap workflow that matches the current official OP Stack deployment guidance,
  • an application-level consensus surface for "reality-derived" blocks where witnesses attest to the same observed broadcast epoch, or
  • a reproducible smoke path that pushes real every.channel archive data through the rail.

The current EveryChannelRail contract is useful as a compact pointer store, but it does not capture the consensus shape requested by the founder: nodes independently discover an observation from reality, then witnesses sign off on that shared observation hash.

Decision

Adopt a two-part rollout:

  1. Stand up an OP Stack Sepolia-anchored testnet on ecp-forge using the official OP Stack stack: op-deployer, op-geth, op-node, op-batcher, op-proposer, op-challenger, and optional op-dispute-mon.
  2. Introduce an application-level observation consensus rail for every.channel:
    • an ObservationHeader is derived from real stream epoch data,
    • witnesses attest to the derived observation hash,
    • the observation is finalized when quorum is reached,
    • full media bytes remain off-chain.

This keeps Ethereum as the ordering/finality substrate while making the application-level "block" come from reality, not from arbitrary contract writes.

Details

ecp-forge OP Stack deployment

  • Use the official OP Stack deployment topology described in the current Optimism chain-operator tutorial:
    • Sepolia L1 contracts via op-deployer,
    • op-geth + op-node sequencer,
    • op-batcher,
    • op-proposer,
    • op-challenger,
    • optional op-dispute-mon.
  • Host these components on ecp-forge via repo-owned NixOS services and pinned official container images.
  • Keep L2 RPC surfaces private by default; expose P2P only as required for testnet participation.
  • Default L1 RPC / beacon endpoints may use public Sepolia providers, but deployment and operation require a repo-managed Sepolia private key secret with sufficient ETH.
  • op-challenger and op-dispute-mon require a repo-managed Cannon absolute prestate artifact. If the prestate is absent, the core rollup may still run, but the dispute path is intentionally gated off instead of starting with incomplete configuration.

Observation consensus

Introduce a new application-level surface alongside EveryChannelRail:

  • ObservationHeader
    • streamHash
    • epochHash
    • parentObservationHash
    • dataRoot
    • locatorHash
    • observedUnixMs
    • sequence
  • ObservationHash
    • keccak256(abi.encode(ObservationHeader))
  • ObservationSlot
    • keccak256(abi.encode(streamHash, epochHash))

Witnesses attest to an ObservationHash, not directly to arbitrary payloads. This lets the chain finalize the winning observation for a (stream, epoch) slot without storing the full manifest, chunk list, PSIP data, or media bytes.

Witness model

For the first testnet tranche:

  • witness membership is registry-backed,
  • quorum is fixed and explicit,
  • no staking or slashing is required,
  • sending an attestation transaction from a witness address is sufficient "sign off".

Off-chain EIP-712 witness signatures may be added later for relayed submission, but they are not a prerequisite for the first live testnet.

Real-data validation

Use real every.channel archive data already present on ecp-forge as the smoke source:

  • derive observation headers from actual archive JSONL entries,
  • submit them to a local Anvil deployment of the observation ledger,
  • prove quorum/finalization against production-shaped data before attempting Sepolia rollout.

Components

  • contracts/EveryChannelRail.sol
    • compact manifest / transport pointer store (existing rail)
  • contracts/EveryChannelWitnessRegistry.sol
    • witness membership for observation consensus
  • contracts/EveryChannelObservationLedger.sol
    • candidate observation storage, attestation tracking, and finalization
  • scripts/op-stack/download-op-deployer.sh
    • pinned op-deployer fetch helper
  • scripts/op-stack/setup-rollup.sh
    • repo-owned OP Stack bootstrap/config generation
  • scripts/op-stack/anvil-reality-smoke.sh
    • local smoke against Anvil using real ecp-forge archive data
  • nix/modules/ec-op-stack.nix
    • NixOS service/module surface for ecp-forge

Alternatives considered

  • Use Base Sepolia directly as the only test environment. Rejected because it validates contract compatibility, but not operation of an every.channel-owned chain.
  • Wait for a future custom consensus implementation before any chain bring-up. Rejected because it delays operator learning and hides infrastructure problems until late.
  • Put media bytes or full manifests on chain. Rejected because it is operationally wasteful and not required for observation finalization.

Rollout / teardown plan

  1. Add the observation-ledger contracts and Foundry tests.
  2. Add Anvil + real-archive smoke scripts.
  3. Add an ec-op-stack Nix module and ecp-forge integration points.
  4. Wire secrets for a Sepolia deployment key on ecp-forge.
  5. Bring up the OP Stack services on ecp-forge.
  6. Deploy observation-ledger contracts onto the new chain.
  7. Submit real archive-derived observations and verify finalization.

Teardown:

  • disable services.every-channel.op-stack,
  • stop and remove the OP Stack containers/state directories,
  • preserve the local Anvil smoke path and the additive Ethereum rail code.

Open questions

  • Should ecp-forge be the only sequencer for the first tranche, or should a second verifier-only peer be provisioned immediately?
  • When we move beyond a registry-backed witness set, do we want bonds, reputation, or both?
  • Should finalized observation slots bridge back into the existing manifest/transport pointer contract automatically, or remain a separate ledger surface for the first rollout?