lib/reticulum/src/node/root.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! A state machine for one node of a mesh network holds everything the node remembers and turns one
2 //! input at a time into a list of things for the program around it to do. That network is
3 //! Reticulum, in which nodes find each other by broadcasting signed announcements and reach each
4 //! other over any network interface that moves bytes.
5 //!
6 //! Someone writing such a node has to decide what to put on the wire, what to remember about who is
7 //! out there, and when a deadline has passed, and the program around the node keeps the sockets,
8 //! the clock, and the source of randomness. The node has to run on machines whose memory is fixed
9 //! before the program starts, so it takes the size of each store it keeps from the caller and
10 //! refuses work once a store is full. A port of an existing protocol has to be checkable against
11 //! the original, byte for byte.
12 //!
13 //! Code that reads the wall clock and draws its own randomness gives a different answer on every
14 //! run, which leaves nothing to compare against a reference. Sending from inside the protocol logic
15 //! also needs somewhere for the bytes to live. A transition can run out of room part way through,
16 //! and a half-applied transition would leave the node's stores disagreeing with what the caller was
17 //! told.
18 //!
19 //! The subtree follows *Reticulum 1.5.0*, the reference implementation this package is a port of.
20 //! The package README and the generated conformance material pin the upstream commit. What the
21 //! subtree takes from the reference is its order of handling an arriving packet, its state machines
22 //! for routes and for encrypted sessions, and its timeouts, and each declaration names the
23 //! reference file and line range it follows. The package generates reference bytes and clocks from
24 //! that release (a *conformance corpus*) and replays them in differential tests, so each of those
25 //! claims is checkable from this tree.
26 //!
27 //! A transition (a *step*) takes the instant and the 32 bytes of randomness it needs from its own
28 //! input, so replaying the same inputs gives the same results. The node sends nothing, arms no
29 //! timer, and writes no storage itself: it appends a record of each such request (an *effect*) to a
30 //! list, and the caller performs them. Every transition first reserves room (a *reserve*): it
31 //! checks that the list of effects and the storage for its bytes can hold what it is about to
32 //! append before it changes any store, so a transition that runs out of room leaves the node as it
33 //! was. Every store takes its entry maximum (its *limits*) from the caller and is carved out of one
34 //! block of caller storage whose length has to equal the derived byte count exactly. The node keeps
35 //! one packet-sized buffer (its *scratch*) where a transition builds the bytes it is about to hand
36 //! to one network interface.
37 //!
38 //! The file exports the subtree's pieces: `Node` and `Limits`, the `Event` a transition takes and
39 //! the `Effect` records it returns, `timer`, and the modules `inbound` for arriving frames,
40 //! `outbound` for sends, `announce`, `link`, `transport` for carrying traffic on behalf of other
41 //! nodes, and `fixture`, the three-node test world.
42 //!
43 //! - *node*: the state machine that holds one Reticulum node's tables, one packet of scratch space,
44 //! and its effect list.
45 //! - *event*: the one input a step takes, either a frame that arrived on a carrier, a timer that
46 //! came due, an application request, or the completion of a caller's storage write.
47 //! - *step entropy*: the 32 bytes the caller draws fresh for each carrier frame and each timer
48 //! event, which the step expands with HKDF-SHA256 whenever it needs a key or an initialization
49 //! vector.
50 //! - *table*: an owner over caller-supplied bytes with a fixed entry maximum, which carves the
51 //! caller's storage once and hands it back at teardown.
52 //! - *packet*: one Reticulum datagram, at most 500 bytes, carrying a flags byte, a hop count, an
53 //! optional transport id, a destination hash, a context byte, and a payload.
54 //! - *frame*: the bytes handed to one carrier, one packet plus at most a 64-byte signature.
55 //! - *carrier*: one network interface a node sends and receives frames over, named by a byte index.
56 //! - *announce*: a packet carrying a destination's public keys, a name hash, ten random bytes, and
57 //! a signature, so any node that hears it learns that destination and how far away it sits.
58 //! - *path*: what a node learned from an announce about reaching one destination: the carrier to
59 //! send on, the neighbor to name as the next hop, and how many hops away it sits.
60 //! - *link*: an encrypted session between two endpoints, named by a 16-byte link id that both ends
61 //! derive from the request packet.
62 //! - *timer*: a deadline the node holds, naming what comes due and the whole second it comes due
63 //! at.
64 //! - *transport node*: a node that carries traffic on behalf of other nodes, as well as sending and
65 //! receiving its own.
66
67 const effect = @import("effect.zig");
68 const errors = @import("error.zig");
69 const event = @import("event.zig");
70 const limits = @import("limits.zig");
71 const owner = @import("owner.zig");
72 pub const timer = @import("timer.zig");
73 pub const outbound = @import("outbound.zig");
74 pub const announce = @import("announce.zig");
75 pub const inbound = @import("inbound.zig");
76 pub const link = @import("link.zig");
77 pub const transition = @import("step.zig");
78 pub const transport = @import("transport/root.zig");
79 pub const fixture = @import("fixture/root.zig");
80
81 pub const Seconds = timer.Seconds;
82 pub const TimerId = timer.TimerId;
83 pub const PersistToken = event.PersistToken;
84
85 pub const Limits = limits.Limits;
86 pub const Capacity = limits.Capacity;
87 pub const Node = owner.Node;
88 pub const Access = owner.Access;
89 pub const Interface = owner.Interface;
90 pub const ProofMode = owner.ProofMode;
91 pub const RatchetBinding = owner.RatchetBinding;
92 pub const StepError = errors.Error;
93
94 pub const Event = event.Event;
95 pub const CarrierFrame = event.CarrierFrame;
96 pub const TimerExpired = event.TimerExpired;
97 pub const ApplicationSend = event.ApplicationSend;
98 pub const ApplicationAnnounce = event.ApplicationAnnounce;
99 pub const ApplicationProve = event.ApplicationProve;
100 pub const ApplicationPathRequest = event.ApplicationPathRequest;
101 pub const ApplicationLinkOpen = event.ApplicationLinkOpen;
102 pub const ApplicationLinkSend = event.ApplicationLinkSend;
103 pub const ApplicationLinkClose = event.ApplicationLinkClose;
104 pub const ApplicationLinkProve = event.ApplicationLinkProve;
105 pub const StorageComplete = event.StorageComplete;
106 pub const Effect = effect.Effect;
107 pub const Effects = effect.Effects;
108 pub const Code = effect.Code;
109 pub const LinkCloseReason = effect.LinkCloseReason;
110 pub const LinkRole = transport.links.Role;
111 pub const PersistKind = effect.PersistKind;
112 pub const effects_per_event_max = effect.effects_per_event_max;
113 pub const effect_frames_per_event_max = effect.effect_frames_per_event_max;