Skip to documentation
SLOP

tiny.reticulum.destination.registry

Reference tiny.reticulum destination registry

Defined in destination.

API (17)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Called byCallsNo direct callstest sourcelib.reticulum.src.destination.registrytest: destinations admit maximum and ...test sourcelib.reticulum.src.destination.registrytest: destinations reject duplicate r...node.Nodeactivatedestination.registry.Tableactivate
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.reticulum.src.destination.registrytest: destinations admit maximum and ...test sourcelib.reticulum.src.destination.registrytest: destinations reject duplicate r...destination.registry.Tablecount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.reticulum.src.destination.registrytest: destinations admit maximum and ...test sourcelib.reticulum.src.destination.registrytest: destinations reject duplicate r...node.Nodedeinitdestination.registry.Tabledeinit
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsdestination.registry.Tableregisterdestination.registry.Tablefind
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.reticulum.src.destination.registrytest: destinations admit maximum and ...test sourcelib.reticulum.src.destination.registrytest: destinations reject duplicate r...private sourcelib.reticulum.src.node.ownerinitSubownersdestination.registry.Tableinit
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallstest sourcelib.reticulum.src.destination.registrytest: destinations admit maximum and ...test sourcelib.reticulum.src.destination.registrytest: destinations reject duplicate r...destination.registry.Tablefinddestination.registry.Tableregister
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/reticulum/src/destination/registry.zig

zig
const std = @import("std");const alloc_phase = @import("alloc_phase");const destination = @import("root.zig");/// The choice of what a registered destination does with a packet delivered to/// it: prove nothing, hand the decision to the application, or prove it at/// once, so a caller can say what the node does with the packet, following/// Reticulum@1.5.0 RNS/Destination.py:69-71.pub const ProofStrategy = enum(u8) {    none = 0x21,    app = 0x22,    all = 0x23,};/// The entry a caller fills in to register a destination the node will answer/// for: the 16-byte address, the announced name hash, the kind of destination,/// the proof strategy, which of the node's private identities signs for it, and/// a group key. A group destination shares one 64-byte key, which its members/// use as a token key directly, following Reticulum@1.5.0/// RNS/Destination.py:544-558 and Reticulum@1.5.0/// RNS/Cryptography/Token.py:53-55.pub const Entry = struct {    hash: [16]u8,    /// The ten bytes an announce publishes for this destination's dotted name,    /// set so the node can announce the destination under the right published    /// name and worked out separately from the address, following    /// Reticulum@1.5.0 RNS/Destination.py:188-190.    name_hash: [10]u8 = @splat(0),    kind: destination.Type,    proof_strategy: ProofStrategy,    identity_index: ?usize = null,    group_key: [64]u8 = @splat(0),};const TableLimits = struct {    destinations_max: usize,};const TableCapacity = struct {    destinations_max: usize,    storage_bytes: usize,    pub const DeriveError = error{ InvalidLimit, CapacityOverflow };    pub fn derive(limits: TableLimits) DeriveError!TableCapacity {        if (limits.destinations_max == 0) return error.InvalidLimit;        const destinations_max = limits.destinations_max;        const storage_bytes = alloc_phase.capacity.mul(            usize,            destinations_max,            @sizeOf(Entry),        ) catch return error.CapacityOverflow;        return .{ .destinations_max = destinations_max, .storage_bytes = storage_bytes };    }};/// The bounded list of destinations one node answers for, for a caller that/// hands the node one block of storage and gets it back at teardown, following/// Reticulum@1.5.0 RNS/Transport.py:2834-2845. The caller fixes how many/// destinations the list holds, and the storage it hands over has to equal the/// byte count derived from that number, or registration returns/// `error.StorageLengthMismatch`. Registering an address the list already holds/// returns `error.Duplicate`, and registering into a full list returns/// `error.Full`, both before the list changes. Looking a destination up scans/// the list, so a lookup costs one pass over it.pub const Table = struct {    phase: alloc_phase.capacity.Phase,    capacity: Capacity,    storage: Storage,    entries: []Entry,    len: usize = 0,    pub const storage_alignment: usize = 8;    pub const Storage = []align(storage_alignment) u8;    pub const Limits: type = TableLimits;    pub const Capacity: type = TableCapacity;    pub const Exhaustion = error{ Full, Duplicate };    pub const InitError = Capacity.DeriveError || error{StorageLengthMismatch};    pub const work_limits: alloc_phase.capacity.WorkLimits = .{        .transition_steps_max = 65_536,        .cleanup_steps_per_call_max = 0,        .cleanup_calls_at_capacity_max = 0,    };    pub const claim: alloc_phase.capacity.Declaration = .{        .source = .{            .id = "reticulum.destinations",            .kind = .phase_static,            .limit_source = .caller,            .storage = .{                .covered = &.{.{                    .id = "caller_local_destination_table",                    .lifetime = .transferred,                    .detail = "caller storage for registered local destinations",                }},                .excluded = &.{                    "private identity storage selected by identity indexes",                    "application handlers and persistence effects",                },            },            .capacity = .{                .inputs = &.{alloc_phase.capacity.bindInput(                    Limits,                    "destinations_max",                    "destinations_max",                )},                .type_selectors = &.{alloc_phase.capacity.bindType(Entry, "destination")},                .nodes = &.{                    .{ .input = 0 },                    .{ .scale = .{                        .node = 0,                        .coefficient = .{ .size_of_concrete_type = 0 },                    } },                },                .assertions = &.{.{                    .scope = .closure_total,                    .measure = .retained,                    .relation = .exact,                    .expression = 1,                }},            },            .overload = .{                .kind = .reject_before_mutation,                .detail = "duplicate and full registration preserve the table",            },            .risks = .{                .transitive = .{                    .status = .excluded,                    .detail = "destination registration calls no allocating owner",                },                .foreign = .{                    .status = .excluded,                    .detail = "destination registration crosses no foreign boundary",                },            },            .work = .{ .equation = "registration scans at most destinations_max entries" },            .obligations = &.{                .{ .key = "reticulum_destinations_capacity", .role = .capacity_model },                .{ .key = "reticulum_destinations_overload", .role = .overload },                .{ .key = "reticulum_destinations_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!Table {        const capacity = try Capacity.derive(limits);        if (storage.len != capacity.storage_bytes) return error.StorageLengthMismatch;        return .{            .phase = .initialization,            .capacity = capacity,            .storage = storage,            .entries = std.mem.bytesAsSlice(Entry, storage),        };    }    pub fn activate(self: *Table) void {        std.debug.assert(self.phase == .initialization);        std.debug.assert(self.len == 0);        self.phase = .steady;    }    pub fn register(self: *Table, entry: Entry) Exhaustion!void {        std.debug.assert(self.phase == .steady);        if (self.find(entry.hash) != null) return error.Duplicate;        if (self.len == self.capacity.destinations_max) return error.Full;        self.entries[self.len] = entry;        self.len += 1;    }    pub fn find(self: *const Table, hash: [16]u8) ?*const Entry {        std.debug.assert(self.phase == .steady);        for (self.entries[0..self.len]) |*entry| {            if (std.mem.eql(u8, &entry.hash, &hash)) return entry;        }        return null;    }    pub fn count(self: *const Table) usize {        std.debug.assert(self.phase == .steady);        return self.len;    }    pub fn deinit(self: *Table) Storage {        std.debug.assert(self.phase == .steady);        self.phase = .teardown;        const storage = self.storage;        self.* = undefined;        return storage;    }};comptime {    alloc_phase.capacity.requireProvisionedRejectingOwnerShape(Table);}fn testEntry(value: u8) Entry {    return .{        .hash = @splat(value),        .kind = .single,        .proof_strategy = .all,        .identity_index = value,    };}test "destinations admit maximum and reject maximum plus one" {    comptime {        @stardustClaim(alloc_phase.capacity.witness(            Table,            "reticulum_destinations_capacity",        ), null, null, null, null, null, null);        @stardustClaim(alloc_phase.capacity.witness(            Table,            "reticulum_destinations_overload",        ), null, null, null, null, null, null);        @stardustClaim(alloc_phase.capacity.witness(            Table,            "reticulum_destinations_work",        ), null, null, null, null, null, null);    }    const capacity = comptime TableCapacity.derive(.{ .destinations_max = 3 }) catch unreachable;    var bytes: [capacity.storage_bytes]u8 align(Table.storage_alignment) = undefined;    var table = try Table.init(&bytes, .{ .destinations_max = 3 });    table.activate();    defer _ = table.deinit();    for (1..4) |value| try table.register(testEntry(@intCast(value)));    try std.testing.expectError(error.Full, table.register(testEntry(4)));    try std.testing.expectEqual(@as(usize, 3), table.count());}test "destinations reject duplicate registration without mutation" {    const capacity = comptime TableCapacity.derive(.{ .destinations_max = 3 }) catch unreachable;    var bytes: [capacity.storage_bytes]u8 align(Table.storage_alignment) = undefined;    var table = try Table.init(&bytes, .{ .destinations_max = 3 });    table.activate();    defer _ = table.deinit();    try table.register(testEntry(1));    try std.testing.expectError(error.Duplicate, table.register(testEntry(1)));    try std.testing.expectEqual(@as(usize, 1), table.count());}

Source: lib/reticulum/src/destination/root.zig:59

zig
pub const registry = @import("registry.zig");

Audit

Definitions18
Public names18
Members16
Version26.7.0
Revisiondaab053ee433