Skip to content
Ephernity

§ 02 · Specification overview

The Protocol — what is, in fact, written down.

Ephernity specifies two complementary pillars on one substrate: a hash-chained, content-addressed, per-entry signed micro-ledger whose retention is a tier parameter; and a deterministic contract dialect whose execution is committed to the same ledger. This page is the orientation; the binding text lives in the RFC suite.


§ 02.01

Wire format.

Every entry is a tuple (header, payload). The header is a 131-byte canonical record (RFC-EPH-003); the payload is opaque bytes addressed by BLAKE3-256.

borz listing
pub type EntryHeader = {
    payload_cid: bytes32,    // blake3(payload)
    prev_hash:   bytes32,    // blake3(prior header)
    seq:         uint64,
    ts_ms:       uint64,
    ttl:         uint64,     // resolved TTL canonical seconds; 0 = unbounded
    sig_scheme:  Scheme,     // Ed25519 | Falcon1024
    signer_id:   bytes32,    // HATP host key id
    reserved:    bytes[14],  // zero
}
Entry header — 131 bytes, big-endian, no padding

§ 02.02

Hash chain.

Each header references the BLAKE3 hash of its predecessor via prev_hash. The chain is therefore tamper-evident: any modification of entry n invalidates the hash of every subsequent entry. Verification walks the chain in O(N).

Periodic Merkle checkpoints (RFC-EPH-004) produce an O(log N) inclusion proof: a verifier can prove entry x is at position y in epoch z with a path of roughly ⌈log₂ N⌉ hashes.

§ 02.03

TTL and tier presets.

TTL is the underlying primitive: any duration from one millisecond to unbounded. The eight named tiers — T0 through T7 — are presets that fix a (retention, anchoring, signature) triple at commonly-needed horizons. Supply a preset name, a duration string, or raw seconds; the resolved value is always canonical seconds in the receipt.

borz listing
// Named preset → canonical TTL seconds (0 = unbounded / ∞)
//
// T0  Ephemeral      1 s          memory only      NoAnchor        Ed25519
// T1  Session       60 s          memory + spill   EndOfLife       Ed25519
// T2  Operational    1 h          BadgerDB         Periodic (1 h)  Ed25519
// T3  Daily          1 d          BadgerDB         Periodic        Ed25519
// T4  Weekly         7 d          BadgerDB         Periodic        Ed25519
// T5  Monthly       30 d          BadgerDB         Periodic (1 h)  Ed25519
// T6  Compliance     1 y          BadgerDB         Periodic + perm Falcon-1024
// T7  Eternal        ∞  (0 s)     BadgerDB + offld Permanent (24h) Falcon-1024

// TTL field — all accepted forms
{ "ttl": "T5" }           // 2 592 000 s — Monthly preset
{ "ttl": "90d" }          // 7 776 000 s — ninety days
{ "ttl": "5m" }           // 300 s — five minutes
{ "ttl": "2h30m" }        // 9 000 s — compound duration
{ "ttl": "forever" }      // 0 — unbounded (equivalent to T7)
{ "ttl": 7776000 }        // 90 days as canonical seconds
RFC-EPH-TTL-001 · T0–T7 canonical mapping

Promotion is non-destructive: it adds a checkpoint and re-anchors at the target TTL. Demotion truncates retention; crypto-shred destroys per-record keys so personal data goes dark while the Merkle path stays verifiable.

See the full tier ladder →

§ 02.04

Anchoring — for timestamps, not settlement.

Batched Merkle roots are committed to a chosen public chain solely for tamper-proof timestamping. Ephernity issues no token; transfers no value on-chain; settles nothing. The anchor is a notary, not a settlement layer.

The default anchor is Bitcoin via OpenTimestamps (max neutrality, low cost, high latency); operators may select a low-cost L2 or an EU-public option (e.g. EBSI) per tier (RFC-EPH-007).

§ 02.05

HATP attestation.

HATP (Hardware Attestation Trust Protocol) is a three-level key delegation: root → tenant → host. The root key is rotated on a slow schedule and protected in an HSM. The tenant key is issued per customer/jurisdiction. The host key is bound to a measured-boot attestation of the KVM guest that performs signing.

A verifier with the root public key alone can validate any entry's signature chain offline (RFC-EPH-005).

§ 02.06

Verification.

borz listing
fn verify_range(entries: [Entry], root_pk: HATPRoot) -> Result[(), Error] {
    let mut prev = ZERO_HASH;
    for e in entries {
        // 1. hash chain
        if e.header.prev_hash != prev { return Err(ChainBroken); }
        let h = blake3_header(e.header);

        // 2. content address
        if blake3(e.payload) != e.header.payload_cid { return Err(CidMismatch); }

        // 3. signature
        let pk = hatp_verify_chain(e.header.signer_id, root_pk)?;
        verify_sig(e.header.sig_scheme, pk, h, e.signature)?;

        prev = h;
    }
    Ok(())
}
Pseudo-code · range verification

The verifier needs only the entries (or a checkpoint plus an inclusion proof) and the root public key. No network access. No trusted middlebox. No tokens.

§ 02.07

Contract dialect — the compute pillar.

Sections 02.01–02.06 specify the storage pillar — what an entry is, how a ledger holds them, and how a verifier checks them. The compute pillar specifies what runs on top: a deterministic contract dialect whose every step reads from and writes to the same kind of ledger.

A contract is an actor: a piece of code with persistent state and message handlers. The dialect interface restricts the runtime so that replay reproduces every result exactly. Three constraints define it:

  1. No ambient inputs. A handler reads only the prior state and the inbound message; the wall-clock, the network, and the host environment are not visible.
  2. Seeded randomness. Any randomness is derived deterministically from the inbound message and a per-contract seed committed at instantiation.
  3. Total commitment. Inputs, prior-state hash, code revision, and outputs are all committed to a ledger entry. Replay re-executes against the committed inputs and compares the output hash.
borz listing
pub interface Contract {
    // The whole environment of a step. No wall-clock, no network,
    // no unsanctioned randomness. Same input → same output.

    fn step(
        prior_state: State,        // commit on the state-ledger
        message:     Message,      // commit on the input-ledger
        env:         DeterministicEnv,
    ) -> Result[StepOutput, Error]
}

pub type StepOutput = {
    next_state: State,
    response:   Response,
    receipts:   list[LedgerReceipt],   // every emit is a ledger entry
}

pub type LedgerReceipt = {
    cid:      bytes32,   // blake3(payload)
    seq:      uint64,
    ts_ms:    uint64,
    ttl:      TTL,       // resolved canonical seconds; 0 = unbounded
}
RFC-EPH-CMP-001 · contract interface — sketch

Each receipt carries the resolved TTL of the ledger entry it names. A contract may inherit the step's ambient TTL, override it per-emit, or promote an existing entry to a longer horizon — all three transitions are first-class and produce a new receipt. The TTL in a receipt is the committed value; the receipt itself is the proof that the runtime honoured it.

Per-call accounting (the unit of work, its inputs, its outputs) is part of the protocol; the price attached to a unit is a deployment concern and lives outside the spec. The reference contract surface is written in Borz; other dialects can conform if they preserve the interface and the ledger commitments. The relevant RFCs are RFC-EPH-CMP-000 (overview), CMP-001 (dialect), CMP-002 (ledger-backed state), and CMP-003 (per-call accounting).

Conformance markers — dialect surface

CMP-001 designates four surface markers a conforming dialect must expose to the contract author, regardless of the underlying language:

canonical encoding
Declared types carry a byte-identical encode/decode contract across conforming runtimes; the canonical form is what enters the hash chain.
determinism rejection
A marker that a function is intended to commit; the conforming compiler rejects calls to the banned-primitive categories (wall-clock, ambient I/O, unseeded randomness, …) at compile time.
meter budget
A per-call cap on CPU-µs, memory, and state-write bytes, enforced by the runtime envelope. Exceeding the budget yields a typed error, committed like any other step result.
ttl resolution
Each emit carries a resolved TTL committed in the receipt. The dialect must surface a per-emit TTL override and propagate the resolved seconds to the ledger entry and its receipt.

The reference dialect, Borz v0.9, exposes these as @canonical, @deterministic, @meter_budget, and @ttl. Other languages can conform by exposing equivalent author-visible markers and producing the same wire-level commitments.

§ 02.08

Non-goals.

  • Not a blockchain. No global consensus, no native currency, no on-chain "smart contract" VM. The anchor is a clock, not a settlement layer.
  • Not a storage market. No node-reward economics, no instrument at the wire. Operators run the substrate; users pay operators for hosting, or self-host.
  • Not a custodial trust anchor. The protocol is verifiable offline against the root public key; trust in the operator is required for availability, not for integrity.
  • Not a retention loophole. Per-entry crypto-shred is structural; deletion of personal data is a first-class operation at every tier.
  • Not an execution monopoly. The contract dialect is an interface; any runtime that preserves the interface and the ledger commitments can host conforming contracts.