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

Host tools: RCEdb, media, redacted replay and chat

This chapter covers four tools of the RCE host runtime, the program that runs an RCE program against the outside world and keeps its log D of admitted events. Codes such as HC-3 (host contract rule 3), HS-9 (host storage rule 9) and T8 (theorem 8), and section numbers such as 6.7 or E.8, name rules of the RCE specification.

These commands ship in the rce binary of the host runtime. They are not yet in the public reference checker that the listings of this book are checked with, so this chapter has no checked listings.

rce db D CMD [ARGS]: RCEdb from the command line

RCEdb is the database of an RCE system: its tables, rows, edges, schemas and indexes are state of an RCE module (rcedb/rcedb.rce), and its only storage is a durable log D of the host runtime. Appendix E.8 gives the normative rules; this section describes the command. rce db is serverless and in-process: the directory D is the database, and each command opens it, admits at most one event and closes it. There is no daemon, no network listener and no query engine outside RCE.

Write commands admit one event to D and print ok seq N, where N is the sequence number of the entry they appended, or REFUSED E with the error E the module raised; a refused write changes no state (T8).

CommandEffect
insert T K ROWadd row ROW under key K of table T (refused with Exists when K is present)
delete T Kremove row K (refused with Missing when absent)
link S L D2 / unlink S L D2add or remove the edge from S to D2 with label L
schema T COLSgive table T a typed schema, COLS as name:text, name:i64 or name:bool, comma-separated; allowed only while T has no rows
index T COLkeep a secondary index on column COL of T, a fold of D (HS-7)

Under a schema a row is its cells in column order, separated by the horizontal tab U+0009; a row whose cells do not parse as their column types is refused with BadRow. Read commands append nothing (HS-8):

CommandOutput
scan T [START]KEY<TAB>ROW per row of T from key START, in canonical key order
lookup T COL VALUEthe rows whose column COL equals VALUE, through the index when one exists
edges SLABEL<TAB>DST per edge from S
describeper table: row count, schema and indexes
dumpevery row and edge, one line each
emit sqlite|postgres|duckdb|cypherthe state as Structured Query Language (SQL) statements for SQLite, PostgreSQL or DuckDB, or openCypher MERGE statements, headed by the entry count and state hash of D they project
as-of N scan T [START]the scan of T over the fold of the first N entries of D (time travel, HS-9)

An emitted store is a projection of D and never feeds back into it: the foreign engine's durability and ordering do not reach δ. A runnable example is run.sh rcedb in the examples of the host runtime.

Media capture and playback: --media DIR

rce host run and rce host serve take --media DIR to connect the media adapters. A program requests them with three output kinds, each with one result event (HC-3):

  • MediaOpen(req, source) opens a track. The source is dir:NAME, the files of DIR/capture/NAME in name order, one per frame, or pattern:N, N generated test frames (at most 100000). The result carries the track id.
  • MediaRead(req, id) reads the next frame of a track. Its bytes are stored as a blob under DIR addressed by their Secure Hash Algorithm 256 (SHA-256) digest, and the result carries only the digest.
  • MediaPlay(req, track, digest) plays a frame to the sink by digest; the sink refuses a frame whose stored bytes do not hash to the digest.

D therefore holds the track, the sequence number and the digest of each frame, and the Tick that read it, never the frame bytes. Replay with every adapter disconnected (HC-8) reaches the same state without capturing again. In a call, frames travel between peers through a selective forwarding unit (SFU), a relay that forwards each frame to the other subscribers of its track without reading it; chapter 17 describes it.

Redacted replay: rce host replay FILE --log D --redact F,...

rce host replay re-derives every state hash of D with every adapter disconnected and prints the final state. With --redact F,G the fields named F and G are printed as <redacted sha256:H>, where H is the first six bytes of the SHA-256 digest of the field's value in canonical form. Redaction changes only what is printed: D, the replay and every state hash are unchanged, and two replays of the same field print the same H, so a reviewer can compare runs without seeing a secret. Private keys, ratchet state and frame digests are the fields to redact. D itself still holds the secrets and stays on the device that wrote it.

The chat user interface

apps/chat.rce is a complete chat program: workspaces, channels and topic threads, direct messages and groups, reactions, presence, file shares and call rooms, as one replicated RCE state. Every change is an operation applied locally and sent to peers over remote channels (P4, the host's channel adapter, enabled with --chan HOST:PORT and --peer HOST:PORT, with Transport Layer Security (TLS) under --tls). Replicas order messages by (Lamport clock, author) and so converge. Direct messages are end-to-end encrypted (E2EE) as chapter 17 describes. apps/chat.rce is generated from apps/chat-app.rce and lib/crypto.rce by scripts/build-chat.sh.

The front end scripts/chat-ui.py runs rce host serve apps/chat.rce as a child process and holds no chat state of its own. Each command it accepts becomes an event in D, so a session replays:

CommandEvent
/open CONV TOPICswitch to a thread and mark it read
TEXTpost TEXT to the current thread
/edit N TEXT, /del Nedit or delete your message N
/react N EMOJItoggle a reaction
/dm PEER TEXT, /dms PEERsend or show an encrypted direct message thread
/unread, /readunread counts per thread; mark the thread read

It renders two queries of the program that change no state: View(conv, topic), one tab-separated line per message (view, the message key, the author, the flags new, edited, deleted and e2e, the text) ending with view-end, and Unread, one line per thread with messages from others after the read marker. Run it with python3 scripts/chat-ui.py --me ann --log /tmp/ann.log [--chan ADDR --peer ADDR ...].