Verify an entry
Three steps check an entry against the ledger.
- Paste the fingerprint or open the entry from the ledger.
- We look up the entry, its times and any outside timestamp.
- If the details are open, your browser recomputes the fingerprint and compares it.
No account is needed to read the ledger. Masked entries need All Access.
We couldn't load this. Try again.
- Committed
-
- Event
-
-
- Market
- Entry
- State
- Full fingerprint
- Fingerprint (first 10 characters)
What this check shows
A match shows these details are the ones we sealed, and the ledger shows when we sealed them. It says nothing about whether the call was right.
Hashes stored before the ledger existed came from earlier methods. They stay where they were and are not part of the ledger.
Check it without our page
This short Python program does the same check on your own computer.
import hashlib
import json
import sys
import urllib.request
BASE = "https://defintel.net/api/ledger/"
def get(path):
with urllib.request.urlopen(BASE + path) as r:
return json.loads(r.read().decode("utf-8"))
def sha(b):
return hashlib.sha256(b).digest()
def batch_hash(b):
fields = {k: str(b[k]) for k in ("batch_id", "entry_count", "first_seq", "last_seq")}
fields["merkle_root"] = b["merkle_root"]
fields["prev_batch_hash"] = b["prev_batch_hash"]
fields["sealed_at"] = b["sealed_at"]
text = json.dumps(fields, sort_keys=True, separators=(",", ":")).encode("utf-8")
return sha(b"DEFINTEL-LEDGER-BATCH-V2" + b"\x00" + text).hex()
def show(label, ok):
print(label + ": " + ("MATCH" if ok else "NO MATCH"))
return ok
def main(entry_hash, steps_back):
reveal = get("reveal/" + entry_hash)
if reveal["state"] != "revealed":
sys.exit("Still sealed. Details open at " + reveal["reveal_at"])
text = reveal["canonical_preimage"].encode("utf-8")
got = sha(b"DEFINTEL-LEDGER-ENTRY-V2" + b"\x00" + text).hex()
show("entry hash", got == entry_hash)
data = get("entry/" + entry_hash)
node = sha(b"\x00" + bytes.fromhex(entry_hash))
for step in data["proof"]["path"]:
sib = bytes.fromhex(step["hash"])
if step["position"] == "left":
node = sha(b"\x01" + sib + node)
else:
node = sha(b"\x01" + node + sib)
batch = data["batch"]
show("batch root", node.hex() == batch["merkle_root"])
show("batch hash", batch_hash(batch) == batch["batch_hash"])
print("committed at " + batch["sealed_at"] + " (UTC)")
current = batch
for _ in range(steps_back):
if current["batch_id"] == 1:
show("genesis link", current["prev_batch_hash"] == "0".ljust(64, "0"))
break
older = get("batch/" + str(current["batch_id"] - 1))["batch"]
ok = batch_hash(older) == older["batch_hash"] == current["prev_batch_hash"]
show("link to batch " + str(older["batch_id"]), ok)
current = older
main(sys.argv[1], int(sys.argv[2]) if len(sys.argv) > 2 else 3)
How the ledger works
- We seal each entry with a fingerprint (SHA-256) before its details open.
- An entry with an event time shows it beside our commit time.
- The fingerprint and its time go into a log that anyone can read.
- Each batch in the log carries the fingerprint of the one before it, so changing an old entry changes every later one.
- Our first batch also went to an outside timestamp service. We haven't confirmed it yet.
- Once an entry's details are open, you can recompute its fingerprint in your browser.
What it shows
It shows when we committed. It says nothing about whether the call was right.