What this project is about
RunLedger is a compact Python command-line tool that links experiment summaries into a verifiable sequence. A hash is a fixed-length fingerprint calculated from data. Each JSON record stores its own hash and the previous record's hash, making certain edits detectable. The project demonstrates this specific integrity check without requiring a database or external service.
Internal consistency is not the same as trustworthy provenance—evidence of where a record came from. A valid chain means the current records agree with their hashes. It does not prove an experiment happened, that the metrics are correct or that the entire file has not been replaced. Someone controlling every record can recalculate the complete chain.
How it works
- Experiment record
- Hash-linked entry
- Chain verification
Hash content consistently
The hash function excludes the stored sha256 field, converts the remaining values to a standard JSON representation with sorted keys and compact separators, then applies SHA-256 to the UTF-8 bytes. This consistent representation prevents ordinary changes in key order or formatting from changing the record's logical fingerprint.
Check before adding records
Before appending, the tool reads the file, rejects reused run IDs and verifies the existing chain. Each new record contains its run ID, status, metrics, UTC timestamp and previous record's hash. The first record uses a fixed all-zero starting value because it has no predecessor.
Locate an inconsistency
Verification checks records in order, recalculating each hash and checking its link to the previous record. It reports the first mismatching line. Invalid JSON also produces a line-specific error. The command's success or failure exit status allows another program to act on the result without interpreting a human-written report.
The important design choices
Keep records readable
Use JSON Lines: one readable JSON record per line in a local file.
The trade-offThe history is easy to inspect and version, but the implementation reads the whole file into memory and does not coordinate programs writing to it at the same time.
Separate integrity from authenticity
Link records without digital signatures or an independent timestamping service.
The trade-offThis exposes inconsistent edits, but cannot prevent a complete rewrite or prove the final stored hash matches an independently trusted original.
Detect a changed metric
Create two linked synthetic experiment summaries in a local ledger.
- Verify the original file and retain its final hash as a separate reference.
- Edit one stored metric without recalculating its hash.
- Run verification again and inspect the first mismatch.
What this showsThe verifier detects the inconsistency. If an attacker recalculates every affected hash instead, exposing the rewrite requires a comparison with an independently trusted reference.
Illustrative example, not an additional measured result.
How it was tested—and what it shows
The checks
The tests included in the repository check a valid two-record chain, modification of an existing metric and rejection of a reused run ID. They cover basic behaviour, not experiment truth or every case of file corruption, removed records or simultaneous writes.
What to take from the results
The deliverable is an inspectable integrity mechanism, not a measured performance improvement. Hashing and trustworthy provenance solve different problems: editing a metric without updating hashes is detectable, but rebuilding the entire chain is not prevented. Keeping the final hash in an independently protected location would provide an external reference against which later versions could be checked.
What to keep in mind
- Someone who can replace the whole chain and its reference can create a different history.
- A consistent record does not prove that its contents are true.
Technical notes & source
Built with
Python · hashing · experiment records
Terms used in this project
- Hash
- A compact fingerprint calculated from data.