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;