nx_u256_mul4_fuzz.nx source
↩ module page · 63 lines · 2223 B
1// nx_u256_mul4_fuzz.nx -- differential fuzz: the G2 4x64 multiply
2// (u256_mul_wide_4x64, using __umulhi64) MUST be byte-exact vs the proven 8x32
3// schoolbook oracle (u256_mul_wide) for every input. Catches any software-carry
4// bug in the 128-bit accumulation. exit 0 = all matched; nonzero encodes where.
5// Must be compiled by a G2-capable compiler (knows __umulhi64). license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_u256.nx"
9import "nx_u256_mul.nx"
10const K_MAGIC_4000: i64 = 4000
11const K_MAGIC_6364136223846793005: i64 = 6364136223846793005
12const K_MAGIC_1442695040888963407: i64 = 1442695040888963407
13const K_MAGIC_1000000: i64 = 1000000
14
15func main() -> i64 {
16 let _s: i64 = nx_scratch_save()
17 let a: *i64 = u256_alloc()
18 let b: *i64 = u256_alloc()
19 let o1: *i64 = u256_wide_alloc() // oracle (8x32)
20 let o2: *i64 = u256_wide_alloc() // 4x64
21
22 // LCG (Knuth) kept 63-bit POSITIVE so `>>` is unambiguous; high bits well-mixed.
23 var st: i64 = 0x2545F4914F6CDD1D & 0x7FFFFFFFFFFFFFFF
24 var n: i64 = 0
25 while n < K_MAGIC_4000 {
26 var i: i64 = 0
27 while i < 8 {
28 st = (st * K_MAGIC_6364136223846793005 + K_MAGIC_1442695040888963407) & 0x7FFFFFFFFFFFFFFF
29 a[i] = (st >> 20) & 0xFFFFFFFF
30 st = (st * K_MAGIC_6364136223846793005 + K_MAGIC_1442695040888963407) & 0x7FFFFFFFFFFFFFFF
31 b[i] = (st >> 20) & 0xFFFFFFFF
32 i = i + 1
33 }
34 u256_mul_wide(o1, a, b)
35 u256_mul_wide_4x64(o2, a, b)
36 var k: i64 = 0
37 while k < 16 {
38 if (o1[k] & 0xFFFFFFFF) != (o2[k] & 0xFFFFFFFF) {
39 nx_scratch_restore(_s)
40 return n * 16 + k + 1
41 }
42 k = k + 1
43 }
44 n = n + 1
45 }
46
47 // Edge case: all-limbs-max (maximises carries).
48 var e: i64 = 0
49 while e < 8 { a[e] = 0xFFFFFFFF; b[e] = 0xFFFFFFFF; e = e + 1 }
50 u256_mul_wide(o1, a, b)
51 u256_mul_wide_4x64(o2, a, b)
52 var k2: i64 = 0
53 while k2 < 16 {
54 if (o1[k2] & 0xFFFFFFFF) != (o2[k2] & 0xFFFFFFFF) {
55 nx_scratch_restore(_s)
56 return K_MAGIC_1000000 + k2
57 }
58 k2 = k2 + 1
59 }
60
61 nx_scratch_restore(_s)
62 return 0
63}