code wiki / (root) / nx_u256_mul4_fuzz.nx

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}