Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

0002 Events and synchronisation

Version 0.1, draft. Implemented in the reference library (crates/librotenado).

Events

A set of books consists of events. An event is immutable; its identity is the SHA-256 hash of its canonical encoding (part 0003), written sha256: followed by 64 lower-case hexadecimal digits, like every hash in the protocol. An event is always a root object of type event:

{"type": "event", "kind": "booking_recorded", "time": {…}, "seq": 1, "prev": null, "booking": {…}}

Every event has:

MemberContent
typeevent
kindwhat happened (below); the members that come with it stand next to the others
timea hybrid logical clock timestamp (type timestamp): wall_ms, counter, device
seqthe event’s position in its device’s chain, starting at 1
prevthe hash of the device’s previous event; null for position 1, never left out

Kinds in version 0.1:

kindMembersWhat happened
organisation_describedorganisationan organisation was described, or its description changed (part 0008)
person_describedpersona person was described, or their description changed (part 0008)
owner_addedownerthe books belong to this organisation or person, too (part 0008)
owner_removedownerthe books no longer belong to them (part 0008)
chart_selectedchart, as name/versionthe books use this harmonised chart of accounts (part 0004)
account_openedaccountan account of the books’ own was opened, refining a known one (below)
booking_recordedbookinga booking (part 0001) was recorded
booking_reversedreverses, bookingthe booking recorded by the event reverses was cancelled by booking, with the opposite amounts
document_recordeddocumenta document was recorded with its data and original (part 0005)

Later versions add kinds and members. An implementation keeps, chains and passes on events of a kind or with members it does not know, unchanged (part 0003), but does not interpret what it does not know.

Devices and clocks

Every device that writes events has a name unique within the set of books: 1 to 64 characters of a-z, 0-9 and -. Its timestamps come from a hybrid logical clock: milliseconds since 1970-01-01 UTC, a counter for events within the same millisecond, and the device name. Timestamps are ordered by wall time, counter and device. A device MUST make every new timestamp later than every timestamp it has made or seen.

Merging

Two copies of the same books merge by set union of their events. Merging MUST give the same result in any order and any number of times. Events are processed in the order of their timestamps, then their hashes – an order every device agrees on.

The state of the books

The state of a set of books is the SHA-256 hash of the canonical encoding (part 0003) of the array of all its event hashes in the agreed order, written sha256:…. Two copies with the same events have the same state, whatever order the events arrived in. Whatever is derived from the books – a filing (part 0007), a report – records the state it was derived from.

Chains and problems

The events of one device form a chain: positions 1, 2, 3, … without gaps, each event pointing to its predecessor with prev. An implementation MUST report, and MUST NOT silently resolve:

  • Fork – two different events of one device at the same position.
  • Gap – missing positions (events that have not arrived yet).
  • Broken link – an event whose prev is not the device’s previous event.

Conflicts in the content of the books – such as reversing a booking twice or reversing one that does not exist – go to a review list in the same way; resolving them is a new event, never a change to an old one.

Accounts of the books

The books select the harmonised chart they use with chart_selected; more than one selected chart is for review. Accounts of their own – each bank account, each customer and supplier – are opened with account_opened: an account (part 0004) whose parent is required and is an account of the chart or another opened account, of the same kind. An implementation MUST report, and MUST NOT silently resolve:

  • Unknown account – a posting on an account that is neither in the chart nor opened (the event that opens it may not have arrived yet).
  • Unknown parent – an opened account without a parent, or whose parent is neither in the chart nor opened.
  • Kind mismatch – an opened account of another kind than its parent.
  • Duplicate – an account opened twice, or opened with the identity of an account of the chart.

Parts 0005 and 0008 add problems of documents and of parties in the same way.