lib/reticulum/src/properties/announce.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const hypothesis = @import("hypothesis");
3 const reticulum = @import("reticulum");
4
5 const announce = reticulum.destination.announce;
6 const identity = reticulum.identity;
7 const seed: u64 = 0x5245_5449_4355_4c55;
8
9 const Rebuild = struct {
10 pub fn property(data: *hypothesis.ConjectureData, _: std.mem.Allocator) !void {
11 const key_input = try data.drawBytes(identity.key_bytes, identity.key_bytes);
12 const name_input = try data.drawBytes(10, 10);
13 const random_input = try data.drawBytes(10, 10);
14 const rotating_input = try data.drawBytes(32, 32);
15 const use_rotating = try data.drawInteger(0, 1, 0) == 1;
16 const app_length: usize = @intCast(try data.drawInteger(0, 128, 0));
17 const app_data = try data.drawBytes(app_length, app_length);
18 var private = identity.Private.fromBytes(key_input[0..identity.key_bytes].*);
19 defer private.zero();
20
21 const name_hash = name_input[0..10].*;
22 var destination_hasher = reticulum.hash.Hasher.init();
23 destination_hasher.update(&name_hash);
24 destination_hasher.update(&private.hash());
25 const destination_hash = destination_hasher.finalTruncated();
26 var output: [announce.payload_bytes_max]u8 = undefined;
27 const payload = try announce.build(.{
28 .destination_hash = destination_hash,
29 .name_hash = name_hash,
30 .random_hash = random_input[0..10].*,
31 .rotating_public_key = if (use_rotating) rotating_input[0..32].* else null,
32 .app_data = app_data,
33 }, &private, &output);
34 const context_flag: u1 = if (use_rotating) 1 else 0;
35 const decoded = try announce.validate(destination_hash, .one, context_flag, payload);
36 try std.testing.expectEqualSlices(u8, app_data, decoded.app_data);
37 }
38 };
39
40 const Total = struct {
41 pub fn property(data: *hypothesis.ConjectureData, _: std.mem.Allocator) !void {
42 const payload_length: usize = @intCast(try data.drawInteger(0, 500, 0));
43 const payload = try data.drawBytes(payload_length, payload_length);
44 const hash_input = try data.drawBytes(16, 16);
45 const context_flag: u1 = @intCast(try data.drawInteger(0, 1, 0));
46 const header: reticulum.wire.HeaderType = if (try data.drawBoolean()) .two else .one;
47 const hash = hash_input[0..16].*;
48 if (announce.validate(hash, header, context_flag, payload)) |_| {} else |_| {}
49 }
50 };
51
52 fn settings() hypothesis.Settings {
53 return hypothesis.Settings.quick()
54 .withSeed(seed)
55 .withDatabase("zig-out/hypothesis-failures/reticulum");
56 }
57
58 test "property: Reticulum@1.5.0 rebuilt announces validate" {
59 try hypothesis.checkNamed(Rebuild, "reticulum-announce-rebuild", settings());
60 }
61
62 test "property: Reticulum@1.5.0 announce validation is total" {
63 try hypothesis.checkNamed(Total, "reticulum-announce-total", settings());
64 }