Add Bitcoin anchoring via OpenTimestamps

Implements merkle tree anchoring for ActivityPub activities with
provable Bitcoin timestamps. Activities are batched into merkle trees,
submitted to OpenTimestamps (free), and proofs stored on IPFS.

Key features:
- Merkle tree construction with membership proofs
- OpenTimestamps integration for Bitcoin anchoring
- JSONL backup file on persistent volume (survives DB wipes)
- API endpoints for creating/verifying anchors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-09 01:22:39 +00:00
parent 2267096271
commit 7ead2026ef

View File

@@ -1848,12 +1848,17 @@ async def record_run(req: RecordRunRequest, user: User = Depends(get_required_us
# ===== PHASE 2: IPFS OPERATIONS (blocking, before any DB changes) =====
try:
# Pin all inputs
for inp in input_infos:
ipfs_client.pin_or_raise(inp["ipfs_cid"])
from concurrent.futures import ThreadPoolExecutor, as_completed
# Pin output
ipfs_client.pin_or_raise(output_ipfs_cid)
# Collect all CIDs to pin (inputs + output)
cids_to_pin = [inp["ipfs_cid"] for inp in input_infos] + [output_ipfs_cid]
# Pin all in parallel
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(ipfs_client.pin_or_raise, cid): cid for cid in cids_to_pin}
for future in as_completed(futures):
cid = futures[future]
future.result() # Raises IPFSError if failed
# Store recipe on IPFS
recipe_cid = ipfs_client.add_json(recipe_data)