158 lines
6.7 KiB
Markdown
158 lines
6.7 KiB
Markdown
# ECP-0092: Ethereum rails and private settlement for every.channel
|
||
|
||
Status: Draft
|
||
|
||
## Problem / context
|
||
|
||
`every.channel` already has useful anti-junk and manifest integrity primitives, but they stop at
|
||
repo-local formats: custom Merkle trees, JSON body hashes, and Ed25519 signatures. That is enough
|
||
for local validation, not for the broader direction now requested:
|
||
|
||
- stream identity, broadcast de-duplication, manifests, and transport announcements should all have
|
||
Ethereum-compatible representations,
|
||
- private-chain settlement should reuse existing Ethereum tooling instead of inventing a custom
|
||
ledger,
|
||
- iroh should remain the transport substrate,
|
||
- storage on chain must stay compact, and
|
||
- `ecp-forge` should become the high-bandwidth head node for sequencing, archival, and bootstrap.
|
||
|
||
This supersedes the specific ECP-0022 alternative that rejected “global consensus / blockchain for
|
||
manifests” as overkill. The new direction is not a public general-purpose chain. It is a private,
|
||
Ethereum-compatible settlement rail for every.channel commitments.
|
||
|
||
## Decision
|
||
|
||
Adopt a dual-plane architecture:
|
||
|
||
- `iroh` remains the transport, discovery, and media movement layer.
|
||
- Local protocol integrity remains first-class:
|
||
- `manifest_id` stays BLAKE3 over the manifest body,
|
||
- object membership proofs stay `merkle+blake3`,
|
||
- Ed25519 manifest signatures remain supported.
|
||
- Ethereum-compatible commitments become an additive settlement/mirroring layer for stream
|
||
identity, transport announcements, and manifests.
|
||
- Ethereum-native signatures are added alongside local signatures:
|
||
- manifests may carry secp256k1 EIP-712 signatures over `ManifestBody`,
|
||
- no existing local signature path is removed as part of this proposal.
|
||
- On-chain state remains compact:
|
||
- manifests store only stream/epoch ids plus commitment hashes,
|
||
- control announcements store only stream ids plus announcement commitments,
|
||
- full media bytes, manifests, PSIP tables, and chunk inventories remain off-chain.
|
||
- The chain is private and purpose-built for every.channel use cases:
|
||
- no arbitrary application compute in the near term,
|
||
- no fraud-proof system in the near term,
|
||
- permissionless submission as far as operationally possible,
|
||
- pseudonymous participation preferred over account-heavy identity.
|
||
|
||
## Details
|
||
|
||
### Canonical Ethereum representations
|
||
|
||
Introduce Solidity-compatible struct mirrors for the protocol surfaces we actually ship:
|
||
|
||
- `BroadcastId`
|
||
- `SourceId`
|
||
- `StreamKey`
|
||
- `StreamDescriptor`
|
||
- `StreamControlAnnouncement`
|
||
- `ChunkId`
|
||
- `ManifestVariant`
|
||
- `ManifestBody`
|
||
- `ManifestSignature`
|
||
- `Manifest`
|
||
|
||
These are encoded via Solidity ABI rules and hashed with `keccak256`. They mirror the shipped
|
||
protocol types; they do not replace the local wire format or local hashing rules.
|
||
|
||
### Manifest commitments
|
||
|
||
Publisher-generated manifests may carry a set of Ethereum commitments as first-class fields:
|
||
|
||
- `manifest-data-merkle-keccak256-v1`
|
||
- Keccak Merkle root over ordered chunk hashes, or over ordered variant roots for multi-variant
|
||
manifests.
|
||
- `manifest-body-abi-keccak256-v1`
|
||
- `keccak256(abi.encode(EthManifestBody))`
|
||
- `manifest-envelope-abi-keccak256-v1`
|
||
- `keccak256(abi.encode(EthManifest))`
|
||
|
||
`manifest_id` and `merkle_root` remain the local BLAKE3-backed protocol fields. Ethereum
|
||
commitments are explicit, separately named, and never inferred from those local field names alone.
|
||
|
||
### Signature rails
|
||
|
||
Manifest signatures become dual-rail:
|
||
|
||
- local signatures continue to sign the local BLAKE3 `manifest_id` with Ed25519,
|
||
- Ethereum-native signatures sign the typed `EthManifestBody` with secp256k1 EIP-712,
|
||
- both signature families may appear on the same manifest.
|
||
|
||
The Ethereum signature target is `ManifestBody`, not the full manifest envelope, so signatures do
|
||
not become self-referential when more signatures are appended.
|
||
|
||
### Stream and control commitments
|
||
|
||
Stream descriptors and control announcements may also carry Ethereum-compatible commitments:
|
||
|
||
- `stream-id-keccak256-v1`
|
||
- `stream-descriptor-abi-keccak256-v1`
|
||
- `control-announcement-abi-keccak256-v1`
|
||
|
||
This ties broadcast-scoped discovery identity to the same settlement vocabulary used by manifests
|
||
without forcing transport-time consumers to abandon the local vocabulary they already use.
|
||
|
||
### Solidity rail contract
|
||
|
||
Add a minimal contract that stores only the latest compact pointers:
|
||
|
||
- latest manifest pointer per `stream_id + epoch_id`
|
||
- latest transport announcement pointer per `stream_id`
|
||
- event emissions for historical indexing
|
||
|
||
The contract must stay event-heavy and storage-light. Full manifests stay in iroh / relay / archive
|
||
storage.
|
||
|
||
### `ecp-forge` role
|
||
|
||
`ecp-forge` becomes the maximal head node for this network:
|
||
|
||
- private-chain bootstrap and packaging,
|
||
- archival indexer for settlement events,
|
||
- high-bandwidth manifest and control announcer,
|
||
- optional sequencer / execution-client host for the private network.
|
||
|
||
This role is operational, not constitutional. Other nodes must still be able to validate, mirror,
|
||
and submit commitments without going through a closed control plane.
|
||
|
||
## Alternatives considered
|
||
|
||
- Keep custom BLAKE3-only manifests forever. Rejected because it strands every.channel outside the
|
||
tooling and audit surface of the Ethereum ecosystem.
|
||
- Replace BLAKE3 and Ed25519 immediately. Rejected because it weakens the local protocol’s existing
|
||
integrity path before the private rail is operational and discards useful cryptographic
|
||
properties for no near-term operational win.
|
||
- Build a custom blockchain. Rejected because existing Rust + Solidity stacks are already good
|
||
enough and reduce implementation risk.
|
||
- Use public Ethereum mainnet / arbitrary public L2s directly. Rejected for now because cost,
|
||
privacy, and operational control do not fit the current network shape.
|
||
|
||
## Rollout / teardown plan
|
||
|
||
1. Add `ec-eth` with canonical Solidity-compatible representations and Keccak commitments.
|
||
2. Preserve the local BLAKE3/Ed25519 rail as the default transport integrity path.
|
||
3. Add optional secp256k1 EIP-712 manifest-body signatures alongside Ed25519 signatures.
|
||
4. Add the minimal Solidity rail contract for compact settlement pointers.
|
||
5. Teach publishers/indexers to mirror manifests and announcements onto the private chain.
|
||
6. Stand up the private Ethereum-compatible network on `ecp-forge` and companion nodes.
|
||
|
||
Teardown:
|
||
|
||
- back out the Ethereum rail changes explicitly in code; the preserved local rail remains as the
|
||
fallback integrity path.
|
||
|
||
## Open questions
|
||
|
||
- Which execution stack should back the private network first: a slim Reth-based node, or a more
|
||
minimal Rust EVM deployment?
|
||
- When the private rail becomes live, do we require both signature families for publisher policy, or
|
||
is one valid rail-specific signature enough for a given transport or settlement action?
|