LedgerHash

The accounting engine with sealed periods. Sandbox on staging

Journal entries sealed into a hash chain, periods closed under a Merkle root, inclusion proofs you can verify offline.

How an entry is sealed

  1. Journal entry

    An entry of 2 to 500 lines is inserted as a draft.

  2. Canonical payload

    Lines are sorted canonically, so input order cannot change the hash. The payload is pipe-delimited and deterministic.

  3. Sealed

    entry_hash = SHA-256(canonical payload ‖ previous_hash). The previous hash is the prior entry's hash; the root is SHA-256(“LEDGERHASH GENESIS v1”). The posting sequence is gapless.

  4. Re-derived by the database

    On draft → posted the database independently re-derives the seal and refuses forged hashes or gaps.

How a period is closed

  1. Merkle tree over the period

    leaf = SHA-256(0x00 ‖ entry hash), node = SHA-256(0x01 ‖ left ‖ right), an odd node is promoted. The result is the period's merkle_root.

  2. Period hash chained

    period_hash = SHA-256(merkle_root ‖ previous_period_hash). Closed periods chain to one another.

  3. Exactly one seal

    One seal per period. Seals are immutable for every role; the database enforces it.

Entries, periods, proof

The illustration below follows one entry from posting to an inclusion proof, then shows what happens when an earlier entry is altered.

LedgerHash: sealed entries, closed periods, inclusion proof

Illustrative digests
  1. Entries 415 to 418 are sealed in sequence; each entry hash is SHA-256 of the canonical payload and the previous hash.
  2. Period P-08 closes: a Merkle tree over the four entry hashes gives the merkle_root; period_hash is SHA-256 of the root and P-07's period hash.
  3. The inclusion proof for entry 418 lists the sibling hashes up to the root; it can be verified offline.
  4. Verification re-derives every payload and finds no mismatch: the period is intact.
  5. Entry 417's amount is altered: its recomputed digest differs, verification reports FINGERPRINT_MISMATCH at posting sequence 417, the Merkle root changes, and P-08 and P-09 period hashes differ.

Entries are sealed with the previous hash; a closed period gets a Merkle root and a period hash chained to the previous period. One altered entry changes the root and every later period hash.

Anchoring of sealed periods to write-once storage is supported.

What the API gives you

  • Inclusion proofs

    GET /v1/verify/entry/{id}/proof returns a Merkle inclusion path that can be verified offline against the period root.

  • Verification

    /v1/verify/* re-derives every payload and reports FINGERPRINT_MISMATCH or CHAIN_LINK_BROKEN at the first altered posting sequence, cascading into that period's Merkle root and every later period hash. An empty result means intact.

  • Attestation snapshots

    /v1/proofs snapshots are durable, content-hashed attestation wrappers. They are not cryptographic proofs by themselves.

  • Anchoring supported

    An anchor record for a sealed period can be written to storage with Object Lock in compliance mode (365 days) and verified via GET /v1/verify/anchor/{code}. Anchoring is operator-triggered today; there is no automated worker.

  • Test and live keys

    Sandbox keys are prefixed lh_test_, live keys lh_live_. Platform sandboxes are constrained to the test environment in the database.

What we do not claim

  • Hashing is not encryption; entries are tamper-evident, not secret.
  • No public or third-party attestation is involved; verification runs against your tenant's data.
  • Anchoring is supported and operator-triggered; periods are not anchored automatically.
  • No certification, audit or uptime statistics are claimed.

Start with a sandbox. Move to production when you are ready.

Sign up in the Portal, create an organisation, open a sandbox. When you need production, join the waitlist.

Sandboxes run on staging with test data. Production access is by waitlist.