Skip to documentation
SLOP

tiny.reticulum.node.fixture

Reference tiny.reticulum node fixture

Defined in node.

Three nodes of a mesh network are held inside one value, which runs them from a single clock and can lose, delay, reorder, or cut off the traffic between them.

API (31)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Source: lib/reticulum/src/node/fixture/world.zig:98

zig
/// The access codes for the A to B link and the B to C link.pub const Codes = struct {    a_b: ?node.Access = null,    b_c: ?node.Access = null,};

Source: lib/reticulum/src/node/fixture/world.zig:206

zig
pub const Delivery = struct {    at: Seconds,    link: LinkId,    ordinal: u32,    frame: carrier.Frame,};

Source: lib/reticulum/src/node/fixture/world.zig:82

zig
/// One scripted failure on one directed link. Three of the four identify a frame by ordinal, the/// number of frames that link was offered ahead of it, counted from 0, with the frames the link/// loses counted in. Every frame a fault names is one the link has yet to be offered. Departure/// follows the delivery second, and two frames due in one second depart by place. A frame's place/// is its ordinal until a swap trades it.pub const Fault = union(enum) {    /// The link drops the frame sitting at this ordinal.    drop: u32,    /// The frame sitting at this ordinal departs `seconds` later than the second that offered it. A    /// swap leaves this delivery second with its own frame.    delay: struct { ordinal: u32, seconds: Seconds },    /// The two frames at ordinals `first` and `second` exchange their places on the single occasion    /// when both sit in the queue, so a frame that left or was lost first blocks the swap. A    /// delivery second stays with its frame through the exchange, and a place moves.    swap: struct { first: u32, second: u32 },    /// The link drops each frame it was offered in the seconds `from` up to `until`, with both of    /// those seconds inside the span.    partition: struct { from: Seconds, until: Seconds },};

Source: lib/reticulum/src/node/fixture/world.zig:161

zig
/// The effect kinds the world logs beside the carrier frames it carries.pub const Kind = enum {    delivery,    announce,    path_request,    receipt,    diagnostic,    timer,    link_requested,    link_established,    link_delivery,    link_closed,};

Source: lib/reticulum/src/node/fixture/world.zig:130

zig
/// One directed link, holding a queue of at most eight frames, the second each is due, and its/// scripted faults. The link counts the frames it was offered and the frames it lost.pub const Link = struct {    queue: carrier.Memory,    due: [frames_max]Seconds = @splat(0),    order: [frames_max]u32 = @splat(0),    /// Each queued frame's tie-break among the frames due in the same second. A place starts out as    /// the frame's ordinal, a swap trades it, and it travels with the frame when the queue rotates.    place: [frames_max]u32 = @splat(0),    faults: [faults_max]Fault = @splat(.{ .drop = std.math.maxInt(u32) }),    consumed: [faults_max]bool = @splat(false),    fault_count: usize = 0,    offered: u32 = 0,    dropped: u32 = 0,    pub fn fault(self: *Link, value: Fault) void {        std.debug.assert(self.fault_count < faults_max);        switch (value) {            .drop => |ordinal| std.debug.assert(ordinal >= self.offered),            .delay => |late| std.debug.assert(late.ordinal >= self.offered),            .swap => |pair| {                std.debug.assert(pair.first != pair.second);                std.debug.assert(@min(pair.first, pair.second) >= self.offered);            },            .partition => |window| std.debug.assert(window.from <= window.until),        }        self.faults[self.fault_count] = value;        self.consumed[self.fault_count] = false;        self.fault_count += 1;    }};

Source: lib/reticulum/src/node/fixture/world.zig:16

zig
/// The four one-way links between neighboring nodes. Within one second the world drains them in/// the order they are written here.pub const LinkId = enum(u2) { a_to_b, b_to_a, b_to_c, c_to_b };

Source: lib/reticulum/src/node/fixture/world.zig:12

zig
/// The world's three nodes, with B between A and C as the one that carries traffic for the other/// two.pub const NodeId = enum(u2) { a, b, c };

Source: lib/reticulum/src/node/fixture/world.zig:120

zig
pub const Options = struct {    start: Seconds,    transport_hash: [16]u8,    codes: Codes = .{},    discover_paths: ?carrier.Index = null,    entropy: Entropy = .{},};

Source: lib/reticulum/src/node/fixture/world.zig:182

zig
pub const Record = struct {    at: Seconds,    owner: NodeId,    kind: Kind,    interface: carrier.Index = 0,    key: [16]u8 = @splat(0),    hops: u8 = 0,    tag: Tag = .receipt,    deadline: Seconds = 0,    path_response: bool = false,    proof_requested: bool = false,    code: ?node.Code = null,    status: ?packet.receipt.Status = null,    role: ?node.LinkRole = null,    reason: ?node.LinkCloseReason = null,    payload: [payload_bytes_max]u8 = @splat(0),    payload_len: u8 = 0,    pub fn plaintext(self: *const Record) []const u8 {        std.debug.assert(self.payload_len <= payload_bytes_max);        return self.payload[0..self.payload_len];    }};

Source: lib/reticulum/src/node/fixture/world.zig:175

zig
/// What a timer record names.pub const Tag = enum(u8) { receipt, hashlist, announces, link, link_entries };

Source: lib/reticulum/src/node/fixture/world.zig:226

zig
/// Three nodes joined by four one-way links, with one clock, the frame queues, the timer copies,/// and the log. The caller initializes this value in place, because each node holds slices that/// point into the world's storage.pub const World = struct {    clock: Seconds = 0,    nodes: [node_count]node.Node = undefined,    links: [4]Link = undefined,    timers: [timers_max]Scheduled = undefined,    timer_count: usize = 0,    deliveries: [deliveries_max]Delivery = undefined,    delivery_count: usize = 0,    log: [records_max]Record = undefined,    record_count: usize = 0,    entropy_count: u64 = 0,    entropy: Entropy = .{},    regions: [node_count]NodeRegion = undefined,    link_regions: [4]LinkRegion = undefined,    pub fn init(self: *World, options: Options) Error!void {        self.clock = options.start;        self.timer_count = 0;        self.delivery_count = 0;        self.record_count = 0;        self.entropy_count = 0;        self.entropy = options.entropy;        for (&self.nodes, &self.regions) |*owner, *region| {            owner.* = try node.Node.init(&region.bytes, limits);            owner.activate();        }        for (&self.links, &self.link_regions) |*link, *region| {            link.* = .{                .queue = try carrier.Memory.init(&region.bytes, link_limits),            };            link.queue.activate();        }        try self.register(options);        std.debug.assert(self.clock == options.start);    }    fn register(self: *World, options: Options) Error!void {        try self.at(.a).registerCarrier(0, true, options.codes.a_b);        try self.at(.b).registerCarrier(0, true, options.codes.a_b);        try self.at(.b).registerCarrier(1, true, options.codes.b_c);        try self.at(.c).registerCarrier(0, true, options.codes.b_c);        self.at(.b).setTransport(options.transport_hash, true);        if (options.discover_paths) |index| try self.at(.b).setPathDiscovery(index, true);    }    pub fn deinit(self: *World) void {        for (&self.links) |*link| _ = link.queue.deinit();        for (&self.nodes) |*owner| _ = owner.deinit();    }    pub fn at(self: *World, id: NodeId) *node.Node {        return &self.nodes[@backingInt(id)];    }    pub fn linkAt(self: *World, id: LinkId) *Link {        return &self.links[@backingInt(id)];    }    /// Applies one caller event to one node at the current second and settles what follows.    pub fn step(self: *World, id: NodeId, value: node.Event) Error!void {        try self.apply(id, try self.at(id).step(value));        try self.settle();    }    /// Runs each second that falls due through the target second, and leaves the clock at the    /// target. A world that has not quieted down after sixty-four rounds returns    /// `error.WorldDidNotSettle`.    pub fn runTo(self: *World, target: Seconds) Error!void {        std.debug.assert(target >= self.clock);        var steps: usize = 0;        while (steps < settle_steps_max) : (steps += 1) {            const due = self.nextDue() orelse break;            if (due > target) break;            self.clock = @max(self.clock, due);            try self.settle();        }        if (steps == settle_steps_max) return error.WorldDidNotSettle;        self.clock = target;    }    pub fn frameCount(self: *const World, id: LinkId) usize {        var count: usize = 0;        for (self.deliveries[0..self.delivery_count]) |delivery| {            if (delivery.link == id) count += 1;        }        return count;    }    pub fn frameOn(self: *const World, id: LinkId, index: usize) ?*const Delivery {        var seen: usize = 0;        for (self.deliveries[0..self.delivery_count]) |*delivery| {            if (delivery.link != id) continue;            if (seen == index) return delivery;            seen += 1;        }        return null;    }    pub fn timerCount(self: *const World, id: NodeId) usize {        std.debug.assert(self.timer_count <= timers_max);        var count: usize = 0;        for (self.timers[0..self.timer_count]) |entry| {            if (entry.owner == id) count += 1;        }        return count;    }    pub fn records(self: *const World) []const Record {        std.debug.assert(self.record_count <= records_max);        return self.log[0..self.record_count];    }    pub fn recordCount(self: *const World, id: NodeId, kind: Kind) usize {        var count: usize = 0;        for (self.records()) |record| {            if (record.owner == id and record.kind == kind) count += 1;        }        return count;    }    pub fn lastRecord(self: *const World, id: NodeId, kind: Kind) ?Record {        var found: ?Record = null;        for (self.records()) |record| {            if (record.owner == id and record.kind == kind) found = record;        }        return found;    }    fn settle(self: *World) Error!void {        var steps: usize = 0;        while (steps < settle_steps_max) : (steps += 1) {            const moved = try self.deliverDue();            const fired = try self.fireDue();            if (!moved and !fired) return;        }        return error.WorldDidNotSettle;    }    fn nextDue(self: *const World) ?Seconds {        var best: ?Seconds = null;        for (&self.links) |*link| {            var offset: usize = 0;            while (offset < link.queue.len) : (offset += 1) {                const slot = (link.queue.start + offset) % frames_max;                best = if (best) |value| @min(value, link.due[slot]) else link.due[slot];            }        }        for (self.timers[0..self.timer_count]) |entry| {            best = if (best) |value| @min(value, entry.at) else entry.at;        }        return best;    }    fn deliverDue(self: *World) Error!bool {        var moved = false;        for (&self.links, 0..) |*link, index| {            var pending = frames_max;            while (pending > 0) : (pending -= 1) {                const offset = dueOffset(link, self.clock) orelse break;                var spins: usize = 0;                while (spins < offset) : (spins += 1) rotate(link);                std.debug.assert(link.queue.len >= 1);                std.debug.assert(link.due[link.queue.start] <= self.clock);                const order = link.order[link.queue.start];                const frame = link.queue.pop() orelse unreachable;                self.keep(@fromBackingInt(@intCast(index)), order, frame);                try self.arrive(@fromBackingInt(@intCast(index)), frame);                moved = true;            }        }        return moved;    }    fn arrive(self: *World, id: LinkId, frame: carrier.Frame) Error!void {        const target = wires[@backingInt(id)];        const effects = try self.at(target.target).step(.{ .carrier_frame = .{            .interface = target.target_carrier,            .now = self.clock,            .bytes = frame.slice(),            .entropy = self.entropyFor(target.target),        } });        try self.apply(target.target, effects);    }    fn fireDue(self: *World) Error!bool {        var chosen: ?usize = null;        for (self.timers[0..self.timer_count], 0..) |entry, index| {            if (entry.at > self.clock) continue;            if (chosen == null or before(entry, self.timers[chosen.?])) chosen = index;        }        const index = chosen orelse return false;        const entry = self.timers[index];        self.timer_count -= 1;        self.timers[index] = self.timers[self.timer_count];        const effects = try self.at(entry.owner).step(.{ .timer_expired = .{            .id = entry.id,            .now = self.clock,            .entropy = self.entropyFor(entry.owner),        } });        try self.apply(entry.owner, effects);        return true;    }    fn entropyFor(self: *World, id: NodeId) [32]u8 {        if (self.entropy.forNode(id)) |fixed| return fixed;        return self.nextEntropy();    }    fn nextEntropy(self: *World) [32]u8 {        var counter: [8]u8 = undefined;        std.mem.writeInt(u64, &counter, self.entropy_count, .little);        self.entropy_count += 1;        var entropy: [32]u8 = undefined;        std.crypto.hash.sha2.Sha256.hash(&counter, &entropy, .{});        return entropy;    }    fn apply(self: *World, id: NodeId, effects: []const node.Effect) Error!void {        self.forget(id);        for (effects) |effect| switch (effect) {            .carrier_send => |send| try self.offer(id, send.interface, send.frame),            .schedule_timer => |scheduled| {                self.schedule(id, scheduled.id, scheduled.at);                self.note(.{                    .at = self.clock,                    .owner = id,                    .kind = .timer,                    .tag = tagOf(scheduled.id),                    .deadline = scheduled.at,                });            },            .application_delivery => |delivery| self.note(delivered(self.clock, id, delivery)),            .announce_received => |announce| self.note(.{                .at = self.clock,                .owner = id,                .kind = .announce,                .key = announce.destination_hash,                .hops = announce.hops,                .path_response = announce.path_response,            }),            .path_request => |request| self.note(.{                .at = self.clock,                .owner = id,                .kind = .path_request,                .interface = request.interface,                .key = request.destination,            }),            .receipt_update => |update| self.note(.{                .at = self.clock,                .owner = id,                .kind = .receipt,                .key = update.packet_hash[0..16].*,                .status = update.status,            }),            .diagnostic => |value| self.note(.{                .at = self.clock,                .owner = id,                .kind = .diagnostic,                .code = value.code,            }),            .link_requested => |requested| self.note(.{                .at = self.clock,                .owner = id,                .kind = .link_requested,                .key = requested.link_id,            }),            .link_established => |established| self.note(.{                .at = self.clock,                .owner = id,                .kind = .link_established,                .interface = established.interface,                .key = established.link_id,                .role = established.role,            }),            .link_delivery => |delivery| self.note(linkDelivered(self.clock, id, delivery)),            .link_closed => |closed| self.note(.{                .at = self.clock,                .owner = id,                .kind = .link_closed,                .key = closed.link_id,                .reason = closed.reason,            }),            .persist => {},        };    }    fn offer(self: *World, id: NodeId, interface: carrier.Index, frame: []const u8) Error!void {        std.debug.assert(frame.len >= 1);        const index = wireOf(id, interface);        const link = &self.links[index];        const ordinal = link.offered;        link.offered += 1;        var due = self.clock;        var blocked = false;        for (link.faults[0..link.fault_count]) |value| switch (value) {            .drop => |lost| blocked = blocked or lost == ordinal,            .delay => |late| if (late.ordinal == ordinal) {                due = self.clock +| late.seconds;            },            .partition => |window| {                const inside = self.clock >= window.from and self.clock <= window.until;                blocked = blocked or inside;            },            .swap => {},        };        if (blocked) {            link.dropped += 1;            return;        }        const slot = (link.queue.start + link.queue.len) % frames_max;        try link.queue.push(try carrier.Frame.init(frame));        link.due[slot] = due;        link.order[slot] = ordinal;        link.place[slot] = ordinal;        swapQueued(link);    }    fn schedule(self: *World, id: NodeId, timer_id: node.TimerId, due: Seconds) void {        std.debug.assert(self.at(id).timers.contains(timer_id));        for (self.timers[0..self.timer_count]) |*entry| {            if (entry.owner != id) continue;            if (!entry.id.eql(timer_id)) continue;            entry.at = due;            return;        }        std.debug.assert(self.timer_count < timers_max);        self.timers[self.timer_count] = .{ .owner = id, .id = timer_id, .at = due };        self.timer_count += 1;        std.debug.assert(self.timerCount(id) <= limits.timers_max);    }    /// Drops the world's copies of the timers that node has dropped, and keeps the rest in order.    /// Cancelling a receipt timer produces no effect that announces it, and a node cancels one on    /// two occasions: a proof concluding the receipt, and a newer receipt culling it. The world    /// makes this call once a node's step returns, holding that step's effects until afterwards, so    /// it spares a timer the step armed.    fn forget(self: *World, id: NodeId) void {        const owner = self.at(id);        var index: usize = 0;        for (0..timers_max) |_| {            if (index == self.timer_count) break;            const entry = self.timers[index];            if (entry.owner == id and !owner.timers.contains(entry.id)) {                std.mem.copyForwards(                    Scheduled,                    self.timers[index .. self.timer_count - 1],                    self.timers[index + 1 .. self.timer_count],                );                self.timer_count -= 1;            } else {                index += 1;            }        }        std.debug.assert(index == self.timer_count);        std.debug.assert(self.timerCount(id) <= owner.timers.count());    }    fn note(self: *World, value: Record) void {        std.debug.assert(self.record_count < records_max);        self.log[self.record_count] = value;        self.record_count += 1;    }    fn keep(self: *World, id: LinkId, ordinal: u32, frame: carrier.Frame) void {        std.debug.assert(self.delivery_count < deliveries_max);        self.deliveries[self.delivery_count] = .{            .at = self.clock,            .link = id,            .ordinal = ordinal,            .frame = frame,        };        self.delivery_count += 1;    }};
Called byCallsNo direct callstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:858-865 loses the link proof and u...test sourcelib.reticulum.src.node.fixture.testtest: fixture holds only the timers i...test sourcelib.reticulum.src.node.fixture.testtest: issue:tiny-6nihz8lx delivers tw...private sourcelib.reticulum.src.node.fixture.world.Worldarriveprivate sourcelib.reticulum.src.node.fixture.world.WorldfireDue+4 morenode.fixture.Worldat
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstiny.pluckevaluatorenumerateIntDistprivate sourcelib.pluck.src.evaluatorcompileFactorprivate sourcelib.pluck.src.evaluatorevaluateThunkUnionprivate sourcelib.pluck.src.evaluatorfinishFactorFromGuardListtiny.pluckevaluatorinferFullDistribution+26 morenode.fixture.Worlddeinit
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1244-1276 relays every link frame ...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1244-1276 relays the same frames b...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1755-1797 batches a second tag and...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:2137-2213 keeps the newer announce...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:3478-3508 forwards one request and...+2 morenode.fixture.WorldframeOn
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.reticulum.src.node.fixture.world.Worldregistertiny.smgtree.Nodeinitnode.fixture.Worldinit
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:744-766 times a partitioned link o...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:540-548 fails the receipt when B c...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1755-1797 batches a second tag and...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:2137-2213 keeps the newer announce...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:3409-3444 answers a lost path with...+2 morenode.fixture.Worldrecordsnode.fixture.WorldlastRecord
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:744-766 times a partitioned link o...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:540-548 fails the receipt when B c...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:2137-2213 keeps the newer announce...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:3409-3444 answers a lost path with...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:858-865 loses the link proof and u...+2 morenode.fixture.WorldlinkAt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:744-766 times a partitioned link o...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1755-1797 batches a second tag and...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:2137-2213 keeps the newer announce...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:3409-3444 answers a lost path with...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:3520-3524 gates at plus 45 and reo...+2 morenode.fixture.Worldrecordsnode.fixture.WorldrecordCount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsnode.fixture.WorldlastRecordnode.fixture.WorldrecordCountnode.fixture.Worldrecords
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:657-683 tears a relayed link down ...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:744-766 times a partitioned link o...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:540-548 fails the receipt when B c...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1244-1276 relays the same frames b...test sourcelib.reticulum.src.node.fixture.test.test_Reti...py:1755-1797 batches a second tag and...+9 moreprivate sourcelib.reticulum.src.node.fixture.world.WorldnextDueprivate sourcelib.reticulum.src.node.fixture.world.Worldsettlenode.fixture.WorldrunTo
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.reticulum.src.node.fixture.world.Worldapplynode.fixture.Worldatprivate sourcelib.reticulum.src.node.fixture.world.Worldsettlenode.fixture.Worldstep
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.reticulum.src.node.fixture.test.test_Reti...py:858-865 loses the link proof and u...test sourcelib.reticulum.src.node.fixture.testtest: fixture holds only the timers i...private sourcelib.reticulum.src.node.fixture.world.Worldforgetprivate sourcelib.reticulum.src.node.fixture.world.Worldschedulenode.fixture.WorldtimerCount
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/reticulum/src/node/fixture/world.zig:58

zig
pub const deliveries_max: usize = 48;

Source: lib/reticulum/src/node/fixture/world.zig:57

zig
pub const faults_max: usize = 4;

Source: lib/reticulum/src/node/fixture/world.zig:56

zig
pub const frames_max: usize = 8;

Source: lib/reticulum/src/node/fixture/world.zig:34

zig
/// The entry maxima each of the world's nodes runs under. Every node holds two carriers, so B sits/// between A and C at the same time.pub const limits = node.Limits{    .interfaces_max = 2,    .destinations_max = 1,    .known_identities_max = 2,    .known_ratchets_max = 1,    .receipts_max = 2,    .duplicate_hashes_max = 32,    .timers_max = 4,    .effects_max = 8,    .effect_frames_max = 4,    .paths_max = 2,    .announces_max = 2,    .reverse_entries_max = 2,    .path_request_tags_max = 8,    .inflight_requests_max = 2,    .discoveries_max = 2,    .links_max = 2,    .link_entries_max = 2,};

Source: lib/reticulum/src/node/fixture/world.zig:59

zig
pub const records_max: usize = 128;

Source: lib/reticulum/src/node/fixture/root.zig

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

Source: lib/reticulum/src/node/root.zig:79

zig
pub const fixture = @import("fixture/root.zig");

Complete caller list for node.fixture.World.at

9 direct callers.

Complete caller list for node.fixture.World.deinit

31 direct callers.

Complete caller list for node.fixture.World.frameOn

7 direct callers.

Complete caller list for node.fixture.World.lastRecord

7 direct callers.

Complete caller list for node.fixture.World.linkAt

7 direct callers.

Complete caller list for node.fixture.World.recordCount

7 direct callers.

Complete caller list for node.fixture.World.runTo

14 direct callers.

Audit

Definitions31
Public names31
Members75
Version26.7.0
Revisiondaab053ee433