Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"built_by": "t27c-bootstrap@0.5.2+01d0a635f",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:5d163c948bcbd1bf56d800662594f481fcfb25c3b88fab43b58b185a21ae5f67",
"gen_hash_rust": "sha256:0431e36cfd9545d88a4cae54f41ec5781b314195ab9a3e5f4bddd7c16c09452d",
"gen_hash_verilog": "sha256:7d21d6225202df08c904c41746d605beade8fab25cbc04687146efcb3b12a28e",
"gen_hash_zig": "sha256:5e22547ca28a10b4eb0b16eb09385d6db7b59bf2cbf107384192a8ae6b47f67f",
"module": "port::trios::crates::trios-chat::rings::CR-CHAT-07::src::cover_traffic_replay_detection_guard",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-17T03:02:40Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:5f8bdbea4ad59f4e450b604c20ee40c98ad8bc78b1c192f33ff01acce365f695",
"spec_path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_replay_detection_guard.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 12,
"total": 12,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"zig": "0.16.0"
}
}
1 change: 1 addition & 0 deletions docs/reports/t27b_expectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,7 @@
{"path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-03/src/unmerged_leaves_bound_guard.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-05/src/envelope_size_distribution_uniformity.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_decoy_ratio_governor.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_replay_detection_guard.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-chat/rings/CR-CHAT-LAWS/src/lib.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-cli/src/cmd/agent.t27", "t27b": "pass"},
{"path": "specs/port/trios/crates/trios-cli/src/cmd/commit.t27", "t27b": "pass"},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
module port::trios::crates::trios-chat::rings::CR-CHAT-07::src::cover_traffic_replay_detection_guard;

// Port of gHashTag/trios crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_replay_detection_guard.rs
// (CR-CHAT-07 - Cover traffic replay detection guard, Wave-113
// Lane A, R-CHAT-10).
//
// Cover patterns must not repeat: a repeating pattern hands the
// adversary a database match that names cover epochs, patterns
// that repeat against no known schedule flag as real, and
// cross-window matches reveal the schedule's period. The
// rules, in the original's order: the batch ceiling, then per
// window the zero-index probe, the zero-hash probe, the
// emission floor, the strictly-increasing index and the
// repeated-hash scan.
//
// The original returns Result<(), CoverReplayError>. This port
// carries the verdict as a named struct (owner decision D5): Ok
// first, then the six variants in the original's declaration
// order - DuplicatePattern, NotIncreasing, ZeroIndex, ZeroHash,
// BelowMin, TooMany - with every payload field: idx for the
// zero and duplicate rules, idx with prev and current for the
// monotonic break, idx with count and min for the floor, and
// got with max for the ceiling.
//
// The BTreeSet dedup becomes a scan over the windows already
// visited; the hashes stay the fixed [32]u8 form.

// Minimum emissions per window.
pub const CTRD_MIN_EMISSIONS: usize = 10;

// Maximum windows per batch.
pub const CTRD_MAX_WINDOWS: usize = 256;

// Pattern hash length.
pub const CTRD_HASH_LEN: usize = 32;

// A cover traffic window pattern.
pub struct CoverWindow {
index: u64,
pattern_hash: [32]u8,
emission_count: usize,
}

// Verdict codes: Ok(()) and CoverReplayError's variants, in declaration order.
pub enum CoverReplayCode {
Ok,
DuplicatePattern,
NotIncreasing,
ZeroIndex,
ZeroHash,
BelowMin,
TooMany,
}

// The verdict of the replay validation, with every error payload
// field.
pub struct CoverReplayVerdict {
code: CoverReplayCode,
idx: usize,
got: usize,
bound: usize,
prev: u64,
current: u64,
}

// Whole-form equality over the fixed thirty-two hash bytes.
pub fn hashes_equal(a: [32]u8, b: [32]u8) -> bool {
for i in 0..32 {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

// The all-zero hash - the original's [0u8; 32] probe.
pub fn hash_zero(h: [32]u8) -> bool {
for i in 0..32 {
if (h[i] != 0) {
return false;
}
}
return true;
}

// Whether window i repeats an earlier hash - the original's
// BTreeSet insert probe, answered by a scan.
pub fn hash_seen_before(windows: []const CoverWindow, i: usize) -> bool {
for j in 0..i {
if (hashes_equal(windows[j].pattern_hash, windows[i].pattern_hash)) {
return true;
}
}
return false;
}

// [VERIFIED] Validate cover traffic replay detection. Returns
// Ok only when every rule holds, checked in the original's
// order: the batch ceiling, then per window the zero index,
// the zero hash, the emission floor, the strictly-increasing
// index and the repeated hash.
pub fn validate_cover_replay(windows: []const CoverWindow) -> CoverReplayVerdict {
if (windows.len > CTRD_MAX_WINDOWS) {
return CoverReplayVerdict { code: CoverReplayCode.TooMany, idx: 0, got: windows.len, bound: CTRD_MAX_WINDOWS, prev: 0, current: 0, };
}
var prev: u64 = 0;
for i in 0..windows.len {
if (windows[i].index == 0) {
return CoverReplayVerdict { code: CoverReplayCode.ZeroIndex, idx: i, got: 0, bound: 0, prev: 0, current: 0, };
}
if (hash_zero(windows[i].pattern_hash)) {
return CoverReplayVerdict { code: CoverReplayCode.ZeroHash, idx: i, got: 0, bound: 0, prev: 0, current: 0, };
}
if (windows[i].emission_count < CTRD_MIN_EMISSIONS) {
return CoverReplayVerdict { code: CoverReplayCode.BelowMin, idx: i, got: windows[i].emission_count, bound: CTRD_MIN_EMISSIONS, prev: 0, current: 0, };
}
if (i > 0) {
if (windows[i].index <= prev) {
return CoverReplayVerdict { code: CoverReplayCode.NotIncreasing, idx: i, got: 0, bound: 0, prev: prev, current: windows[i].index, };
}
}
if (hash_seen_before(windows, i)) {
return CoverReplayVerdict { code: CoverReplayCode.DuplicatePattern, idx: i, got: 0, bound: 0, prev: 0, current: 0, };
}
prev = windows[i].index;
}
return CoverReplayVerdict { code: CoverReplayCode.Ok, idx: 0, got: 0, bound: 0, prev: 0, current: 0, };
}

// The pattern hashes of the fixtures, one byte repeated
// thirty-two times - the original's hash(byte) helper, entry by
// entry.
pub const HASH_01: [32]u8 = [32]u8{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,};
pub const HASH_02: [32]u8 = [32]u8{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,};
pub const HASH_03: [32]u8 = [32]u8{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,};
pub const HASH_AA: [32]u8 = [32]u8{170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,};
pub const ZERO_HASH32: [32]u8 = [32]u8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};

// The leading hash bytes of the too-many fixture: the
// original's (i as u8).wrapping_add(1) walk over 0..=256.
pub const CTRD_FLOOD_257: [257]u8 = [257]u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 1};

// **CTRD-01** - a duplicate pattern rejected: the second window
// repeats the first's hash.
test ctrd_01_duplicate_rejected {
const ws: [2]CoverWindow = [2]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_AA, emission_count: 20, },
CoverWindow { index: 2, pattern_hash: HASH_AA, emission_count: 25, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.DuplicatePattern);
assert(v.idx == 1);
}

// **CTRD-02** - a non-increasing index rejected: three after
// five.
test ctrd_02_not_increasing_rejected {
const ws: [2]CoverWindow = [2]CoverWindow{
CoverWindow { index: 5, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 3, pattern_hash: HASH_02, emission_count: 20, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.NotIncreasing);
assert(v.idx == 1);
assert(v.prev == 5);
assert(v.current == 3);
}

// **CTRD-03** - the zero index rejected.
test ctrd_03_zero_index_rejected {
const ws: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 0, pattern_hash: HASH_01, emission_count: 20, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.ZeroIndex);
assert(v.idx == 0);
}

// **CTRD-04** - the zero hash rejected.
test ctrd_04_zero_hash_rejected {
const ws: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 1, pattern_hash: ZERO_HASH32, emission_count: 20, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.ZeroHash);
assert(v.idx == 0);
}

// **CTRD-05** - below the emission floor rejected: five of a
// required ten.
test ctrd_05_below_min_rejected {
const ws: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_01, emission_count: 5, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.BelowMin);
assert(v.idx == 0);
assert(v.got == 5);
assert(v.bound == 10);
}

// **CTRD-06** - too many rejected: 257 windows of a maximum 256,
// built in a loop like the original's, the indexes walking one
// upward and the hashes carrying the wrapped walk bytes. The
// batch rule fires before any window is examined.
test ctrd_06_too_many_rejected {
var ws: [257]CoverWindow;
for i in 0..257 {
var h: [32]u8 = [32]u8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
h[0] = CTRD_FLOOD_257[i];
ws[i] = CoverWindow { index: @as(u64, i) + 1, pattern_hash: h, emission_count: 20, };
}
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.TooMany);
assert(v.got == 257);
assert(v.bound == 256);
}

// **CTRD-07** - the valid batch accepted: three windows, three
// hashes.
test ctrd_07_valid_accepted {
const ws: [3]CoverWindow = [3]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 2, pattern_hash: HASH_02, emission_count: 25, },
CoverWindow { index: 3, pattern_hash: HASH_03, emission_count: 22, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.Ok);
}

// **CTRD-08** - an empty batch accepted.
test ctrd_08_empty_accepted {
const ws: [0]CoverWindow = [0]CoverWindow{};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.Ok);
}

// **CTRD-09** - a single window accepted.
test ctrd_09_single_accepted {
const ws: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_01, emission_count: 20, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.Ok);
}

// **CTRD-10** - the boundary emission count accepted: exactly
// ten.
test ctrd_10_boundary_accepted {
const ws: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_01, emission_count: 10, },
};
const v = validate_cover_replay(&ws);
assert(v.code == CoverReplayCode.Ok);
}

// The three helpers have direct tests (coverage: Untested 0).
test ctrd_helpers_answer {
assert(hashes_equal(HASH_01, HASH_01));
assert(!hashes_equal(HASH_01, HASH_02));
assert(hash_zero(ZERO_HASH32));
assert(!hash_zero(HASH_01));
const three: [3]CoverWindow = [3]CoverWindow{
CoverWindow { index: 1, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 2, pattern_hash: HASH_02, emission_count: 20, },
CoverWindow { index: 3, pattern_hash: HASH_01, emission_count: 20, },
};
assert(!hash_seen_before(&three, 0));
assert(!hash_seen_before(&three, 1));
assert(hash_seen_before(&three, 2));
}

// Rule order is the original's: the zero index before the zero
// hash, the zero hash before the emission floor, the floor
// before the monotonicity, and the monotonicity before the
// repeated hash - with both violations on one window.
test rule_order_matches_original {
const zero_both: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 0, pattern_hash: ZERO_HASH32, emission_count: 5, },
};
const v1 = validate_cover_replay(&zero_both);
assert(v1.code == CoverReplayCode.ZeroIndex);
assert(v1.idx == 0);

const zero_hash_few: [1]CoverWindow = [1]CoverWindow{
CoverWindow { index: 1, pattern_hash: ZERO_HASH32, emission_count: 5, },
};
const v2 = validate_cover_replay(&zero_hash_few);
assert(v2.code == CoverReplayCode.ZeroHash);
assert(v2.idx == 0);

const few_backstep: [2]CoverWindow = [2]CoverWindow{
CoverWindow { index: 5, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 3, pattern_hash: HASH_02, emission_count: 5, },
};
const v3 = validate_cover_replay(&few_backstep);
assert(v3.code == CoverReplayCode.BelowMin);
assert(v3.idx == 1);

const backstep_dup: [2]CoverWindow = [2]CoverWindow{
CoverWindow { index: 5, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 3, pattern_hash: HASH_01, emission_count: 20, },
};
const v4 = validate_cover_replay(&backstep_dup);
assert(v4.code == CoverReplayCode.NotIncreasing);
assert(v4.idx == 1);

const dup_only: [2]CoverWindow = [2]CoverWindow{
CoverWindow { index: 5, pattern_hash: HASH_01, emission_count: 20, },
CoverWindow { index: 6, pattern_hash: HASH_01, emission_count: 20, },
};
const v5 = validate_cover_replay(&dup_only);
assert(v5.code == CoverReplayCode.DuplicatePattern);
assert(v5.idx == 1);
}
Loading