walletpress/backend/core/proof_digest.py
cryptorugmunch e13bd4d774
Some checks are pending
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / security (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / license (push) Waiting to run
CI / ai-review (push) Waiting to run
docs: apply fleet-template (16-artifact scaffold)
Adds missing standard artifacts:
- README.md (if missing)
- AGENTS.md (AI agent contract)
- PLAN.md (current sprint)
- STATUS.md (where we are)
- DEVELOPMENT.md (dev workflow)
- DEPLOYMENT.md (deploy procedure)
- TESTING.md (test strategy)
- DECISIONS.md (ADR index + templates)
- .github/CODEOWNERS
- .github/workflows/ci.yml

Preserves all existing artifacts.

Refs: RugMunchMedia/fleet-template
2026-07-02 02:07:06 +07:00

121 lines
3.9 KiB
Python

"""Proof of Generation Digest — periodic Merkle root publishing.
Every N attestations, compute the Merkle root and record it.
This digest serves as the immutable record of all wallet generations.
The Merkle root can be:
1. Stored locally in SQLite (always, free)
2. Published to the /api/v1/proof/roots endpoint (always)
3. Sealed on Arweave for permanent immutable storage (planned)
4. Committed to Ethereum as calldata for on-chain timestamp (planned)
ARCHITECTURE:
Attestations (leaves)
Merkle Tree (batches of 100-1000 attestations)
Merkle Root (hash of all leaves in batch)
├──→ SQLite (always)
├──→ API endpoint (always)
├──→ Arweave (planned)
└──→ Ethereum (planned)
"""
from __future__ import annotations
import time
from pathlib import Path
from typing import Optional
from .proof import PROOF_VERSION, get_proof
def create_digest() -> dict:
"""Create a Proof of Generation digest from all pending attestations.
Computes the Merkle root, commits it, and returns a digest document
that can be published as proof of all wallet generations up to now.
Returns:
Dict with root_hash, leaf_count, timestamp, and attestation IDs.
"""
proof = get_proof()
root_hash, leaf_count = proof.compute_merkle_root()
if not root_hash or leaf_count == 0:
return {"committed": False, "leaf_count": 0}
result = proof.commit(root_hash, leaf_count)
return {
"committed": True,
"version": PROOF_VERSION,
"root_hash": root_hash,
"leaf_count": leaf_count,
"timestamp": time.time(),
"verification_url": f"/api/v1/proof/root/{root_hash}",
"commitment": result,
}
def verify_wallet(wallet_id: str, address: str, public_key_hex: str = "") -> dict:
"""Verify a specific wallet's attestation.
Returns the full provenance including the Merkle path.
"""
proof = get_proof()
return proof.verify(wallet_id, address, public_key_hex)
def generate_verification_page(root_hash: str, output_path: Optional[Path] = None) -> str:
"""Generate an HTML verification page for a Merkle root.
This page can be statically hosted or published as proof.
Anyone visiting this URL can verify any wallet under this root.
"""
proof = get_proof()
roots = proof.get_roots(1)
html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WalletPress Proof of Generation — Root Verification</title>
<style>
body {{ font-family: monospace; background: #f5f5f5; padding: 40px; }}
.container {{ max-width: 640px; margin: 0 auto; background: #fff; padding: 32px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }}
h1 {{ font-size: 20px; margin-bottom: 16px; }}
.meta {{ font-size: 13px; color: #666; margin-bottom: 24px; }}
.hash {{ font-family: monospace; background: #f0f0f0; padding: 12px; border-radius: 4px; word-break: break-all; font-size: 12px; }}
.verified {{ color: #10b981; font-weight: 600; }}
</style>
</head>
<body>
<div class="container">
<h1>WalletPress Proof of Generation</h1>
<div class="meta">
<strong>Merkle Root:</strong>
<div class="hash">{root_hash}</div>
</div>
<div class="meta">
<strong>Version:</strong> {PROOF_VERSION}<br>
<strong>Timestamp:</strong> {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}<br>
<strong>Total Wallet Attestations:</strong> {roots[0]['leaf_count'] if roots else 'N/A'}<br>
</div>
<p>This Merkle root is the cryptographic commitment for all wallet
generations in this batch. Each wallet's attestation is a leaf in
this Merkle tree.</p>
<p>To verify a specific wallet, visit:<br>
<code>/api/v1/proof/verify/{{wallet_id}}</code></p>
<p class="verified">This attestation is immutable and timestamped.</p>
</div>
</body>
</html>"""
if output_path:
output_path.write_text(html)
return html