tiny.reticulum.node.transport
Defined in node.
The state and the steps a node needs to work out where destinations are from the broadcasts it hears, and to move traffic toward them.
API (23)
Actions
Public operations.
State.activateState.configure: Names this node as a next hop, following Reticulum@1.5.0 RNS/Transport.py:1577-1580,1907.State.deinitState.init
Types and contracts
Public types and contracts.
State: The eight tables a node needs to carry traffic for others, together with the hash that names it and the flag that turns the carrying on.State.CapacityState.InitErrorState.LimitsState.Storage
Namespaces
Public namespaces.
announcesdiscoveriesinflightlink: A node needs records and steps to move the packets of encrypted sessions that run between other pairs of nodes through itself.linkspathrelayrequestsretransmitreverserewrite
Values and defaults
Public values and defaults.
Source
Source: lib/reticulum/src/node/transport/state.zig:105
zig
/// The eight tables a node needs to carry traffic for others, together with the/// hash that names it and the flag that turns the carrying on. A caller holds/// one of these per node, and every transport step reaches its store through/// it. The eight tables are carved from one block of caller storage whose/// length has to equal the derived byte count exactly.pub const State = struct { phase: alloc_phase.capacity.Phase, capacity: Capacity, storage: Storage, paths: path.Table, announces: announces.Table, reverse_entries: reverse.Table, tags: packet.hashlist.Table, inflight_requests: inflight.Table, discoveries: discoveries.Table, links: links.Table, link_entries: link_entries.Table, identity_hash: ?[16]u8 = null, enabled: bool = false, pub const storage_alignment: usize = 8; pub const Storage = []align(storage_alignment) u8; pub const Limits: type = StateLimits; pub const Capacity: type = StateCapacity; pub const InitError = Capacity.DeriveError || error{StorageLengthMismatch}; pub const work_limits: alloc_phase.capacity.WorkLimits = .{ .transition_steps_max = 8, .cleanup_steps_per_call_max = 0, .cleanup_calls_at_capacity_max = 0, }; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "reticulum.transport", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{.{ .id = "caller_transport_tables", .lifetime = .transferred, .detail = "caller storage for routing, relay, path request, and link tables", }}, .excluded = &.{"relayed, rebroadcast, request, and link frames in effect storage"}, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "paths", "paths_max"), alloc_phase.capacity.bindInput(Limits, "announces", "announces_max"), alloc_phase.capacity.bindInput( Limits, "reverse_entries", "reverse_entries_max", ), alloc_phase.capacity.bindInput( Limits, "path_request_tags", "path_request_tags_max", ), alloc_phase.capacity.bindInput( Limits, "inflight_requests", "inflight_requests_max", ), alloc_phase.capacity.bindInput(Limits, "discoveries", "discoveries_max"), alloc_phase.capacity.bindInput(Limits, "links", "links_max"), alloc_phase.capacity.bindInput( Limits, "link_entries", "link_entries_max", ), }, .type_selectors = &.{ alloc_phase.capacity.bindType(path.Entry, "path"), alloc_phase.capacity.bindType(announces.Entry, "announce"), alloc_phase.capacity.bindType(reverse.Entry, "reverse_entry"), alloc_phase.capacity.bindType(packet.Hash, "path_request_tag"), alloc_phase.capacity.bindType(inflight.Entry, "inflight_request"), alloc_phase.capacity.bindType(discoveries.Entry, "discovery"), alloc_phase.capacity.bindType(links.Entry, "link"), alloc_phase.capacity.bindType(link_entries.Entry, "link_entry"), }, .nodes = &.{ .{ .input = 0 }, .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 0 }, } }, .{ .input = 1 }, .{ .scale = .{ .node = 2, .coefficient = .{ .size_of_concrete_type = 1 }, } }, .{ .add = .{ .left = 1, .right = 3 } }, .{ .input = 2 }, .{ .scale = .{ .node = 5, .coefficient = .{ .size_of_concrete_type = 2 }, } }, .{ .add = .{ .left = 4, .right = 6 } }, .{ .input = 3 }, .{ .scale = .{ .node = 8, .coefficient = .{ .size_of_concrete_type = 3 }, } }, .{ .add = .{ .left = 7, .right = 9 } }, .{ .input = 4 }, .{ .scale = .{ .node = 11, .coefficient = .{ .size_of_concrete_type = 4 }, } }, .{ .add = .{ .left = 10, .right = 12 } }, .{ .input = 5 }, .{ .scale = .{ .node = 14, .coefficient = .{ .size_of_concrete_type = 5 }, } }, .{ .add = .{ .left = 13, .right = 15 } }, .{ .input = 6 }, .{ .scale = .{ .node = 17, .coefficient = .{ .size_of_concrete_type = 6 }, } }, .{ .add = .{ .left = 16, .right = 18 } }, .{ .input = 7 }, .{ .scale = .{ .node = 20, .coefficient = .{ .size_of_concrete_type = 7 }, } }, .{ .add = .{ .left = 19, .right = 21 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 22, }}, }, .overload = .{ .kind = .reject_before_seal, .detail = "invalid limits and short caller storage reject before activation", }, .risks = .{ .transitive = .{ .status = .witnessed, .detail = "all retained table storage is carved from the transport region", }, .foreign = .{ .status = .excluded, .detail = "the transport owner crosses no foreign boundary", }, }, .work = .{ .equation = "activation and teardown each visit eight subowners" }, .dependencies = &.{ "reticulum.paths", "reticulum.announces", "reticulum.reverse_entries", "reticulum.hashlist", "reticulum.inflight_requests", "reticulum.discoveries", "reticulum.links", "reticulum.link_entries", }, .obligations = &.{ .{ .key = "reticulum_transport_capacity", .role = .capacity_model }, .{ .key = "reticulum_transport_overload", .role = .overload }, .{ .key = "reticulum_transport_transitive", .role = .transitive_risk }, .{ .key = "reticulum_transport_work", .role = .work_bound }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker }, }, }, }; pub fn init(storage: Storage, limits: Limits) InitError!State { const capacity = try Capacity.derive(limits); if (storage.len != capacity.storage_bytes) return error.StorageLengthMismatch; return .{ .phase = .initialization, .capacity = capacity, .storage = storage, .paths = try path.Table.init( region(storage, 0, capacity.paths.storage_bytes), .{ .paths_max = limits.paths_max }, ), .announces = try announces.Table.init( region(storage, capacity.announces_offset, capacity.announces.storage_bytes), .{ .announces_max = limits.announces_max }, ), .reverse_entries = try reverse.Table.init( region( storage, capacity.reverse_entries_offset, capacity.reverse_entries.storage_bytes, ), .{ .reverse_entries_max = limits.reverse_entries_max }, ), .tags = try packet.hashlist.Table.init( region(storage, capacity.tags_offset, capacity.tags.storage_bytes), .{ .hashes_max = limits.path_request_tags_max }, ), .inflight_requests = try inflight.Table.init( region( storage, capacity.inflight_requests_offset, capacity.inflight_requests.storage_bytes, ), .{ .inflight_requests_max = limits.inflight_requests_max }, ), .discoveries = try discoveries.Table.init( region(storage, capacity.discoveries_offset, capacity.discoveries.storage_bytes), .{ .discoveries_max = limits.discoveries_max }, ), .links = try links.Table.init( region(storage, capacity.links_offset, capacity.links.storage_bytes), .{ .links_max = limits.links_max }, ), .link_entries = try link_entries.Table.init( region( storage, capacity.link_entries_offset, capacity.link_entries.storage_bytes, ), .{ .link_entries_max = limits.link_entries_max }, ), }; } pub fn activate(self: *State) void { std.debug.assert(self.phase == .initialization); self.paths.activate(); self.announces.activate(); self.reverse_entries.activate(); self.tags.activate(); self.inflight_requests.activate(); self.discoveries.activate(); self.links.activate(); self.link_entries.activate(); self.phase = .steady; } /// Names this node as a next hop, following Reticulum@1.5.0 /// RNS/Transport.py:1577-1580,1907. A caller turns the node into one that /// carries traffic for others, and gives it the hash that names it to its /// neighbors. Every step that carries traffic for others refuses until the /// flag is set. pub fn configure(self: *State, identity_hash: [16]u8, enabled: bool) void { std.debug.assert(self.phase == .steady); self.identity_hash = identity_hash; self.enabled = enabled; } pub fn deinit(self: *State) Storage { std.debug.assert(self.phase == .steady); _ = self.link_entries.deinit(); _ = self.links.deinit(); _ = self.discoveries.deinit(); _ = self.inflight_requests.deinit(); _ = self.tags.deinit(); _ = self.reverse_entries.deinit(); _ = self.announces.deinit(); _ = self.paths.deinit(); self.phase = .teardown; const storage = self.storage; self.* = undefined; return storage; }};Source: lib/reticulum/src/node/root.zig:78
zig
pub const transport = @import("transport/root.zig");Source: lib/reticulum/src/node/transport/root.zig
zig
//! The state and the steps a node needs to work out where destinations are from//! the broadcasts it hears, and to move traffic toward them.//!//! A node has to find out where destinations are with no directory to ask. A//! node that carries traffic for others carries it toward destinations for//! neighbors that cannot reach them directly, and answers a neighbor that//! asks about a destination it knows. The node also passes another pair's//! encrypted session across itself.//!//! What a node knows arrives as broadcasts, so the same broadcast reaches it//! more than once, by more than one route, and out of order, and the node needs//! a rule that picks one without a clock shared with the sender. Repeating//! every broadcast would flood the mesh. A forwarded packet has to say which//! node passed it on for any answer to come back. Storage is a fixed number of//! entries the caller fixes before the node starts, so every store states which//! entry a new one takes over, and a store that refuses a new entry when it is//! full says so. The node performs no input or output and reads no clock, so//! each step takes the current second from its caller and returns the frames to//! send and the timers to arm.//!//! Reticulum 1.5.0, the reference implementation this package is a port of,//! answers each of these forces, and this subtree is a port of those answers.//! Every module here cites the reference by file and line. The lineage is//! checkable in this tree: the package README pins the upstream commit the port//! follows, and the conformance corpus under src/conformance is generated from//! that release and drives the differential tests.//!//! A destination makes itself known with a broadcast carrying its public keys,//! a signature and ten random bytes holding the instant it was stamped (an//! *announce*), so any node that hears the announce learns that destination and//! how far away it sits. That instant orders two announces from the same//! destination without a shared clock. The node keeps what it learns from//! announces about reaching one destination, the network interface to send on,//! the neighbor to name as the next hop, and how many hops away the//! destination sits (a *path*). A path keeps the announces it has already//! taken, so a repeat is recognized and an older one loses. A node that carries//! traffic for others sends an announce it accepted onward at most twice, stops//! at 128 hops, and stops as soon as it hears neighbors carrying the same one.//! A forwarded packet's header grows a field that names the node passing it on//! by that node's 16-byte hash, and two header shapes, of 19 and of 35 bytes,//! tell a packet in transport from one at its last hop. The node keeps a record//! for each packet it forwards, tying it to the network interface it arrived on//! and the one it left on, so the signed answer that confirms the packet (a//! *proof*) travels the way the packet came. A node asks its neighbors for a//! way to reach a destination by sending requests to one well-known//! destination.//!//! Every store here (a *table*) lives in bytes the caller hands over and the//! node hands back at teardown, with its entry maximum fixed before the node//! starts and its replacement rule written in the code. Reticulum 1.5.0 grows//! dictionaries and culls them on a periodic pass. Time is whole seconds, so//! the reference's fractional waits become the nearest whole second. Nothing//! sweeps on a fixed interval: an entry stops counting at its own deadline when//! it is looked up, and for relayed sessions the node asks its caller to wake//! it at each session's deadline (a *node timer*). A step that turns a packet//! away names the reason in a record for its caller to read (a *diagnostic*).//! Reticulum 1.5.0 writes such a reason to a log or raises a protocol//! violation.//!//! The modules below divide the work: `path` holds what the node learned about//! reaching destinations, `announces` and `retransmit` hold the queue of//! announces to send on and the sweep that sends them, `relay` with `rewrite`//! and `reverse` carry one packet onward and bring its proof back, `requests`//! with `inflight` and `discoveries` ask for a path and answer when asked,//! `link` and `links` hold the sessions the node carries and the ones it holds//! an end of, and `state` carves all eight stores from one block of caller//! storage.//!//! - *destination*: the 16-byte hash that names one addressable endpoint on the//! network.//! - *transport node*: a node that carries traffic on behalf of other nodes, as//! well as sending and receiving its own.//! - *link*: an encrypted session between two endpoints, named by a 16-byte//! link id that both ends derive from the request packet.//! - *emission time*: the instant the originator stamped into the ten random//! bytes an announce carries, which orders two announces from the same//! destination.//! - *carrier*: one network interface the node sends and receives over, named//! by a small integer index.//! - *transport identity hash*: the 16 bytes a transport node writes into a//! packet header so the next node along sees who passed it on.//! - *next hop*: the neighboring node a packet is handed to on its way, named//! in the packet header by its transport identity hash.//! - *rebroadcast*: the sending onward of an announce a transport node//! accepted, so the mesh learns the destination beyond this node.//! - *hop count*: the byte in the packet header that rises by one at every node//! the packet passes through.//! - *pathfinder maximum*: the hop count of 128, at and above which a packet is//! refused.//! - *reverse entry*: the record that ties a relayed packet to the carrier it//! arrived on and the carrier it left on, so the answering proof travels the//! way the packet came.//! - *effect*: a record the node appends to send a frame on a carrier or arm a//! timer.//! - *path request*: a packet asking any node that knows a path to a//! destination to answer with one.//! - *HEADER_1*: the 19-byte header shape, carried by a packet that names no//! node it is passing through.//! - *HEADER_2*: the 35-byte header shape, which carries the 16-byte hash of//! the node the packet is passing through.pub const announces = @import("announces.zig");pub const discoveries = @import("discoveries.zig");pub const inflight = @import("inflight.zig");pub const link = @import("link/root.zig");pub const links = @import("links.zig");pub const path = @import("path.zig");pub const relay = @import("relay.zig");pub const requests = @import("requests.zig");pub const retransmit = @import("retransmit.zig");pub const reverse = @import("reverse.zig");pub const rewrite = @import("rewrite.zig");pub const State = @import("state.zig").State;Complete call list for node.transport.State.activate
7 direct calls.
tiny.reticulum.node.transport.announces.Table.activate[method] atlib/reticulum/src/node/transport/announces.zig:227tiny.reticulum.node.transport.discoveries.Table.activate[method] atlib/reticulum/src/node/transport/discoveries.zig:154tiny.reticulum.node.transport.inflight.Table.activate[method] atlib/reticulum/src/node/transport/inflight.zig:144tiny.reticulum.node.transport.links.Table.activate[method] atlib/reticulum/src/node/transport/links.zig:197tiny.reticulum.node.transport.path.Table.activate[method] atlib/reticulum/src/node/transport/path.zig:247tiny.reticulum.node.transport.reverse.Table.activate[method] atlib/reticulum/src/node/transport/reverse.zig:148tiny.reticulum.packet.hashlist.Table.activate[method] atlib/reticulum/src/packet/hashlist.zig:128
Complete call list for node.transport.State.deinit
7 direct calls.
tiny.reticulum.node.transport.announces.Table.deinit[method] atlib/reticulum/src/node/transport/announces.zig:308tiny.reticulum.node.transport.discoveries.Table.deinit[method] atlib/reticulum/src/node/transport/discoveries.zig:248tiny.reticulum.node.transport.inflight.Table.deinit[method] atlib/reticulum/src/node/transport/inflight.zig:187tiny.reticulum.node.transport.links.Table.deinit[method] atlib/reticulum/src/node/transport/links.zig:267tiny.reticulum.node.transport.path.Table.deinit[method] atlib/reticulum/src/node/transport/path.zig:338tiny.reticulum.node.transport.reverse.Table.deinit[method] atlib/reticulum/src/node/transport/reverse.zig:189tiny.reticulum.packet.hashlist.Table.deinit[method] atlib/reticulum/src/packet/hashlist.zig:215
Complete call list for node.transport.State.init
8 direct calls.
tiny.reticulum.node.transport.announces.Table.init[function] atlib/reticulum/src/node/transport/announces.zig:216tiny.reticulum.node.transport.discoveries.Table.init[function] atlib/reticulum/src/node/transport/discoveries.zig:143tiny.reticulum.node.transport.inflight.Table.init[function] atlib/reticulum/src/node/transport/inflight.zig:133tiny.reticulum.node.transport.links.Table.init[function] atlib/reticulum/src/node/transport/links.zig:183tiny.reticulum.node.transport.path.Table.init[function] atlib/reticulum/src/node/transport/path.zig:236tiny.reticulum.node.transport.reverse.Table.init[function] atlib/reticulum/src/node/transport/reverse.zig:137lib.reticulum.src.node.transport.state.region[function] — private source atlib/reticulum/src/node/transport/state.zig:376in nearest public ownerlib.reticulum.src.node.transport.statetiny.reticulum.packet.hashlist.Table.init[function] atlib/reticulum/src/packet/hashlist.zig:117
Audit
| Definitions | 13 |
|---|---|
| Public names | 13 |
| Members | 13 |
| Version | 26.7.0 |
| Revision | daab053ee433 |