Open data
Evidence digests
Recompute it yourself. Every SHA-256 the published price rows cite as their evidence, grouped by UTC day with one Merkle root per day. The manifest carries digests only — no payload, so nothing a source restricts is redistributed. Below: how to recompute a digest from its retained raw file, and a day's root from the manifest.
The manifest
/evidence/digests.json lists each day’s distinct digests in leaf order, each with the evidence reference that pins it and the /price-history.json series whose row on that day cites it. A raw-payload digest is the SHA-256 of a retained source payload (a Vast.ai book retained from collector live-quotes-v6 on is hashed as its allowlist projection, an earlier one as the response received). An observation-set digest is the SHA-256 of the sorted IDs of the observations behind a daily class aggregate, joined with commas; those IDs live in the price database, so that digest is checked on request.
Each build checks the published datasets for digests:
- Price-history ledger: 1,891 rows cite a digest; all are listed
- Quote snapshot export: publishes no evidence digests (its rows cite none; /evidence shows the snapshot's own content ID)
- Marketplace ask tape: publishes no evidence digests (its raw books' digests are not exported yet)
- Forward-curve archive: publishes 26 digest values, not yet listed here
Verify a digest
- Request the raw file. A raw-payload reference reads
raw-snapshots@<commit>:<path>#source=<source>: an exact commit on the site’s private raw-snapshots branch, the gzipped bundle at that path, and the payload’s source. Raw payloads are archived privately and available on request: email data@aicomputetracker.com with the reference. - Decompress the bundle and find the entry in its
evidencelist whosesourceis the reference’s decoded#source=value. - Hash its
rawTexts: a single text as its UTF-8 bytes; several in order, each as its UTF-8 byte length in decimal, a colon, then its bytes. The hex result is the digest the manifest lists.
# python3 verify_digest.py <bundle.json.gz> <the reference's #source= value>
import gzip, hashlib, json, sys, urllib.parse
bundle = json.loads(gzip.open(sys.argv[1]).read())
source = urllib.parse.unquote(sys.argv[2])
for item in bundle["evidence"]:
if item["source"] != source:
continue
texts = item["rawTexts"]
digest = hashlib.sha256()
if len(texts) == 1:
digest.update(texts[0].encode("utf-8"))
else:
for text in texts:
body = text.encode("utf-8")
digest.update(f"{len(body)}:".encode("ascii") + body)
print(item.get("gpu", "-"), digest.hexdigest())Recompute a day’s root
A day’s root is the RFC 6962 Merkle Tree Hash of its digests. The day's distinct digests, each as its 32 raw bytes, in ascending order of their lowercase hex; each leaf hash is SHA-256(0x00 || digest). Each interior node is SHA-256(0x01 || left || right). A list of one leaf hashes to its leaf hash; a list of n > 1 leaves splits after the first k, where k is the largest power of two smaller than n, and the root is the node over the two halves' roots.
# python3 verify_root.py digests.json <YYYY-MM-DD>
import hashlib, json, sys
def tree_hash(leaves):
if len(leaves) == 1:
return hashlib.sha256(b"\x00" + leaves[0]).digest()
split = 1
while split * 2 < len(leaves):
split *= 2
return hashlib.sha256(
b"\x01" + tree_hash(leaves[:split]) + tree_hash(leaves[split:])
).digest()
day = next(d for d in json.load(open(sys.argv[1]))["days"] if d["date"] == sys.argv[2])
leaves = sorted({entry["sha256"] for entry in day["digests"]})
print(tree_hash([bytes.fromhex(d) for d in leaves]).hex() == day["root"])Test vector
The SHA-256 digests of “a”, “b” and “c”, in leaf order:
2e7d2c03a9507ae265ecf5b5356885a53393a2029d241394997265a1a25aefc63e23e8160039594a33894f6564e1b1348bbd7a0088d42c4acb73eeaed59c009dca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
give the root dd67a4e94fcb4fff954bcb093257364a5b5d0832bda9ffb7a5b6340e45ca647b.
Roots by day
The 30 newest of 81 days; the manifest lists every day. A day is open until the ledger has been exported 2 days after it: its root may still change, and only a closed day is timestamped. A day shows a timestamp only once a proof for its current root is committed; a later change to a day’s digests makes a new root, which needs its own proof.
| Day (UTC) | Digests | Root | Timestamp |
|---|---|---|---|
| open — root may change | 12 | 66a8a277d7edaf31fa7e519e96f6d55827f10b5dbe24c06c15851519c30e0454 | Not yet timestamped |
| open — root may change | 11 | 4ddc6f15c9de3dfe70b7de4d5b3a50442c5ef574df65934332c31669ea576a6d | Not yet timestamped |
| 13 | 7e630bd4cd126c99026628decde0cd4c9c9633ab13dfa358e37cbe516898db09 | Not yet timestamped | |
| 23 | e23765e3daebaa34a33e402198afba188dd2fbef40b593d8d7d5995aac9f6ec1 | Not yet timestamped | |
| 18 | ad93a77c052b56d742a6ec1d0af74fde2ad474c21e7f0fa2aac3515f607c8b35 | Not yet timestamped | |
| 23 | 0ca0ed049793b2ed21e3c989b8f2ef5bd78c653a62dffa2b7a80c0ca1ed459a8 | Not yet timestamped | |
| 23 | d8679eb205e2549a01f8a0f9a37b68ed208b3d68f2a9225a7830a80a0e22bc7c | Not yet timestamped | |
| 23 | 914d93716455ec2d17a738f3a19b4ad4019a61a043a705d4720d6d3b1e23ecbe | Not yet timestamped | |
| 21 | 953563e337c884f4a8f0456eb6c628633e3b73571faeb94d174f8e2c538f9e69 | Not yet timestamped | |
| 21 | 86b64dcfdcbdb33bdda635a1573a151dbc13545e2b7984f15f54c515c55400d9 | Not yet timestamped | |
| 21 | 3456688a72547efe05fb39ddca7723a9f21aeb646f0ca35fe42b771711104161 | Not yet timestamped | |
| 21 | 2b1b1aab459fb05e6ba75749e2778782e91e10125d078accd42d544f43db941e | Not yet timestamped | |
| 23 | e1f65f74d4360b617c42551513324c93fa86bd8db8622d74c1efc1ad26e3c2cc | Not yet timestamped | |
| 21 | 546775ba05a6f9a12797cfb7a43606f798f81e365075da04ac1484c3df222d0c | Not yet timestamped | |
| 21 | a989ab010a0e6b1890757e963f98807f789205e5d783005285a2562ee5d2e41e | Not yet timestamped | |
| 23 | a99f6ba1b069870058dfca849d729d18601c5bc03fed5b74f935b5251b0d8184 | Not yet timestamped | |
| 21 | 78e76252302542fcb38c83a84151dce5190c18fad9c45b2355f2072318e50b47 | Not yet timestamped | |
| 21 | 6197b6bcc107e0e3ea5325d2a30bd1f797ab2ccff2378fb8f9b588388c080555 | Not yet timestamped | |
| 21 | 9d7614bab61899ba9eb1450ed0199b545c8987b52c52cfaa9357e68ff69dfa93 | Not yet timestamped | |
| 23 | 7dd079580abf97aec5358a675e75144a64d76d706f9c548f1436fa03026c81ab | Not yet timestamped | |
| 23 | 43100ad885a03364d8326332bd842c8d6a4ce85ce9d88b841dc901898859bb62 | Not yet timestamped | |
| 19 | cdabfcf97528ea3042b498df87a8e2370cfbba55c9617c1d0d7d10738129bbdd | Not yet timestamped | |
| 23 | 5d4cfc7fc8aec3370dbe8981a63435e6251ba5ee264cc2eab87bc47b3187e6f0 | Not yet timestamped | |
| 19 | feed6f4bb72fdbbba80d7e30d3afc6d4745cd2dcd797e2a85788d91e32af600d | Not yet timestamped | |
| 21 | 879b8ed888139f103297fe3492bac7579b6cabdb44b0213412a4be24c8dc7442 | Not yet timestamped | |
| 21 | 11de365acee4096171b188d2840053af88d080423737b908890db42fad8a873b | Not yet timestamped | |
| 21 | 8f48856159600a45b7f8e7a447bd58408ded4fadf2a145b8cda238f26de8a300 | Not yet timestamped | |
| 21 | 9dcb13c09ce4d0a2646d5e24261631c5e2becc863bd5dc8bc4f12b0999c65064 | Not yet timestamped | |
| 21 | 0438fb7ff32e4a21580ec7df7321b7fb2a71df13ac371c697ee8506fdc86c5b1 | Not yet timestamped | |
| 21 | bfcb3398a53d7b3797488d15603b031c6e0cdfcfc1683d2d26be001730bf5103 | Not yet timestamped |