Verify the chain. Any language. No credentials.
Fonteum’s attestation chain is a Certificate-Transparency-style cryptographic chain over the snapshot attestations appended to it. Every link is Ed25519-signed, references the previous link’s hash, and is verifiable from inputs alone with the published public key. Unattached attestation rows are not chain members. This page is the canonical reference for verifiers.
← Chain index Underlying snapshot attestations → Live metadata JSON →
What the chain proves.
Every chain_links row is one signed link:
link_index— monotonically increasing bigint, starting at 0 (genesis).prev_hash— 64-char lowercase hex SHA-256 of the prior link’scontent_hash. Genesis prev_hash is"00".repeat(32).attestation_id— bigint reference to the underlyingsnapshot_attestationsrow this link attests over.NULLfor genesis only.attestation_content_hash— echoed fromsnapshot_attestations.content_hash. Same zero-pad asprev_hashfor genesis.content_hash— SHA-256 over the canonical serialization (next section). Locked once written.signature— Ed25519 signature ofcontent_hashusing the chain’s private key.public_key_id— identifier for the signing key. Phase 1 uses a single key (rotation is Phase 2 — see Public-key publication below).signed_at— ISO 8601 timestamp the link was signed. Part of the canonical content-hash payload.
A verifier walks link_index 0..head, recomputes eachcontent_hash, verifies eachsignature against the published public key, and checks prev_hash[N] == content_hash[N-1]. Any tamper anywhere in the chain breaks at least one of these three checks.
Atomic chain extension: each new link is appended via the extend_chain SECURITY DEFINER plpgsql function which performs INSERT chain_links + UPDATE chain_state head pointer in one transaction. The chain head pointer never lags the disk row.
Frozen contract.
The content_hash is SHA-256 over the following UTF-8 byte string. This format is FROZEN — changing it breaks every external verifier:
contentHash = SHA256(
String(linkIndex) || "||" ||
prevHash || "||" ||
attestationIdStr || "||" || // "null" for genesis
attestationContentHash || "||" ||
signedAtIso
)linkIndex— base-10 string, no leading zeros (e.g."0","123").prevHash,attestationContentHash— 64-char lowercase hex SHA-256.attestationIdStr— base-10 string for non-genesis links; literal"null"for genesis (attestation_id IS NULLonly atlink_index=0).signedAtIso— ISO 8601 with millisecond precision and trailing "Z" (e.g."2026-05-09T17:42:31.123Z")."||"— the literal two-character separator (U+007C twice). Not escaped inside any field because no field can contain "||" by construction.
link_index = 0.
The genesis link anchors the chain. It is created once, post-deploy, by the operator. Its values are fixed by spec:
link_index = 0prev_hash = "00".repeat(32)(64 zero hex chars)attestation_id = NULL(no underlying attestation)attestation_content_hash = "00".repeat(32)content_hash= canonical SHA-256 over the above +signed_atsignature= Ed25519 overcontent_hash
The genesis link’s attestation_id serializes to the literal string "null" in the canonical content-hash payload. This guarantees genesis cannot collide with any future link that has attestation_id = 0.
Single key, two equivalent surfaces.
The chain’s Ed25519 public key is published at two endpoints, both serving the same value (canonical source: chain_state.public_key):
https://fonteum.com/.well-known/chain-public-key— text/plain hex (64 lowercase hex chars + trailing newline). RFC-blessed location for automated discovery.https://fonteum.com/api/v1/chain→public_keyfield. Same value as a JSON field alongside chain metadata.
Phase 1 uses a single signing key. Key rotation is deferred to a separate wave (§sprint3-chain-key-rotation) which will introduce multi-key support with overlapping validity windows so verifiers can transition gracefully. Until rotation lands, the published public_key_id on every link points to the same key.
Six reads, one verify.
GET /api/v1/chain— chain head + total + published public key.GET /api/v1/chain/[link_index]— full record for one link. Cachedpublic, max-age=31536000, immutable(chain links are immutable once signed).GET /api/v1/chain/manifest— complete chain-link sequence with each referenced snapshot attestation; unattached attestations are excluded.GET /.well-known/chain-public-key— text/plain hex public key.GET /api/v1/chain/anchors— stored OpenTimestamps operational fields with independent mainnet validation reported separately.GET /api/v1/chain/corrections— append-only corrections and their available snapshot-attestation references.POST /api/v1/chain/verify— accepts a chain link JSON in the body, returns{ valid, errors[] }. Verifies content_hash, signature, and prev_hash linkage to the prior on-disk link.
Independent validation on July 12, 2026 found that 0 of 162 stored OpenTimestamps proof records validated against authentic Bitcoin-mainnet block headers. The stored operational state is not mainnet evidence.
Two checks, no DB access.
// Node 20+ — npm i @noble/ed25519
import { createHash } from 'node:crypto';
import { verifyAsync } from '@noble/ed25519';
const link = await fetch('https://fonteum.com/api/v1/chain/123').then((r) => r.json());
const meta = await fetch('https://fonteum.com/api/v1/chain').then((r) => r.json());
// 1. Re-derive content_hash via the canonical serialization.
const payload =
String(link.link_index) + '||' +
link.prev_hash + '||' +
(link.attestation_id === null ? 'null' : String(link.attestation_id)) + '||' +
link.attestation_content_hash + '||' +
link.signed_at;
const recomputed = createHash('sha256').update(payload, 'utf8').digest('hex');
console.log('content_hash matches:', recomputed === link.content_hash);
// 2. Verify the Ed25519 signature.
const hexToBytes = (h) => Uint8Array.from(h.match(/.{2}/g).map((b) => parseInt(b, 16)));
const valid = await verifyAsync(
hexToBytes(link.signature),
hexToBytes(link.content_hash),
hexToBytes(meta.public_key),
);
console.log('valid:', valid);
stdlib + cryptography.
# Python 3.10+ — pip install cryptography requests
import hashlib, requests
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.exceptions import InvalidSignature
link = requests.get('https://fonteum.com/api/v1/chain/123').json()
meta = requests.get('https://fonteum.com/api/v1/chain').json()
# 1. Re-derive content_hash via the canonical serialization.
attestation_id_str = 'null' if link['attestation_id'] is None else str(link['attestation_id'])
payload = '||'.join([
str(link['link_index']),
link['prev_hash'],
attestation_id_str,
link['attestation_content_hash'],
link['signed_at'],
])
recomputed = hashlib.sha256(payload.encode('utf-8')).hexdigest()
print('content_hash matches:', recomputed == link['content_hash'])
# 2. Verify the Ed25519 signature.
public_key = Ed25519PublicKey.from_public_bytes(bytes.fromhex(meta['public_key']))
try:
public_key.verify(bytes.fromhex(link['signature']), bytes.fromhex(link['content_hash']))
print('valid: True')
except InvalidSignature:
print('valid: False')
stdlib only.
// Go 1.21+ (stdlib only)
package main
import (
"crypto/ed25519"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
)
type ChainLink struct {
LinkIndex int `json:"link_index"`
PrevHash string `json:"prev_hash"`
AttestationID *int `json:"attestation_id"`
AttestationContentHash string `json:"attestation_content_hash"`
ContentHash string `json:"content_hash"`
Signature string `json:"signature"`
SignedAt string `json:"signed_at"`
}
type ChainMeta struct {
PublicKey string `json:"public_key"`
}
func mustGet(url string, out any) {
res, err := http.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
if err := json.NewDecoder(res.Body).Decode(out); err != nil {
panic(err)
}
}
func main() {
var link ChainLink
var meta ChainMeta
mustGet("https://fonteum.com/api/v1/chain/123", &link)
mustGet("https://fonteum.com/api/v1/chain", &meta)
// 1. Re-derive content_hash.
attID := "null"
if link.AttestationID != nil {
attID = fmt.Sprintf("%d", *link.AttestationID)
}
payload := fmt.Sprintf("%d||%s||%s||%s||%s",
link.LinkIndex, link.PrevHash, attID,
link.AttestationContentHash, link.SignedAt,
)
sum := sha256.Sum256([]byte(payload))
recomputed := hex.EncodeToString(sum[:])
fmt.Println("content_hash matches:", recomputed == link.ContentHash)
// 2. Verify the Ed25519 signature.
pubBytes, _ := hex.DecodeString(meta.PublicKey)
sigBytes, _ := hex.DecodeString(link.Signature)
msgBytes, _ := hex.DecodeString(link.ContentHash)
valid := ed25519.Verify(ed25519.PublicKey(pubBytes), msgBytes, sigBytes)
fmt.Println("valid:", valid)
}