Canonicalization
The exact procedure behind commitmentHash and attestationReason (elpis-canon/1), so any implementation — yours, an auditor's — produces the same bytes.
Why this page exists
If you cannot recompute our hashes, you cannot check our decisions — only trust them.
Two hashes matter. commitmentHash(condition) fixes what “done” means before the work. attestationReason(verdict) is the decision and its rationale, recorded as the ERC-8183 reason. Both are 0x-prefixed lowercase hex SHA-256 digests over UTF-8. The version is elpis-canon/1; a change to any rule below is a new version.
commitmentHash(condition)
Input: an ordered array of acceptance checks.
- For each check, drop the
labelfield entirely — it is presentation only and never affects the commitment. - Emit the remaining fields with keys sorted ascending. Array-valued fields keep their order; an omitted optional field is simply absent (never
null). JSON.stringifythe array with no insignificant whitespace."0x" + hex(SHA-256(utf8(json))).
// condition
[ { "kind": "deliverable_hash", "hash": "0xDEED", "label": "the report" } ]
// canonical (label dropped, keys sorted)
[{"hash":"0xDEED","kind":"deliverable_hash"}]
// commitmentHash
0x0ce2db10fdbfe486bbea23d6e8236bb75b3edbf8c3935227564cf2389bfc2a52attestationReason(verdict)
Input: { decision, rationale }, where decision is complete, reject or hold, and rationale is an ordered array of strings.
JSON.stringify({ decision, rationale })— exactly those two keys, in that order, with the rationale in the order produced."0x" + hex(SHA-256(utf8(json))).- The rationale strings are byte-significant: change a word and the reason changes.
| Settlement decision | Verdict decision |
|---|---|
release | complete |
refund | reject |
hold | hold |
What a replay must reproduce
POST /api/v1/attestations/{id}/replay re-runs the pure decision over the stored condition and proof, recomputes both hashes, and reports matches: true only when the recomputed attestation equals the recorded one. The Python SDK is a second implementation of this page, and its tests reproduce the reference hashes from the TypeScript one byte for byte.