Ecosystem CTF· Observatory· Voting· Governance· API· GitHub
Don't trust · verify

Verify Cardano's history yourself

The Observatory's record is append-only and hash-chained, and the complete event log is public. You don't have to trust us — recompute the entire chain yourself with ~12 lines of standard Python, and confirm it matches the published head. No account, no API key, no Observatory code required.

How it works

Every change to Project Memory is written as an event in an append-only log. Each event is SHA-256 hash-chained to the one before it, so altering any past event changes its hash — and every hash after it. The final hash, the chain head, is published. Recompute the chain from the public event log: if your head matches the published head, the entire recorded history is intact and unaltered. If a single byte was changed, your computation breaks exactly where.

The public artifacts (CC0, no key)

events.ndjson
The complete, ordered event log — every event with its prev_hash and hash.
index.json → meta.chain_head
The published chain head your computation must reproduce.
verify-memory-chain.py
The reference verifier (stdlib only). Or just use the snippet below.

Run it — the whole verifier

Standard library only (Python 3 — no packages to install). Save as verify.py and run python3 verify.py:

# Download the public event log + published head, recompute the chain. Trust nobody.
import json, hashlib, urllib.request
BASE = "https://observatory.asy.life/data/snapshots/projectmemory"
get = lambda p: urllib.request.urlopen(BASE + p, timeout=30).read().decode()
events = sorted((json.loads(l) for l in get("/events.ndjson").splitlines() if l.strip()),
                key=lambda e: e["seq"])
published = json.loads(get("/index.json"))["meta"]["chain_head"]
prev = "0" * 64
for e in events:
    canon = "\n".join([prev, e["ts"], e["type"], e["subject"] or "", e["actor"], e["payload"]])
    if e["prev_hash"] != prev or e["hash"] != hashlib.sha256(canon.encode()).hexdigest():
        raise SystemExit(f"CHAIN BROKEN at seq {e['seq']}")
    prev = e["hash"]
print(f"{len(events)} events verified . head {prev[:16]}...")
print("MATCHES published chain_head" if prev == published else "MISMATCH")

Expected output (your event count grows over time):

5728 events verified · head f2e4fbc47154c486… · MATCHES published chain_head ✓

Try to break it

Download events.ndjson, change a single character in any event, and run the verifier against your copy. It reports CHAIN BROKEN at seq N at exactly the event you touched — because the hash no longer matches, and neither does anything after it. That is the whole point: the history cannot be quietly rewritten without it being detectable by anyone, with no special tools.

What this proves — and what it doesn't

Honesty about scope is part of the point. What the check proves: the Project Memory event log is internally consistent and unaltered — no recorded event has been edited or removed since it was written, and the chain you compute matches the published head. What it does not prove: that a recorded claim is true in the outside world. Verification confirms that a value was recorded with its stated source at its stated time — not that the source itself is correct; each claim carries its source and authority class so you can judge that yourself. This chain covers Project Memory; the governance and treasury figures are computed from on-chain snapshots and carry their own provenance and methodology.

Why this matters

An ecosystem's memory is only as trustworthy as your ability to check it. Most dashboards ask you to take their numbers on faith. Here, the record carries its own proof: the data is public, the chain is published, and the verification is a few lines you can read in full and run yourself — today, or in ten years, on any machine with Python. Provenance you can confirm, not provenance you're asked to believe.

Go deeper. Each project's sourced history lives in Project Memory; the preservation model is documented in PRESERVATION.md; the full methodology is in methodology.