Evidence integrity and chain of custody · Lesson 2 of 5
Preserving on-chain evidence
8 min read
A blockchain keeps its history, but almost everything an investigator uses to read that history can change. Explorers redesign pages and relabel addresses, analytics tools update their attributions, websites and forum posts disappear, and the most recent blocks can still be replaced. Preserving on-chain evidence means fixing each of these views at a known moment, so that a reviewer years later can check exactly what you saw and confirm it against the chain itself.
What actually needs preserving
The raw ledger is the one part of a case that rarely needs rescuing: once a block is final, any honest node will return the same data. What needs preserving is the context around it. The table lists the usual items.
| Item | Why it can change or vanish | How to preserve it |
|---|---|---|
| Raw transactions and blocks | Not final yet; your provider prunes data or goes offline | Save raw JSON or hex from a node, with block hash and finality status |
| Explorer pages | Layout, labels and decoded fields change | Capture the page (screenshot plus archive file) and also save the raw data behind it |
| Address and cluster labels | Tools and label sets update, merge or remove entries | Export the labels used, with source, version and date |
| Tool outputs (graphs, traces, reports) | Re-running later uses new labels and code | Export native files and a readable copy, with tool version and settings |
| Web evidence (sites, forums, social posts) | Deleted, edited or geo-restricted | Archive file, screenshot, hash, URL and time of capture |
| Prices and exchange rates | Sources revise data; values differ between venues | Record the source, pair, time and the value used |
Treat the raw data as the evidence and everything else as a dated view of it. If an explorer screenshot and the node disagree, the node wins, and the disagreement goes in your notes.
Anchoring every fact to a block
A txid identifies a transaction, but it does not by itself fix where that transaction sits in the chain you examined. Record, for every transaction you rely on:
- chain and network (Bitcoin mainnet, Ethereum chain ID 1, a named L2 and its chain ID);
- txid, and for account-model chains the log index of any event you rely on;
- block height and block hash;
- confirmations, or finality status, at the moment of capture;
- the source: your own node and its client version, or a named public API;
- retrieval time in UTC, and the file the raw data was saved to, with its SHA-256 hash.
{
"fact_id": "F-012",
"chain": "bitcoin-mainnet",
"txid": "4f3a…c21e",
"block_height": 966204,
"block_hash": "0000…3b9e",
"confirmations_at_capture": 4828,
"source": "own node, client v30.x",
"cross_check": "public explorer API, retrieved 2026-10-14T10:05Z, fields match",
"retrieved_utc": "2026-10-14T09:42:10Z",
"raw_file": "raw/4f3a_c21e.json",
"raw_file_sha256": "0072…33a9"
}
This record ties one fact used in the report (F-012) to the exact transaction, block and source, and to a saved raw file whose hash can be checked. Digests are shortened for print; the real record holds all 64 hex characters. The cross-check line records that a second, independent source gave the same values. The IDFE-BA lesson Data quality, normalization and provenance gives a similar record for whole datasets; the forensic addition is that every fact cited in a report can be traced to one of these records.
Reorganizations and finality
Data captured near the chain tip can be undone by a reorganization, in which nodes switch to a competing branch and recent blocks become stale. The IDFE-BA lesson Blocks and headers as data explains the mechanics. For evidence the rules are simple:
- Do not preserve as final what is not final. On Bitcoin, six confirmations is the common convention, and evidence for a report should sit well beyond that. On Ethereum, use blocks at or below the
finalizedcheckpoint, normally about 13 minutes behind the head. - Record the status at capture. If you had to capture early, for example to document a theft while it is happening, mark the record as provisional.
- Re-verify provisional records once they are final: fetch the transaction again, confirm it sits in a block with the same hash, and note the check. If the block hash changed, the transaction may have moved or vanished, and anything built on it must be reviewed.
- Layer 2s need a second look. A rollup's own blocks can appear final within seconds, but the stronger guarantee comes only when the batch containing them is final on the base chain, and withdrawals from optimistic rollups add a challenge window. Record which level of finality you relied on.
Live documentation is still valuable: an early capture shows what was visible and when. It simply must be labeled for what it is.
Verifying against a second source
A single source can be wrong: an explorer can mis-decode a token, show a stale balance or attach a wrong label. Before an extract becomes evidence, compare it with an independent source, ideally your own node against a public one, or two unrelated providers. The query below assumes the examiner has loaded the facts cited in the report into evidence_facts, and a fresh extract from a second source into node_check.
-- Facts whose txid is missing, or sits in a different block, in the second source
SELECT f.fact_id, f.txid, f.block_hash AS cited_block, n.block_hash AS check_block
FROM evidence_facts f
LEFT JOIN node_check n ON n.txid = f.txid
WHERE n.txid IS NULL
OR n.block_hash <> f.block_hash
OR n.value_sats <> f.value_sats; -- for EVM chains compare value in wei and log_index
Every row returned is a problem to resolve before the report goes out. A txid missing from the second source usually means a typing error; the same txid in a different block means the record was captured on a branch later replaced in a reorganization; a different value usually means a unit or decimals error. An empty result, with the query and both sources recorded, is itself a useful record of verification.
Snapshotting labels and tool outputs
Labels decay. An address labeled as a payment processor this year may be relabeled as an exchange next year, or merged into a larger cluster. If your report says a deposit went to "Exchange X", a reviewer must be able to see the label as it stood when you relied on it. Export, for each label used: the entity name, the address or cluster it covers, the source (self-published, provider record, community list, analytics tool), the source's version or date, and your confidence. The IDFE-BA lesson Attribution and labeling covers grading labels; here the point is to freeze them.
Tool outputs need the same treatment. Save the native project file if the tool has one, a readable export (CSV or JSON of nodes and edges) and a rendered image, and record the tool version, the tracing method, hop limits and other settings. Re-running the same case in a later version may give a different graph, and you will need to explain the difference. The lesson Tooling, reproducibility and validation covers how to reconcile tools that disagree.
Archiving web evidence
Off-chain pages often carry the attribution: a scam site listing deposit addresses, a forum post offering stolen funds, a service's terms of use. The Berkeley Protocol on Digital Open Source Investigations, published in 2020 by the UN Human Rights Office and the Human Rights Center at UC Berkeley, sets out how to collect and preserve such material professionally. Capture methods are covered in the lesson OSINT methodology. The preservation record should include:
- an archive file in the WARC format (ISO 28500:2017), which keeps the page's content and the server's responses;
- a full-page screenshot, for human reading;
- the URL, capture time in UTC, the tool used, and whether the capture was attributable or not;
- the SHA-256 hash of each file, computed at capture;
- where useful, a copy in a public web archive as independent corroboration, never as the only copy.
To show that a capture existed by a certain time, you can obtain a trusted timestamp for its hash (RFC 3161 defines one protocol) or anchor the hash in a public blockchain transaction. OpenTimestamps is an open-source example of the second approach.
The re-verifiable evidence package
All of this comes together in an evidence package: a folder that lets a reviewer check every fact without trusting you.
CF-2026-041_onchain_v1/
README.txt how to re-verify, sources, software versions
manifest.sha256 one SHA-256 line per file below
facts.json fact records (F-001 ... F-088)
raw/ raw transactions and blocks from the node
labels/labels_2026-10-12.json
tool/trace_graph_export.json
web/forum_post_capture.warc
web/forum_post_capture.png
The manifest lists every file's hash; the hash of the manifest itself (for this version, 4b91…199f) goes into the case log and the evidence log, so one value protects the whole package. The README says how to fetch each transaction from any node, compare it with raw/, and recompute the hashes. Never edit a package after it is sealed: issue version 2 with a new manifest and record why. The lesson Hashing, logging and chain of custody covers how the package then moves through custody.
Exam focus: why raw final chain data rarely needs rescuing while explorer pages, labels, tool outputs, web pages and prices do; the fields that anchor a fact (chain, txid, log index, height and block hash, finality at capture, source and client version, UTC time, raw file hash); not treating unfinalized data as final, marking provisional captures and re-verifying them; rollup versus base-chain finality; cross-checking against an independent source; exporting label snapshots and tool settings; WARC, screenshots, hashes and trusted timestamps for web evidence under the Berkeley Protocol; the evidence package, its manifest and versioning instead of editing.