How the hash chain works
Every daily portfolio snapshot on NakedPnL is cryptographically chained to the previous one. This makes historical records tamper-evident: changing any past snapshot breaks every subsequent hash in the chain.
1. Hash chain formula
For each daily snapshot, two hashes are computed:
For the very first snapshot in a chain (genesis), previousChainHash is the literal string "genesis".
Concatenation uses no separator: the input to the chain hash is previousChainHash + contentHash (two 64-character hex strings joined directly, or "genesis" + 64 hex chars for the first entry).
2. Fetch the raw chain
The full chain for any public trader is available via a CORS-open API:
Returns JSON with an array of snapshots, each containing contentHash, chainHash, and previousChainHash.
3. Verify in Python (20 lines)
4. Verify in JavaScript (25 lines)
5. What the chain proves
The chain does not prove that the underlying exchange API returned accurate data, that the trader is who they claim to be, or that past performance will continue. See our full disclaimers.
6. Bitcoin attestation via OpenTimestamps
Each day, all entity chain heads across the registry are combined into a binary Merkle tree. The Merkle root is submitted to OpenTimestamps calendar servers, producing a cryptographic attestation that is independently verifiable against the Bitcoin network.
Attestations are independently verifiable using the OpenTimestamps CLI. The Merkle root cryptographically attests to the state of every entity chain in the registry at that point in time. Modifying any historical snapshot would change its chain head, which would change the Merkle root, which would no longer match the attestation anchored in a specific Bitcoin block.
7. Correction events
The chain is append-only: historical rows are never modified or deleted, even when an integration bug is discovered after-the-fact. Instead, a correction is recorded as a new NavSnapshot with a clearly labelled rawResponse.correctiontag. The correction row is itself a valid chain entry — its contentHash and chainHash verify like any other row, so the public verifier still passes. The visible discontinuity at a correction event is the point: the registry shows what was wrong and what replaced it, instead of silently rewriting history.
The OKX adapter previously called the asset-valuation endpoint without specifying the valuation currency. OKX defaults to BTC, so historical OKX NavSnapshot rows stored a BTC-denominated value in the navUsd field. The raw API responses on disk are unchanged and still verify; the underlying defect was in the field that we derived from those responses on insert.
The integration was fixed to pass ccy=USD, and a single okx-btc-to-usd-redenomination-2026-05-05 correction row was appended to each affected trader's chain on 2026-05-05. The verifier will show a step-change in NAV at that row; the chain math still passes because the correction is itself a valid chain entry. All snapshots from this date forward are correctly USD-denominated.
8. On-chain reconciliation
For prediction market venues with on-chain settlement (Polymarket on Polygon), NakedPnL performs daily reconciliation between the venue REST API and the public subgraph. Position data from both sources is canonicalized, hashed, and compared. Mismatches are logged to an append-only reconciliation ledger and flagged for review.
On-chain trade history for Polymarket-connected traders is publicly viewable at /trader/<handle>/onchain, with direct links to transaction records on Polygonscan. This provides a second, independently verifiable data source for position history.