Skip to documentation
SLOP

tiny.reticulum.node.transport

Reference 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.

Types and contracts

Public types and contracts.

Namespaces

Public namespaces.

Values and defaults

Public values and defaults.

No direct callersNo direct callsnodetransport
Static calls · unresolved targets: unknown · external targets: unknown.

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;    }};
Called byCallstest sourcelib.reticulum.src.node.transport.statetest: transport state carves and acti...node.transport.announces.Tableactivatenode.transport.discoveries.Tableactivatenode.transport.inflight.Tableactivatenode.transport.links.Tableactivatenode.transport.path.Tableactivate+2 morenode.transport.Stateactivate
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest sourcelib.reticulum.src.node.transport.statetest: transport state carves and acti...node.transport.Stateconfigure
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.reticulum.src.node.transport.statetest: transport state carves and acti...node.transport.announces.Tabledeinitnode.transport.discoveries.Tabledeinitnode.transport.inflight.Tabledeinitnode.transport.links.Tabledeinitnode.transport.path.Tabledeinit+2 morenode.transport.Statedeinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.reticulum.src.node.transport.statetest: transport state carves and acti...test sourcelib.reticulum.src.node.transport.statetest: transport state rejects zero li...node.transport.announces.Tableinitnode.transport.discoveries.Tableinitnode.transport.inflight.Tableinitnode.transport.links.Tableinitnode.transport.path.Tableinit+3 morenode.transport.Stateinit
Static calls · unresolved targets: 1 · external targets: 1.

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.

Complete call list for node.transport.State.deinit

7 direct calls.

Complete call list for node.transport.State.init

8 direct calls.

Audit

Definitions13
Public names13
Members13
Version26.7.0
Revisiondaab053ee433