Zerobook. Ledger
(zerobook v0.1.0)
Copy Markdown
A tamper-evident, double-entry ledger.
The ledger is a linear chain of Zerobook.Blocks; each block holds the
SHA-256 of its own content plus the hash of the previous block. Any edit
to a past transaction — or a reordering, insertion or deletion of a
block — breaks every subsequent hash, so tampering is detectable by
re-verifying the chain.
Usage
ledger =
Zerobook.Ledger.new()
|> Zerobook.Ledger.append!(Zerobook.Transaction.new("txn_1", [
Zerobook.Entry.new("1000.cash", 1_000, "BRL"),
Zerobook.Entry.new("2000.revenue", -1_000, "BRL")
]))
Zerobook.Ledger.verify!(ledger) # => :okLedger state is immutable data (%Zerobook.Ledger{blocks: [...]}); each
block is plain data with prev_hash/hash links, so persistence is up to
the caller — store blocks in SQLite/Postgres (jsonb) and rebuild the
ledger by appending them in order.
Summary
Functions
Validates a transaction and appends it as a new block, returning
{:ok, ledger}.
Appends and unwraps: returns the updated ledger or raises.
Computes the running balance of account in currency.
Returns the list of blocks, oldest first.
Returns the last block, or nil on an empty ledger.
Creates an empty ledger.
Returns all postings touching account as
{transaction, entry} pairs, oldest first.
Verifies the whole chain: structural hashes and balanced transactions.
Verifies and unwraps: returns :ok or raises.
Types
@type t() :: %Zerobook.Ledger{ blocks: [Zerobook.Block.t()], index: non_neg_integer(), last_hash: binary() }
Functions
Validates a transaction and appends it as a new block, returning
{:ok, ledger}.
Rejects unbalanced transactions and duplicate transaction ids.
Appends and unwraps: returns the updated ledger or raises.
Computes the running balance of account in currency.
Examples
iex> ledger = Zerobook.Ledger.new() |> Zerobook.Ledger.append!(Zerobook.Transaction.new("t1", [
...> Zerobook.Entry.new("1000.cash", 1_000, "BRL"),
...> Zerobook.Entry.new("2000.revenue", -1_000, "BRL")
...> ]))
iex> Zerobook.Ledger.balance_of(ledger, "1000.cash", "BRL")
1000
Returns the list of blocks, oldest first.
Returns the last block, or nil on an empty ledger.
Creates an empty ledger.
Returns all postings touching account as
{transaction, entry} pairs, oldest first.
Verifies the whole chain: structural hashes and balanced transactions.
Returns :ok or {:error, reason} where reason is one of (positions
are 0-based indexes into the block list):
{:bad_hash, position}— the stored hash of the block atpositiondoes not match its recomputed content hash (tamper detected){:broken_link, position}— block atpositiondoes not reference the hash of the previous block (reorder/insertion/deletion detected){:unbalanced_tx, position}— transaction atpositionno longer sums to zero in every currency
Verifies and unwraps: returns :ok or raises.