lib/reticulum/src/node/fixture/root.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! Three nodes of a mesh network are held inside one value, which runs them from a single clock and
2 //! can lose, delay, reorder, or cut off the traffic between them. The middle node carries traffic
3 //! for the two outer ones, so a packet from one end to the other crosses it in both directions.
4 //!
5 //! A test of a mesh protocol has to watch a packet cross an intermediate node and has to see the
6 //! answer come back the way it went. The test also has to put the protocol under loss, delay,
7 //! reordering, and a cut link, because the protocol exists to survive them. Every such run has to
8 //! give the same answer each time, so that a failure can be reproduced and the bytes can be
9 //! compared against a reference.
10 //!
11 //! Real interfaces and real clocks give a different interleaving on every run. Each node needs its
12 //! own storage before the test starts, because a node calls no allocator. A node reports what it
13 //! wants done and does none of it, so something has to carry its traffic, hold its deadlines, and
14 //! hand back each thing it asked for.
15 //!
16 //! The package follows *Reticulum 1.5.0* (the reference implementation this package ports, pinned
17 //! to one upstream commit), generates reference bytes and clocks from that release (a *conformance
18 //! corpus*), and replays those vectors in this world for a packet forwarded through the middle
19 //! node.
20 //!
21 //! That value (the *world*) owns the three nodes' storage and runs from one clock that drives
22 //! everything: it advances to the next packet or deadline that falls due and parks at the second
23 //! the caller asked for. Each of the four one-way paths between neighboring nodes (a *directed
24 //! link*) holds a queue of at most eight frames with the second each is due, so a test scripts its
25 //! loss, delay, and reordering in advance. The 32 bytes each input carries, drawn fresh for each
26 //! carrier frame and each timer event (the *step entropy*), come from a counter hashed with
27 //! SHA-256, so two runs of the same script derive the same keys. A transition expands those bytes
28 //! with HKDF-SHA256 whenever it needs a key or an initialization vector. Every request a node
29 //! returns, such as a frame to send on a carrier or a deadline to arm (an *effect*), stands in for
30 //! input or output the node does not do itself. The world writes each effect to its log as one
31 //! line, which the test reads back by node and kind. The test runs the world until no frame is due
32 //! and no deadline falls due (it *settles*). A run still busy after sixty-four rounds fails with
33 //! `error.WorldDidNotSettle`.
34 //!
35 //! - *node*: the state machine that holds one Reticulum node's tables, one packet of scratch space,
36 //! and its effect list.
37 //! - *transport node*: a node that carries traffic on behalf of other nodes, as well as sending and
38 //! receiving its own.
39 //! - *timer*: a deadline the node holds, naming what comes due and the whole second it comes due
40 //! at.
41 //! - *record*: one line of the world's log, holding the second, the node, the effect kind, and the
42 //! fields that kind carries.
43 //! - *relay*: forwarding a packet that names this node as its next hop toward the destination its
44 //! path gives, rewriting only the header.
45
46 const world = @import("world.zig");
47
48 pub const World = world.World;
49 pub const Link = world.Link;
50 pub const NodeId = world.NodeId;
51 pub const LinkId = world.LinkId;
52 pub const Fault = world.Fault;
53 pub const Options = world.Options;
54 pub const Codes = world.Codes;
55 pub const Record = world.Record;
56 pub const Kind = world.Kind;
57 pub const Tag = world.Tag;
58 pub const Delivery = world.Delivery;
59 pub const Seconds = world.Seconds;
60 pub const limits = world.limits;
61 pub const records_max = world.records_max;
62 pub const deliveries_max = world.deliveries_max;
63 pub const frames_max = world.frames_max;
64 pub const faults_max = world.faults_max;