flowchart LR
E1["Event 1<br>─────<br>payload_hash<br>payload_ref<br>prev: 0000<br>sig: pk₁"] --> E2["Event 2<br>─────<br>payload_hash<br>payload_ref<br>prev: H(E1)<br>sig: pk₂"]
E2 --> E3["Event 3<br>─────<br>payload_hash<br>payload_ref<br>prev: H(E2)<br>sig: pk₁"]
E3 --> E4["Event N<br>─────<br>payload_hash<br>payload_ref<br>prev: H(E3)<br>sig: pk₃"]
6 How EventChain Works
EventChain combines three primitives: a hash-chained JSONL file, identity-bound signatures (WebAuthn passkeys for humans, TPM or PUF credentials for devices) and real-time distribution from a central Hub. Helios uses those primitives to preserve the evidence trail produced by its business workflows. Verification requires no trust in the Hub, the host, or network security: the file proves itself.
6.1 The Append-Only File
The append-only file (AOF) is a JSON-Lines document: one event per line. Each entry contains a payload_hash (SHA-256 of the payload content), a payload_ref (index key to the payload in Hub storage), the SHA-256 hash of the previous entry, the signer’s public key, and an ECDSA-P256 signature. Payload content is stored encrypted in the Hub and is retrieved via role-based access control (Section 6.7). The hash chain locks every event to the full history that preceded it: altering any past entry breaks every subsequent hash.
6.2 Payload Commitment and Visibility
Each entry commits to its payload through a one-way hash: a cryptographic fingerprint that locks the content without revealing it. The hash is a public function: anyone who later obtains the payload can recompute the hash and confirm it matches the commitment in the signed entry.
| Operation | Key needed | Who can do it | Purpose |
|---|---|---|---|
SHA-256(payload) |
None | Anyone with the payload | Produce deterministic fingerprint |
ecdsa_p256_sign(entry, private_key) |
Private key (in authenticator/TPM) | Signer’s device only | Create proof of authorship |
ecdsa_p256_verify(entry, sig, public_key) |
Public key only | Anyone — OpenSSL, Web Crypto API, libsodium | Confirm signature authentic |
Every entry carries the same structure: payload_hash, payload_ref, prev_hash, public_key, and signature.
The AOF carries no human-readable signer identifiers, only the public key. Signer context (name, role, organisation) resides in the payload, protected by RBAC. The organisational directory maps public keys to people internally. This separation keeps the proof layer free of pseudonymous identifiers under GDPR while preserving full attribution in the access-controlled business layer.
| Field | Example | Purpose |
|---|---|---|
entry_id |
evt-042 |
Unique entry identifier |
payload_hash |
a1b2c3d4... |
SHA-256 of payload content |
payload_ref |
ref-042 |
Index key to Hub storage |
prev_hash |
f7e6d5c4... |
SHA-256 of previous entry |
public_key |
MFkw... |
Signer’s public key |
signature |
MEUCIQDx... |
ECDSA-P256 signature (WebAuthn/FIDO2) |
payload_ref under RBAC
| Field | Restricted (Inspection) | Public (DPP) | Headless (Sensor) |
|---|---|---|---|
| Signer / Device | Alice Chen, QA Inspector | System, DPP Generator | sensor-PT-007 (TPM) |
| Type | Inspection result | Product passport | Pressure measurement |
| Asset | valve-CLF-1500-042 | valve-CLF-1500-042 | valve-CLF-1500-042 |
| Key data | result: pass, 345 bar | material: A105 Carbon Steel | reading: 342.7 bar |
| RBAC policy | Restricted (QA, auditors) | Public (anyone) | Restricted (ops, regulators) |
6.3 Identity-Bound Signatures
Every entry carries a signature from a registered credential tied to a specific identity. Verification logic is identical for human and device signers. This implements the attribution model from Section 2.3.
6.3.1 Human Signers
For human actors, EventChain uses WebAuthn/FIDO2 credentials to sign specific entries. The private key remains controlled by the authenticator, and local user verification such as biometric or PIN confirmation can be required by policy. The signature binds the registered credential to the entry and chain position; organisational systems bind that credential to a person and role.
6.3.2 Signer Lifecycle
Registration binds a credential to a verified identity and device-controlled authenticator. Authority to attest comes from organisational role; the protocol records who signed. A quality inspector signs because the organisation assigns that responsibility. EventChain captures the signature without judging whether the signer was authorised.
When an employee departs, their historical signatures remain valid. A signature attests a fact at a point in time. It carries no ongoing authority. No revocation is required because the signer held no protocol-level privilege, only an organisational role that the directory already manages.
Key loss does not compromise the chain. The organisation deactivates the old credential, issues a new credential, and maps identity continuity forward. Entries signed with the lost key may require re-attestation depending on business policy, but the chain’s cryptographic integrity is unaffected.1
6.3.3 Headless Signers
For sensors and automated systems, the key lives in a TPM, PUF, or secure element. The device signs autonomously when it produces a measurement. No user verification step. The resulting entry is cryptographically identical to a human-signed entry: same hash chain, same signature format, same offline verification. The signature proves which device produced the reading and where it sits in the sequence; Helios operating controls handle calibration, physical binding, attachment checks, and exception handling.2
6.4 Distribution
The Hub receives events from Helios workflows, appends signed entries, and serves the file to authorised recipients via API, webhook, or shared storage. Any copy of the file is independently verifiable: the hash chain and signatures are self-proving. The Hub is the authoritative source and operational centre; recipients read from it whenever they need the current state.
The cost asymmetry is architectural. Generating a signed entry requires the signer’s private key, held in a hardware authenticator, an operation that only the signer’s device can perform. Verifying that entry requires only the public key and a standard ECDSA-P256 check available in any crypto library. One Hub generates proof; any number of recipients verify independently at negligible cost. This realises the asymmetric verification model from Section 4.1.
6.5 Scale and Ordering
The Hub processes events on a single thread; sequential processing guarantees ordering by architecture.
A single-threaded event processor handles millions of operations per second. The practical bottleneck is network I/O, not computation.
6.6 Cryptographically Bound Contracts
Custody transfers use multi-signature entries. Both the transferring and receiving party sign the same event, fixing the handoff moment cryptographically. The payload contains human-readable fields (asset identifier, parties, conditions, timestamp) so that the contract is legible to auditors and lawyers without tooling beyond a text editor. CBC payloads are typically set to an RBAC policy accessible to both parties, their auditors, and any relevant regulator. A broken signature or missing counter-sign makes a disputed handoff immediately apparent.
6.7 Role-Based Access Control
The Hub enforces which recipients can retrieve which payloads. Each payload_ref in the AOF carries an RBAC policy: some are public (anyone can retrieve), others are restricted to specific roles. Access policy is operational: it controls visibility; integrity is mathematical. A regulator may access the full set of payloads; a downstream customer may access only entries relevant to their contract. The AOF itself (the proof layer) is identical regardless of the viewer’s access level.
Hosting is flexible: cloud-managed, on-premise, regulator escrow, or shared storage. The access layer adapts to organisational security posture without changing the verification model. For public payloads, the Hub can export content as a flat file (CSV or JSON) with payload_ref as the join key, enabling fully offline verification without API access.
6.8 OpenTimestamps Daily Rollups
Each day, the Hub rolls the current chain head into an OpenTimestamps commitment: an independent, public temporal proof that the chain existed in a given state at a given time.3
The AOF’s integrity holds without it (hash continuity and signatures are self-proving), but daily anchoring is a recommended part of the EventChain deployment. Public time anchoring adds value when external parties (auditors, regulators, counterparties in dispute) need proof of when a state existed, beyond what existed. The daily rollup batches all events into a single anchor (one Bitcoin transaction per day regardless of event volume), keeping the anchoring cost fixed and minimal.
6.9 Verification
The open-source EventChain Verifier runs against any copy of the AOF. Verification proceeds in independent steps; each adds assurance without requiring the previous to complete. Chain verification and signature verification are separate checks — chain integrity can be confirmed without verifying any signatures, and attribution can be checked on-demand for specific entries when accountability matters.
flowchart TD
AOF[AOF File] --> S1["STEP 1: Chain Verification<br>(offline — no RBAC, no private keys)"]
S1 --> H1{"prev_hash ==<br>SHA-256(previous entry)?"}
H1 -->|No| FAIL1["CHAIN BROKEN<br>tampered entry identified"]
H1 -->|Yes| SIG{"ecdsa_p256_verify<br>(public_key, entry, signature)?"}
SIG -->|No| FAIL2["SIGNATURE INVALID<br>forged or corrupted entry"]
SIG -->|Yes| PASS1["Chain intact<br>Public key authenticated"]
PASS1 --> S2["STEP 2: Payload Verification<br>(requires RBAC to retrieve payload)"]
S2 --> RBAC{"RBAC access<br>to payload_ref?"}
RBAC -->|No access| STOP["Chain verified<br>payload not accessible<br>(integrity proven, content unknown)"]
RBAC -->|Granted| RETRIEVE["Retrieve payload<br>from Hub via payload_ref"]
RETRIEVE --> H2{"SHA-256(retrieved payload)<br>== payload_hash?"}
H2 -->|No| FAIL3["PAYLOAD TAMPERED<br>Hub served different content"]
H2 -->|Yes| PASS2["Payload authentic<br>matches signer commitment"]
PASS2 --> S3["STEP 3: Temporal Anchor (optional)"]
S3 --> OTS{"OTS receipt matches<br>chain state at timestamp?"}
OTS -->|No| FAIL4["ANCHOR MISMATCH<br>chain state disputed"]
OTS -->|Yes| PASS3["Full audit complete<br>integrity + authenticity + time"]
Step 1 requires only the AOF: no network, no RBAC, no private keys. Public keys are bundled in the AOF alongside the signed entries.4 Step 2 requires retrieving the actual payload from the Hub, which means RBAC access to the relevant payload_ref. Step 3 requires OTS receipts.
VerifyChain(AOF)
// Step 1a: Hash chain integrity — offline, no keys needed
FOR i ← length(AOF) − 1 DO
IF i > 0 THEN
AOF[i].prev_hash = SHA256(AOF[i − 1])
END IF
END FOR
END
VerifyAttribution(entry)
// Step 1b: Signature — ECDSA-P256 (WebAuthn/FIDO2)
// Available in: OpenSSL, Web Crypto API, libsodium, BoringSSL
ECDSA_P256_Verify(
publicKey ← entry.public_key,
message ← entry.data(),
signature ← entry.signature
)
END
VerifyPayload(entry, payload)
// Step 2: Payload authenticity — no keys needed, just SHA-256
SHA256(payload) = entry.payload_hash
END
FullAudit(AOF, payloads, OTS_receipts)
// Step 3: Everything together
// 3a. Chain integrity
VerifyChain(AOF)
// 3b. Per-entry attribution + payload
FOR EACH entry IN AOF DO
VerifyAttribution(entry)
VerifyPayload(entry, payloads[entry.payload_ref])
END FOR
// 3c. Timestamp proofs
FOR EACH receipt IN OTS_receipts DO
VerifyOTS(AOF, receipt)
END FOR
ENDA file that passes all steps is cryptographically consistent with its hash chain, signatures, payload commitments, and any available anchors. A file that fails identifies the exact point and type of divergence. No API call, no service dependency, no platform trust required for chain integrity. Trust in signer enrolment, key-to-identity binding, and operating controls remains outside the cryptographic guarantee.
6.9.1 What Recipients Need
Recipient requirements scale with the verification level:
- Chain verification: AOF file only; offline, no network.
- Attribution: AOF file only; public keys are embedded.
- Payload verification: AOF file plus Hub API access for specific
payload_refentries under RBAC. For public payloads, a CSV/JSON export withpayload_refas the join key works without API access. - Full audit: AOF file plus full Hub API access plus OTS receipts.
The runtime is agnostic: the open-source verifier runs on any platform, and the verification logic is simple enough to reimplement from the specification. In practice, recipients rarely verify the full chain. The common operation is verifying a specific event: confirming that a particular inspection, handoff, or measurement exists in the chain with a valid hash and a valid signature from a known public key. Full-chain verification serves audit and dispute scenarios.
When verification fails, the protocol identifies the failure type but prescribes no response. Consequences are contractual: the business relationship, not the protocol, determines what happens next. This boundary is deliberate; a proof format should not embed dispute-resolution logic. The failure-mode taxonomy (Table 4.2) maps what the proof layer detects against what requires complementary organisational controls.
Device changes follow the same mapping procedure: old credential is deactivated in the identity provider, new credential is registered, and the identity thread remains continuous in the AOF.↩︎
A commissioning CBC (Section 6.6) binds sensor to asset; periodic cryptographic challenges can provide continued-attachment evidence.↩︎
OpenTimestamps anchors commitments to the Bitcoin blockchain, providing a timestamping authority that no single party controls.↩︎
The verifier confirms that each signature matches a public key declared within the artifact. Trust in the key-to-identity binding rests on the issuing organisation’s identity-proofing process — the same trust model as any certificate-based system.↩︎