HTTP transparency log service inspired by Certificate Transparency (CT). Stores bundle hashes in an append-only Merkle tree with verifiable inclusion proofs.
# Start the service
node index.js
# Or with Docker
docker compose up transparency-logThe service listens on http://localhost:3002 by default.
Service health check.
curl http://localhost:3002/health{
"ok": true,
"service": "dcp-transparency-log",
"size": 42
}Add a bundle hash to the log.
curl -X POST http://localhost:3002/add \
-H "Content-Type: application/json" \
-d '{"bundle_hash": "sha256:abc123..."}'{
"index": 42,
"leaf_hash": "a1b2c3...",
"root": "d4e5f6...",
"size": 43
}Get the current Merkle root of the log.
curl http://localhost:3002/root{
"root": "d4e5f6...",
"size": 43
}Get the signed Merkle root (placeholder for operator signature).
curl http://localhost:3002/root/signed{
"root": "d4e5f6...",
"size": 43,
"timestamp": "2025-01-01T00:00:00.000Z",
"signature": "placeholder"
}Get the Merkle inclusion proof for an entry by index.
curl http://localhost:3002/proof/5{
"index": 5,
"leaf_hash": "a1b2c3...",
"entry": {
"hash": "sha256:abc123...",
"leaf_hash": "a1b2c3...",
"timestamp": "2025-01-01T00:00:00.000Z",
"index": 5
},
"root": "d4e5f6...",
"proof": [
{ "hash": "x1y2z3...", "direction": "left" },
{ "hash": "m4n5o6...", "direction": "right" }
]
}The proof allows verifying that an entry is included in the Merkle tree without downloading the entire log.
List all log entries.
curl http://localhost:3002/entries{
"entries": [
{ "hash": "sha256:...", "leaf_hash": "...", "timestamp": "...", "index": 0 },
{ "hash": "sha256:...", "leaf_hash": "...", "timestamp": "...", "index": 1 }
],
"size": 2
}| Variable | Default | Description |
|---|---|---|
PORT |
3002 |
HTTP port |
The log follows a format inspired by Certificate Transparency (RFC 6962):
- Append-only: Entries are never deleted or modified
- Merkle tree: Each entry generates a
leaf_hash(SHA-256) that is incorporated into the tree - Inclusion proofs: Anyone can verify that an entry exists in the log using the proof
- Signed root: The root can be signed by the operator (current placeholder)
To verify that an entry is in the log:
- Get the proof with
GET /proof/:index - Compute
leaf_hash = SHA-256(entry.hash) - Recombine the proof nodes:
- If
direction == "left":hash = SHA-256(proof_hash + current) - If
direction == "right":hash = SHA-256(current + proof_hash)
- If
- The final result must match the current
root
# Start in development mode
PORT=3002 node index.js
# Test
curl http://localhost:3002/health
curl -X POST http://localhost:3002/add \
-H "Content-Type: application/json" \
-d '{"bundle_hash": "sha256:test123"}'
curl http://localhost:3002/root
curl http://localhost:3002/proof/0Apache-2.0