/** * BLAKE3 Compression Function - Highly Optimized * * Optimization techniques applied (from Fleek Network case study): * 1. Use 16 SMI variables for state instead of TypedArray * 2. Use 16 SMI variables for message words * 3. Fully inlined G function (no function call overhead) * 4. Use `| 0` for integer coercion (forces V8 to use 32-bit ALU) * 5. Hardcoded permutation swaps using only 2 temporary variables * 6. Offset-based access pattern (avoid creating new views) * * The compression function takes: * - cv: 8-word chaining value * - block: 16-word message block (64 bytes) * - counter: 64-bit block counter * - blockLen: number of input bytes in this block * - flags: domain separation flags * * And outputs 8 or 16 words depending on whether this is a root node. */ /** * Compress a single block. * * This is the hot path - every optimization matters here. * * @param cv - Chaining value array * @param cvOff - Offset into cv * @param block - Message block words * @param blockOff - Offset into block * @param out - Output array (8 or 16 words) * @param outOff - Offset into out * @param full - If true, output all 16 words (for XOF); if false, output 8 words * @param counter - 64-bit block counter * @param blockLen - Number of bytes in this block (0-64) * @param flags - Domain separation flags */ export function compress( cv: Uint32Array, cvOff: number, block: Uint32Array, blockOff: number, out: Uint32Array, outOff: number, full: boolean, counter: number, blockLen: number, flags: number, ): void { // Load message words into SMI variables for maximum performance // V8 optimizes SMI arithmetic directly with the ALU let m0 = block[blockOff] | 0; let m1 = block[blockOff + 1] | 0; let m2 = block[blockOff + 2] | 0; let m3 = block[blockOff + 3] | 0; let m4 = block[blockOff + 4] | 0; let m5 = block[blockOff + 5] | 0; let m6 = block[blockOff + 6] | 0; let m7 = block[blockOff + 7] | 0; let m8 = block[blockOff + 8] | 0; let m9 = block[blockOff + 9] | 0; let m10 = block[blockOff + 10] | 0; let m11 = block[blockOff + 11] | 0; let m12 = block[blockOff + 12] | 0; let m13 = block[blockOff + 13] | 0; let m14 = block[blockOff + 14] | 0; let m15 = block[blockOff + 15] | 0; // Initialize state: first 8 words from chaining value let s0 = cv[cvOff] | 0; let s1 = cv[cvOff + 1] | 0; let s2 = cv[cvOff + 2] | 0; let s3 = cv[cvOff + 3] | 0; let s4 = cv[cvOff + 4] | 0; let s5 = cv[cvOff + 5] | 0; let s6 = cv[cvOff + 6] | 0; let s7 = cv[cvOff + 7] | 0; // Words 8-11: IV constants let s8 = 0x6a09e667; let s9 = 0xbb67ae85; let s10 = 0x3c6ef372; let s11 = 0xa54ff53a; // Words 12-15: counter, blockLen, flags // Note: counter is 64-bit, split into low and high 32-bit words let s12 = counter | 0; let s13 = (counter / 0x100000000) | 0; let s14 = blockLen | 0; let s15 = flags | 0; // ============================================================ // 7 rounds of mixing // Each round consists of 4 column G functions and 4 diagonal G functions // followed by a message word permutation (except for round 7) // ============================================================ // ROUND 1 (message schedule: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) // Column G functions // G(0, 4, 8, 12) with m0, m1 s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); // G(1, 5, 9, 13) with m2, m3 s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); // G(2, 6, 10, 14) with m4, m5 s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); // G(3, 7, 11, 15) with m6, m7 s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); // Diagonal G functions // G(0, 5, 10, 15) with m8, m9 s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); // G(1, 6, 11, 12) with m10, m11 s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); // G(2, 7, 8, 13) with m12, m13 s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); // G(3, 4, 9, 14) with m14, m15 s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute message words for round 2 // Permutation: [2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8] // Using 2 temps for the two cycles in the permutation { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 2 (message schedule: 2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute for round 3 { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 3 (message schedule: 3,4,10,12,13,2,7,14,6,5,9,0,11,15,8,1) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute for round 4 { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 4 (message schedule: 10,7,12,9,14,3,13,15,4,0,11,2,5,8,1,6) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute for round 5 { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 5 (message schedule: 12,13,9,11,15,10,14,8,7,2,5,3,0,1,6,4) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute for round 6 { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 6 (message schedule: 9,14,11,5,8,12,15,1,13,3,0,10,2,6,4,7) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // Permute for round 7 { const t0 = m0, t1 = m1; m0 = m2; m2 = m3; m3 = m10; m10 = m12; m12 = m9; m9 = m11; m11 = m5; m5 = t0; m1 = m6; m6 = m4; m4 = m7; m7 = m13; m13 = m14; m14 = m15; m15 = m8; m8 = t1; } // ROUND 7 (message schedule: 11,15,5,0,1,9,8,6,14,10,2,12,3,4,7,13) s0 = (((s0 + s4) | 0) + m0) | 0; s12 ^= s0; s12 = (s12 >>> 16) | (s12 << 16); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 12) | (s4 << 20); s0 = (((s0 + s4) | 0) + m1) | 0; s12 ^= s0; s12 = (s12 >>> 8) | (s12 << 24); s8 = (s8 + s12) | 0; s4 ^= s8; s4 = (s4 >>> 7) | (s4 << 25); s1 = (((s1 + s5) | 0) + m2) | 0; s13 ^= s1; s13 = (s13 >>> 16) | (s13 << 16); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 12) | (s5 << 20); s1 = (((s1 + s5) | 0) + m3) | 0; s13 ^= s1; s13 = (s13 >>> 8) | (s13 << 24); s9 = (s9 + s13) | 0; s5 ^= s9; s5 = (s5 >>> 7) | (s5 << 25); s2 = (((s2 + s6) | 0) + m4) | 0; s14 ^= s2; s14 = (s14 >>> 16) | (s14 << 16); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 12) | (s6 << 20); s2 = (((s2 + s6) | 0) + m5) | 0; s14 ^= s2; s14 = (s14 >>> 8) | (s14 << 24); s10 = (s10 + s14) | 0; s6 ^= s10; s6 = (s6 >>> 7) | (s6 << 25); s3 = (((s3 + s7) | 0) + m6) | 0; s15 ^= s3; s15 = (s15 >>> 16) | (s15 << 16); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 12) | (s7 << 20); s3 = (((s3 + s7) | 0) + m7) | 0; s15 ^= s3; s15 = (s15 >>> 8) | (s15 << 24); s11 = (s11 + s15) | 0; s7 ^= s11; s7 = (s7 >>> 7) | (s7 << 25); s0 = (((s0 + s5) | 0) + m8) | 0; s15 ^= s0; s15 = (s15 >>> 16) | (s15 << 16); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 12) | (s5 << 20); s0 = (((s0 + s5) | 0) + m9) | 0; s15 ^= s0; s15 = (s15 >>> 8) | (s15 << 24); s10 = (s10 + s15) | 0; s5 ^= s10; s5 = (s5 >>> 7) | (s5 << 25); s1 = (((s1 + s6) | 0) + m10) | 0; s12 ^= s1; s12 = (s12 >>> 16) | (s12 << 16); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 12) | (s6 << 20); s1 = (((s1 + s6) | 0) + m11) | 0; s12 ^= s1; s12 = (s12 >>> 8) | (s12 << 24); s11 = (s11 + s12) | 0; s6 ^= s11; s6 = (s6 >>> 7) | (s6 << 25); s2 = (((s2 + s7) | 0) + m12) | 0; s13 ^= s2; s13 = (s13 >>> 16) | (s13 << 16); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 12) | (s7 << 20); s2 = (((s2 + s7) | 0) + m13) | 0; s13 ^= s2; s13 = (s13 >>> 8) | (s13 << 24); s8 = (s8 + s13) | 0; s7 ^= s8; s7 = (s7 >>> 7) | (s7 << 25); s3 = (((s3 + s4) | 0) + m14) | 0; s14 ^= s3; s14 = (s14 >>> 16) | (s14 << 16); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 12) | (s4 << 20); s3 = (((s3 + s4) | 0) + m15) | 0; s14 ^= s3; s14 = (s14 >>> 8) | (s14 << 24); s9 = (s9 + s14) | 0; s4 ^= s9; s4 = (s4 >>> 7) | (s4 << 25); // ============================================================ // Final XOR and output // ============================================================ // If full output needed (XOF mode), write words 8-15 first // (written first in case out === cv) if (full) { out[outOff + 8] = s8 ^ cv[cvOff]; out[outOff + 9] = s9 ^ cv[cvOff + 1]; out[outOff + 10] = s10 ^ cv[cvOff + 2]; out[outOff + 11] = s11 ^ cv[cvOff + 3]; out[outOff + 12] = s12 ^ cv[cvOff + 4]; out[outOff + 13] = s13 ^ cv[cvOff + 5]; out[outOff + 14] = s14 ^ cv[cvOff + 6]; out[outOff + 15] = s15 ^ cv[cvOff + 7]; } // Standard output: XOR state[0..7] with state[8..15] out[outOff] = s0 ^ s8; out[outOff + 1] = s1 ^ s9; out[outOff + 2] = s2 ^ s10; out[outOff + 3] = s3 ^ s11; out[outOff + 4] = s4 ^ s12; out[outOff + 5] = s5 ^ s13; out[outOff + 6] = s6 ^ s14; out[outOff + 7] = s7 ^ s15; }