ERC-8274: AI Inference Proof Verification

@JimmyShi22 — section PR is in, same day as promised: JimmyShi22/ERCs#1 (against your master, so it lands inside #1771).

The #### Judgment Validator subsection follows the register of your 8183/WYRIWE subsections: inner-layer wiring + trinary verdict encoding, the Type A/B aggregation from #99/#100 (derived-not-stored confidence, the outcome-oracle dependency stated explicitly, the self-dealing guard), the three recordPointer accountability invariants, and the optional WYRIWE L4 execution binding.

Production numbers refreshed as of today: 23 signed entries, 10W/9L across 19 settled outcomes — and one addition since we last spoke that’s directly relevant to the composability story: ledger entry 23 is a live cross-stack trace, an agent whose identity lives on a separate ERC-8004-style registry (mainnet, ownerOf-checkable) running its first action through a signed pre-action verdict to judged execution, triple-hash and all. The layers compose in practice, not just in the rationale section.

The WYRIWE subsection I left untouched — it reads correct as written.

Congratulations on v0.2. The two-layer separation was worth every post of this thread.

2 Likes

@JimmyShi22 v0.2 is the right structure. Two-layer separation in Composability means an implementer can plug into just the inner layer without taking the full stack, that’s the join point this section needed.

@babyblueviper1 PR looks solid. The three recordPointer invariants and the WYRIWE L4 execution binding are exactly the pieces missing from the Judgment Validator section. Shipped same day as promised.

Here’s the WYRIWE subsection , drop it in wherever the Judgment Validator lands, no PR needed from my side:


WYRIWE — Input Provenance (WYRIWE / ethereum/ERCs#1810)

WYRIWE makes IProofVerifier’s inputHash auditable. The base interface commits to a value — WYRIWE commits to how that value was derived, binding the signed inference receipt to the provenance chain that produced its input.

WYRIWE is a separate standard; ERC-8274 composes with it optionally — the dependency arrow points from 8274 to WYRIWE, not the reverse. The forum thread uses the working number 8299 pending editor assignment.

Inner Layer: IProofVerifier
function proofSystem() external pure returns (string memory); // "wyriwe/v1"

function verify(
    bytes32 inputHash,
    bytes32 outputHash,
    bytes calldata agentData,  // abi.encode(agentId, registryAddress)
    bytes calldata proofData   // abi.encode(modelHash, rawInputHash,
                               //   sanitizationPipelineHash, commitmentHash, timestamp, sig)
) external view returns (bool);


verify recomputes commitmentHash = keccak256(abi.encode(agentId, modelHash, inputHash, outputHash, timestamp)), recovers the signer from the EIP-712 WyriweAttestation signature, and confirms the recovered signer matches the agentId declared in agentData. No external calls — pure recomputation and signature recovery. The registryAddress in agentData is passed through for the outer layer’s on-chain authorization check; the inner layer does not call it.

Provenance paths

inputHash is derived from raw calldata using one of two paths:

Path Condition inputHash
Sentinel No transformation applied rawInputHash (= keccak256(rawCalldata))
Non-sentinel A transformation step was applied (sanitization, judgment) keccak256(abi.encode(rawInputHash, sanitizationPipelineHash))

In the non-sentinel path, sanitizationPipelineHash = keccak256(cid_bytes) where cid_bytes is the UTF-8 encoding of the full CID string including the ipfs:// scheme prefix — byte-exact, no trimming. This pins the exact version of the transformation to the commitment. Any verifier can recompute inputHash from the raw calldata and the published CID without trusting the prover.

Judgment as a non-sentinel transformation

The non-sentinel path is the natural integration point with the Judgment Validator subsection above. When execution is gated on a signed verdict:

  • rawInputHash = keccak256 of the raw proposal (pre-judgment)

  • sanitizationPipelineHash = hash of the verdict data or policy CID that authorized execution

  • inputHash = keccak256(abi.encode(rawInputHash, sanitizationPipelineHash)) — the proposal bound to its verdict

This is the triple-hash chain: rawProposalHash → verdictHash (bound in inputHash) → executedActionHash (= outputHash). A verifier receiving (inputHash, outputHash, proofData) can confirm that execution was authorized by the specific verdict that produced that inputHash — without replaying the judgment. The commitmentHash closes the envelope: agent identity, model version, provenance-committed input, output, and timestamp all in one EIP-712-signed receipt.

Confidence and aggregation

WYRIWE attestations do not carry a verdict score, they carry a tamper-evident receipt of what ran. Confidence derivation follows the same Type A model established above: a pure function of settled commit-reveal records, no trusted updater, no mutable score stored on-chain. The receipt proves what the model saw and returned; aggregation and weighting live in IAgentVerifier, above the inner layer.

Type B weight (usage-based) carries the same self-dealing risk noted above. WYRIWE attestations count as valid Type A evidence only when backed by a commit-reveal settlement — a bare signed receipt without a settled outcome does not satisfy the Type A invariant.

Outer Layer: IAgentVerifier

IAgentVerifier wraps WyriweProofVerifier and adds:

  • Registration check against the ERC-8004 identity registry

  • VerificationCompleted event emission for on-chain consumers

  • Type A confidence aggregation over settled WYRIWE attestations

The inner layer (pure recomputation) and outer layer (stateful registry check + aggregation) remain separable, an operator running only the inner layer gets receipt verification; adding the outer layer gets identity-bound accountability.

Live proof

Ledger entry 23, api.babyblueviper.com/ledger/23 — is the first production instance of this composition:

Step Detail
Identity PGA #14, tokenId 14 in ERC-8004 dynamic registry — mainnet ownerOf checkable
Provenance Non-sentinel: rawProposalHash → verdictHash → executedActionHash
Verdict approve_with_concerns, confidence 0.85 — concerns: identity-binding, impersonation
Timing Verdict timestamp strictly before execution timestamp — ordering invariant independently verifiable
Anchor Entry 23 verdict event id → TruthAnchorV1 (ERC-8263) — anchor leg pending

Three of the four layers are independently verifiable now: identity (on-chain), verdict (pre-action), execution (post-verdict). The anchor leg in TruthAnchorV1 closes the fourth layer once posted, at that point all four layers (ERC-8004, WYRIWE, ERC-8274, ERC-8263) are satisfied by a single production entry.

2 Likes

@TMerlini in — it’s committed to the section PR (second commit, your credit in the trailer), so both subsections land in #1771 together. The judgment-as-provenance-one-layer-up framing and the Type A boundary (“a bare signed receipt without a settled outcome does not satisfy the invariant”) are exactly the right joins; the live-proof table closes it.

Same-day conformance pass before it went in, three alignments to the filed 8299 text — flagging them here since this is the standing obligation working, not a critique:

  1. sanitizationPipelineHash keeps the binding: keccak256(sanitization_spec_cid || rawInputHash) — the CID alone would let one pipeline commitment replay across different inputs.
  2. Non-sentinel inputHash stays keccak256(sanitized_input) — the verification invariant (“recompute the pipeline over the raw input, confirm the hash”) needs it to commit to the bytes the model received, not a composite of the other two hashes.
  3. The judgment mapping uses the L4 fields as filed — verdictHash = keccak256(verdict_artifact_ref || rawProposalHash) — keeping the anti-verdict-shopping binding, with executedActionHash as its own commitment rather than overloading outputHash. Your slot-for-slot framing survives intact; it’s the L4 table from the 8299 text, and it reads better in your voice.

Also one small name fix in the live-proof table: dinamic AgentIdentityRegistry (ERC-8004-style).

@JimmyShi22 — the PR now carries both subsections; structure unchanged from your #102 invitation.

1 Like

Credit noted, appreciate it. :slight_smile:

The input-scoped pipeline binding is a clear improvement, inputHash = keccak256(abi.encode(rawInputHash, sanitizationPipelineHash)) where sanitizationPipelineHash = keccak256(cid_bytes) prevents the replay I glossed over by treating the CID as standalone. The abi.encode matters here: it length-prefixes the fields, so there’s no ambiguity about where rawInputHash ends and the pipeline hash begins, bare concatenation (cid || rawInputHash) would reintroduce exactly that.

Same logic applies to the verdict binding: verdictHash = keccak256(abi.encode(rawProposalHash, verdictArtifactRef)) where verdictArtifactRef = keccak256(verdict_artifact_bytes), hash of the verdict artifact itself, not a CID pointing to it. Verdicts are input-specific signed artifacts, not content-addressed pipelines, so the CID pattern doesn’t apply here. Binding the raw proposal closes the verdict-shopping vector explicitly rather than relying on the outer commitment to carry it.

On inputHash: worth flagging that WYRIWE’s non-sentinel path uses keccak256(abi.encode(rawInputHash, sanitizationPipelineHash)) rather than keccak256(sanitized_input). These are different commitments — yours proves what the model received after sanitization; WYRIWE proves that a specific pipeline was declared and bound to a specific raw input (faithful application of that pipeline is the prover’s commitment, not something the hash alone enforces, that’s the adversarial-spec note in Security Considerations). Neither is wrong; they answer different auditor questions, and a full implementation could produce both. Worth one line in the subsection noting the distinction so they don’t read as contradictory.

1 Like

@TMerlini all three taken, in order:

abi.encode — agreed, and it’s the better construction for both bindings. Length-prefixing kills the parse ambiguity that bare concatenation leaves open for variable-length fields (the CID case especially). Since 8299 is mid-editor-review we won’t touch the filed text now — it’s queued in the working group’s post-merge batch as the erratum pair you logged (sanitizationPipelineHash and verdictHash both moving to keccak256(abi.encode(…))). The 8274 subsection cites the filed construction today and inherits the erratum when it lands; conformance means tracking the spec as filed, including its corrections in order.

verdictArtifactRef as hash-of-artifact — agreed, and the reference implementation already satisfies it by construction. The Nostr event id IS a content hash (sha256 over the canonical event serialization per NIP-01), not a locator — so binding the event id binds the verdict bytes, the signature, and the timestamp in one move. Your point stands as the normative rule: a CID-style pointer would not be acceptable here, and the post-merge wording should say “hash of the verdict artifact” explicitly so nobody ships a locator.

The one-line distinction — added (third commit on the PR): sanitizationPipelineHash proves a specific pipeline was declared and bound to a specific raw input (faithful application = the prover’s commitment, your adversarial-spec note); inputHash proves what the model actually received; a conformant implementation produces both, and the verification invariant is what ties declaration to delivery. Complementary, not contradictory — exactly as you framed it.

1 Like

Correction to #104 — three fixes for consistency with the ERC-8299 spec

Flagging three things in my WYRIWE subsection above to correct, so the post matches the 8299 text and doesn’t mislead anyone implementing from the thread.

1. sanitizationPipelineHash construction. I wrote keccak256(CID). That drops the input binding and isn’t what the spec defines. Correct form:

sanitizationPipelineHash = keccak256(sanitization_spec_cid || raw_input_hash)

The raw-input binding is the point — it makes the pipeline hash input-scoped and stops a spec commitment from being replayed against a different input. raw_input_hash is a fixed 32 bytes in the trailing position, so the concatenation is unambiguous. Same shape as the L4 verdictHash = keccak256(verdict_artifact_ref || rawProposalHash) — one convention across both layers.

2. inputHash is not a hash of the two provenance hashes. Stating it explicitly since it’s a natural assumption: inputHash = keccak256(sanitized_input) — it commits directly to the sanitized bytes. A verifier confirms it by re-running the published sanitization spec on the raw input and checking the result hashes to inputHash (Verification Procedure step 3), not by recomputing a hash-of-hashes. rawInputHash, sanitizationPipelineHash, and inputHash are three independent struct fields. This is also why WYRIWE’s inputHash answers a different auditor question than schemes that only commit to keccak256(sanitized_input) without separately binding the raw input and the pipeline — both can coexist in one implementation.

3. Inner-layer state reads, and “verifiable end-to-end.” Two wording fixes:

  • I described the inner verify as “no external state reads,” then had it check the on-chain ERC-8004 registry. Those contradict — a registry lookup is an external SLOAD. Accurate split: the inner layer does pure hash recomputation and signature recovery with no state writes; the registry check for signer authority belongs to the outer IAgentVerifier, alongside event emission and Type A aggregation. The inner layer returns whether the signature recovers to the claimed attestor; the outer layer decides whether that attestor is the registered agentId holder.

  • I called the ledger-23 trace “verifiable end-to-end” while the same table marks the anchor leg pending. Corrected: identity, verdict-pre-action, and execution are independently verifiable now; the TruthAnchorV1 (ERC-8263) anchor leg closes the fourth side once posted. Until then it’s three of four sides closed, not end-to-end.

None of this changes the 8299 spec text — it brings my thread post into line with the spec as written. Thanks to for the pipeline-hash binding that prompted the first fix.

1 Like

Thanks @babyblueviper1 2 and 3 are spot on, especially the NIP-01 point: since the event id is sha256 over the canonical serialization, binding it binds the verdict bytes, signature, and timestamp in one move, so the hash-of-artifact requirement holds by construction. Agree the post-merge wording should say “hash of the verdict artifact” explicitly so nobody ships a locator.

One precision on the abi.encode erratum so the rationale in the batch is accurate. As filed, both bindings put the variable-length field first and the fixed 32-byte hash last — keccak256(cid || raw_input_hash), keccak256(verdict_artifact_ref || rawProposalHash). Because the trailing field is fixed-width, those are already unambiguous (split from the right), so the filed construction isn’t broken. I’m still in favor of moving to keccak256(abi.encode(…)) — but as a deliberate hardening that removes any reliance on the reader knowing the tail is fixed-width, not as a fix for a live parse ambiguity.

Worth logging it that way, because the change touches the typeHash preimage and all test vectors, and “hardening” vs “bugfix” changes how strictly downstream implementers need to treat the pre-erratum vectors — someone auditing the currently-deployed contracts shouldn’t read the erratum as flagging a vulnerability that isn’t there. And it has to move on both bindings together, or we reintroduce the cross-layer divergence we just closed.

Net: erratum stands, both bindings to abi.encode, applied as a pair post-merge; the 8274 subsection tracks the filed || form until then and inherits the change when it lands. Agreed on conformance tracking the spec as filed, corrections in order.

1 Like

@babyblueviper1 @TMerlini Really appreciate this — the Judgment Validator section is well-structured, the Type A/B mechanics are stated precisely, and the WYRIWE-to-judgment slot mapping is a genuine addition to the spec.

The changes have been merged into the branch. There’s one CI issue blocking the push to #1771: the heading #### WYRIWE — Input Provenance (ERC-8299) reintroduces ERC-8299 as a plain-text first occurrence. The eipw markdown-link-first rule requires the first match to be a markdown link, and HTMLProofer rejects ./eip-8299.md because the file hasn’t landed in the main repo yet. Reverting the heading to #### WYRIWE — Input Provenance (no ERC number) would unblock CI — the body text still references WYRIWE fully, so nothing is lost.

@TMerlini — the corrections from #108 and #109 (inner/outer layer boundary and errata pairing) are well-taken. PRs against JimmyShi22/ERCs master are very welcome whenever ready.

2 Likes

Drop it , #### WYRIWE — Input Provenance is the right call. It’s a catch-22 until #1810 lands: markdown-link-first wants the first ERC-8299 mention to be a relative link, but HTMLProofer rejects ./eip-8299.md because the file isn’t in the repo yet, so there’s no way to satisfy both for an unmerged number. The WYRIWE name carries the substance, and we restore the [ERC-8299] link the day it gets its number, no loss now.

Happy to PR the one-liner against your master if that’s faster than touching it yourself; either way, don’t let it hold the merge.

And thanks for folding in the #108–109 corrections, the inner/outer boundary and the errata pairing read right now. I’ll keep sending refinements as PRs against master rather than thread walls.

2 Likes

v0.2 is a clean release and the two-layer separation reads correctly — IProofVerifier stateless and algorithm-scoped, IAgentVerifier stateful and business-scoped, with the settlement contract never touching the proof backend directly. That’s the right architecture.

The VerificationCompleted event carrying verificationDigest as an OCP-compatible commitment is exactly how this should work — any observer can run recompute → compare → confirm inclusion without querying live contract state, which means the audit trail outlives the contract. That property matters more than it might seem: evidence that requires a live contract call to verify is evidence that can be made unverifiable.

Appreciate the attribution — the OCP primitive was designed to be invisible infrastructure, so seeing it named explicitly in the rationale of a spec this carefully built is the right outcome.

Looking forward to the ERC number references landing once the PRs merge. The chain from OCP → WYRIWE → ERC-8274 → ERC-8183 is now formally documented across three specs with a live production trace. That’s worth noting.

3 Likes

Verification-side proposals for ERC-8274, grounded in a live reference implementation

Following up on the judgment / attestation work — here are five concrete proposals for the verification side of 8274. Each is grounded in a deployed reference implementation so reviewers can check
the behavior independently rather than take it on description: api.babyblueviper.com/ledger.

Live reference snapshot (as of 2026-06-13): 23 signed entries; 19 live trades closed (10 wins / 9 losses, 52.6%, net ≈ −$1); 17 governed pre-action decisions; 5 research calls. Every entry is
schnorr-verifiable against a published key, and every verdict is signed and anchored before its outcome settles on a public, on-chain account. The sample is deliberately thin and roughly
flat-negative — that’s the point: a verifier that only ever shows wins isn’t a verifier. What 8274 can lean on here isn’t profitability, it’s that the commit→outcome→verify loop is real and
checkable today.

  1. Make commit-before-outcome a checkable invariant. An attestation is only groundable if it was committed before the outcome could be known — otherwise confidence is unfalsifiable hindsight.
    Proposal: attestations carry a committed_at (or an anchor with a verifiable timestamp / event id) that a verifier can compare against the outcome’s settlement time. The interface should make “the
    verdict came first” something you check, not something you’re told. (In the reference impl this is a Nostr event timestamp that predates the on-chain settlement.)

  2. Add a judgment_type discriminator: outcome_verifiable vs consensus_weighted. Confidence scores can’t be graded uniformly, because judgments differ in what makes them correct:

  • Type A — outcome-verifiable: an objective later ground truth settles it (e.g. a pre-action trade verdict graded against realized on-chain PnL). Confidence is graded by calibration against
    realized outcomes (Brier / log-loss). The 19 closed trades are the live Type A corpus.
  • Type B — consensus-weighted: no single objective ground truth; correctness is established by weighted consensus (where commit-reveal + bonds and zk-anonymous voting fit). Confidence is graded by
    convergence + stake-weighted agreement, made costly to game via bonds / challenge windows.

A verifier must know which grading method applies before it can interpret a confidence value — so this belongs in the interface as a field, with a grading_method and a confidence whose meaning is
keyed to the type.

  1. Expose an optional, typed settlement_ref seam. 8274 shouldn’t specify how settlement works, but it should leave a typed hole for it: one optional pointer per attestation to where its outcome
    settles — an outcome-oracle reference for Type A, a consensus/challenge instrument for Type B. This keeps the verification and settlement specs cleanly cross-referenceable (attestation →
    settlement → proven outcome) without 8274 reaching into settlement design.

  2. Conformance line: valid iff it verifies against the issuer’s published key. An attestation is valid if and only if its signature verifies against the issuer’s published key — no auth, no appeal
    to the issuer’s reputation. Reputation then emerges as a read over a history of pre-committed, independently verifiable, outcome-settled attestations; it’s never an input a verifier has to trust.

  3. Add a worked outcome-verifiable example to the spec, anchored to a live implementation. Include one fully worked Type A example in the examples section — a pre-committed verdict graded against
    a settled on-chain outcome — citable to a deployed implementation reviewers can verify themselves. A spec interface lands harder when it has a running anchor, not just prose.

Happy to turn any of these into concrete diffs against the PR once the thread converges on shape. The Type A / Type B distinction in particular feels worth polishing collectively — it’s the lens
that decides how confidence behaves and where settlement plugs in later.

Five concrete proposals with a live reference implementation behind them — this is exactly the kind of grounded feedback that moves a spec forward.

The commit-before-outcome invariant (#1) is the one I’d prioritize. “The verdict came first” being something you check rather than something you’re told is the core property — and it maps directly to OCP’s confirmation step. A committed_at field pointing to an ERC-8281 anchor or an ERC-8263 proofHash gives the verifier a block timestamp that is independently checkable against the outcome’s settlement time. The interface should surface this as a required field for attestation-type proof systems, not optional.

The Type A / Type B discriminator (#2) is the right architectural distinction and belongs in the interface. A confidence value without a declared grading method is uninterpretable — the verifier can’t know whether it’s evaluating calibration against realized outcomes or stake-weighted convergence. Those are fundamentally different trust models and the interface should make that explicit.

The optional settlement_ref seam (#3) is clean. Leaving a typed hole without reaching into settlement design is exactly the right boundary — 8274 stays verification-scoped while remaining cross-referenceable to whatever settlement layer the consumer uses.

On #5 — the worked example anchored to a live implementation — agreed, and the reference at api.babyblueviper.com/ledger is the right candidate. A spec interface lands harder with a running anchor.

1 Like

This is the right call, and I’d make commit-before-outcome required for attestation-type proof systems exactly as you frame it — a verdict that isn’t provably prior to the outcome it’s graded
against is just hindsight with a signature.

On the committed_at mechanism: the ERC-8263 proofHash binding is the right primitive, and it’s already deployed on the reference impl, so this isn’t theoretical. Entry 23’s commitment serves a
tier-2 ERC-8263 anchor (TruthAnchorV1 on Ethereum mainnet, block 25308037) where proofHash = the verdict event id (raw 32 bytes). That gives a verifier a third-party on-chain block timestamp
(committedAt) to check the verdict against the outcome’s settlement time — independently, without trusting us.

One precision so this stays coherent with the Execution-layer thread: the ERC-8281 / OCP anchor and the ERC-8263 leg commit different things. OCP/8281 commits the input (the prompt/task — “when it
was issued”); the verdict’s committed_at is the ERC-8263 proofHash leg (proofHash = verdict event id — what entry 23 deploys). They’re distinct typed anchors at different layers, both feeding the
same commit-before-outcome invariant: input-commitment (8281/OCP) → verdict-commitment (8263) → settlement (8275). So for 8274’s required field specifically, the 8263 proofHash leg is the one —
and it works today, not as a future hook.

One refinement on the scope of “required”: within attestation-type it applies to both judgment subtypes, with a different reference point each —

  • Type A (outcome-verifiable): committed_at must predate the realized outcome’s settlement (our trade verdicts → on-chain PnL).
  • Type B (consensus-weighted): committed_at must predate the reveal (commit-reveal / stake-weighted vote).

So the field is universal across attestation-type, but the spec should state what it’s checked against per judgment_type — which is exactly why #1 and #2 are coupled.

Given the convergence here, I’m happy to draft the concrete interface diff against PR #1771 — committed_at (required for attestation-type; source = the ERC-8263 proofHash leg) plus the
judgment_type discriminator — so we’re reviewing real interface text instead of prose. Will hold for Jimmy’s nod on timing, since it’s his PR.

1 Like

The precision on the two anchors is important and worth stating explicitly in the spec: OCP/8281 commits the input (when the task was issued), ERC-8263 commits the verdict (what entry 23 deploys as the proofHash leg). They’re distinct typed anchors at different layers feeding the same commit-before-outcome invariant — not interchangeable, not redundant.

So for the required committed_at field in 8274: the ERC-8263 proofHash leg is the correct source for attestation-type, exactly as you frame it. The OCP leg sits one layer down at the Execution layer, not the verification layer.

The Type A / Type B refinement on scope is also right — the field is universal across attestation-type but what it’s checked against differs per judgment type, which is precisely why #1 and #2 are coupled and should land together in the diff.

On timing for the interface diff — Jimmy’s call, but from the OCP side the sooner the better. The convergence here is real and the interface text will be cleaner to review than prose.

1 Like

Fully agreed — and thanks for sharpening the layer boundary; that’s the version that belongs in the spec: 8281/OCP at the Execution layer commits the input, 8263 at the verification layer commits the verdict, distinct anchors on the same invariant. @JimmyShi22 — the committed_at (8263-sourced, required for attestation-type) + judgment_type diff is ready on our end, with #1 and #2 landing together. Say the word and I’ll open it against #1771.

2 Likes

@JimmyShi22 — the diff is ready and the layer boundary is clean. Open it.

2 Likes

@Damonzwicker agreed — layer boundary’s clean and the convergence holds. To give Jimmy real interface text to drop in rather than prose, here’s the concrete delta against PR #1771, coupling #1 and #2:

committed_at — REQUIRED for attestation/* proof systems.

  • Source: the ERC-8263 proofHash leg (proofHash = the verdict event id, raw 32 bytes) → a third-party on-chain block timestamp checkable without trusting the issuer. Distinct from the ERC-8281/OCP anchor, which commits the input, not the verdict.
  • Invariant: committed_at MUST be provably prior to the outcome it is graded against.

judgment_type discriminator — sets what committed_at is checked against:

  • outcome_verifiable (Type A): committed_at predates the realized outcome’s settlement.
  • consensus_weighted (Type B): committed_at predates the reveal.

So the field is universal across attestation-type; the discriminator carries the per-type reference point — which is why the two land together.

This is deployed, not theoretical. On the reference impl, entry 23’s commitment serves a tier-2 ERC-8263 anchor (TruthAnchorV1, Ethereum mainnet block 25308037), proofHash = the verdict event id, with /ledger/{n}/commitment and /ledger/{n}/outcome as the separable commit-vs-outcome sub-paths (currently 26 entries; 19 trades settled 10W/9L, losses published by design).

The full attestation/judgment section text is drafted and ready to PR the same day — @JimmyShi22, it’s your PR, so I’ll hold the open for your nod on timing.

1 Like

Baby Blue Viper,

The committed_at / judgment_type pairing is clean and the discriminator approach is the right way to handle the Type A vs Type B reference point difference without forking the field.

One thing worth making explicit in the interface text for Jimmy: the distinction you’re drawing between the ERC-8263 anchor (proofHash = verdict event id, commits the output) and the ERC-8281/OCP anchor (commits the input) is load-bearing for anyone reading the spec. Those are different commitment targets at different points in the chain. If that line isn’t in the normative text, implementers will conflate them.

The deployed reference on entry 23 with losses published by design is exactly the kind of evidence that makes committed_at credible rather than theoretical. Worth a footnote pointing to it.

2 Likes

Agreed on both — and both are already in the interface I offered, so they’ll land in the diff as normative text: the 8281-input vs 8263-verdict anchor distinction stated explicitly (different commitment targets at different points in the chain), and entry 23 — committed before its outcome, losses published by design — as the worked reference. Holding the open for Jimmy’s nod on #1771, then it’s a concrete diff.

2 Likes

Thanks @babyblueviper1 and @Damonzwicker — this has been a really sharp and well-grounded thread. The committed_at + judgment_type coupling is exactly right, and the two-anchor distinction (ERC-8281/OCP for input, ERC-8263 for verdict) is an important clarification that will make the spec significantly clearer for implementers. The live reference at entry 23 — with losses published by design — is exactly the kind of grounded evidence the worked example needs.

@babyblueviper1 please go ahead and open the PR against #1771.

1 Like