]> git.codecow.com Git - nano25519.git/commitdiff
Pointers, vectors, and doubling.
authorChris Duncan <chris@zoso.dev>
Fri, 27 Feb 2026 08:03:35 +0000 (00:03 -0800)
committerChris Duncan <chris@zoso.dev>
Fri, 27 Feb 2026 08:03:35 +0000 (00:03 -0800)
Use pointers for field element constants and simplify scalarbase copy setup. Implement point doubling function. Vectorize selection logic and use built-in for swapping bits. Tweak error handling, maybe fix liftString at some point. Use immediate offsets instead of pointer arithmetic where possible. Pass pointers directly to scalarmult, add, and cswap.

assembly/nano-nacl.ts
index.ts

index 87b811aed8713a2f5a8fd93d91bb4fbc76cb88d2..1b816d08f899390811aed9becf95e271992e8fea 100644 (file)
@@ -189,12 +189,14 @@ const PUBLICKEY_BYTES: i32 = 32
 const SECRETKEY_BYTES: i32 = PRIVATEKEY_BYTES + PUBLICKEY_BYTES\r
 const SIGNATURE_BYTES: i32 = 64\r
 const SIGNEDBLOCKHASH_BYTES: i32 = SIGNATURE_BYTES + BLOCKHASH_BYTES\r
-const D: StaticArray<i32> = StaticArray.fromArray<i32>([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203])\r
-const D2: StaticArray<i32> = StaticArray.fromArray<i32>([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406])\r
-const X: StaticArray<i32> = StaticArray.fromArray<i32>([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169])\r
-const Y: StaticArray<i32> = StaticArray.fromArray<i32>([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666])\r
-const I: StaticArray<i32> = StaticArray.fromArray<i32>([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83])\r
-const XY: StaticArray<i32> = StaticArray.fromArray<i32>([0xdd90, 0xa5b7, 0x8ab3, 0x6dde, 0x52f5, 0x7751, 0x9f80, 0x20f0, 0xe37d, 0x64ab, 0x4e8e, 0x66ea, 0x7665, 0xd78b, 0x5f0f, 0xe787])\r
+\r
+const ZERO = changetype<usize>(new StaticArray<i32>(16))\r
+const D = changetype<usize>(StaticArray.fromArray<i32>([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]))\r
+const D2 = changetype<usize>(StaticArray.fromArray<i32>([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]))\r
+const X = changetype<usize>(StaticArray.fromArray<i32>([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]))\r
+const Y = changetype<usize>(StaticArray.fromArray<i32>([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]))\r
+const I = changetype<usize>(StaticArray.fromArray<i32>([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]))\r
+const XY = changetype<usize>(StaticArray.fromArray<i32>([0xdd90, 0xa5b7, 0x8ab3, 0x6dde, 0x52f5, 0x7751, 0x9f80, 0x20f0, 0xe37d, 0x64ab, 0x4e8e, 0x66ea, 0x7665, 0xd78b, 0x5f0f, 0xe787]))\r
 \r
 // Static I/O buffers\r
 const INPUT_BUFFER = memory.data(128)\r
@@ -208,11 +210,12 @@ function vn (x: StaticArray<u8>, y: StaticArray<u8>): bool {
        return d !== 0\r
 }\r
 \r
+// o, a = StaticArray<i32>[16]\r
 const pow_c: StaticArray<i32> = new StaticArray<i32>(16)\r
-function pow2523 (o: StaticArray<i32>, a: StaticArray<i32>): void {\r
-       const c = pow_c\r
+function pow2523 (o: usize, a: usize): void {\r
+       const c = changetype<usize>(pow_c)\r
        for (let i = 0; i < 16; i++) {\r
-               c[i] = a[i]\r
+               store<i32>(c + (i << 2), load<i32>(a + (i << 2)))\r
        }\r
        for (let i = 0; i < 249; i++) {\r
                Square(c, c)\r
@@ -222,7 +225,7 @@ function pow2523 (o: StaticArray<i32>, a: StaticArray<i32>): void {
        Square(c, c)\r
        Multiply(c, c, a)\r
        for (let i = 0; i < 16; i++) {\r
-               o[i] = c[i]\r
+               store<i32>(o + (i << 2), load<i32>(c + (i << 2)))\r
        }\r
 }\r
 \r
@@ -236,11 +239,12 @@ function car25519 (o: StaticArray<i32>): void {
        o[0] += 38 * c\r
 }\r
 \r
+// a = StaticArray<i32>[16]\r
 const inv_c: StaticArray<i32> = new StaticArray<i32>(16)\r
-function inv25519 (o: StaticArray<i32>, a: StaticArray<i32>): void {\r
-       const c = inv_c\r
+function inv25519 (o: StaticArray<i32>, a: usize): void {\r
+       const c = changetype<usize>(inv_c)\r
        for (let i = 0; i < 16; i++) {\r
-               c[i] = a[i]\r
+               store<i32>(c + (i << 2), load<i32>(a + (i << 2)))\r
        }\r
        for (let i = 0; i < 249; i++) {\r
                Square(c, c)\r
@@ -255,10 +259,11 @@ function inv25519 (o: StaticArray<i32>, a: StaticArray<i32>): void {
        Square(c, c)\r
        Multiply(c, c, a)\r
        for (let i = 0; i < 16; i++) {\r
-               o[i] = c[i]\r
+               o[i] = load<i32>(c + (i << 2))\r
        }\r
 }\r
 \r
+// a, b = StaticArray<i32>[16]\r
 const neq_c = new StaticArray<u8>(32)\r
 const neq_d = new StaticArray<u8>(32)\r
 function neq25519 (a: StaticArray<i32>, b: StaticArray<i32>): bool {\r
@@ -293,7 +298,7 @@ function pack25519 (o: StaticArray<u8>, n: StaticArray<i32>): void {
                m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1)\r
                b = (m[15] >> 16) & 1\r
                m[14] &= 0xffff\r
-               sel25519(t, m, 1 - b)\r
+               sel25519(changetype<i32>(t), changetype<i32>(m), 1 - b)\r
        }\r
 \r
        for (let i = 0; i < 16; i++) {\r
@@ -303,76 +308,92 @@ function pack25519 (o: StaticArray<u8>, n: StaticArray<i32>): void {
 }\r
 \r
 const par_d = new StaticArray<u8>(32)\r
-function par25519 (a: StaticArray<i32>): u8 {\r
+function par25519 (a: usize): u8 {\r
        const d = par_d\r
-       pack25519(d, a)\r
+       pack25519(d, changetype<StaticArray<i32>>(a))\r
        return d[0] & 1\r
 }\r
 \r
-function sel25519 (p: StaticArray<i32>, q: StaticArray<i32>, b: i32): void {\r
-       let t: i32 = 0\r
-       const c: i32 = ~(b - 1)\r
-       for (let i = 0; i < 16; i++) {\r
-               t = c & (p[i] ^ q[i])\r
-               p[i] ^= t\r
-               q[i] ^= t\r
-       }\r
+// p, q = StaticArray<i32>[16]\r
+@inline\r
+function sel25519 (p: usize, q: usize, b: i32): void {\r
+       const c = v128.splat<u64>(0 - b)\r
+\r
+       let pi = v128.load(p)\r
+       let qi = v128.load(q)\r
+       v128.store(p, v128.bitselect(qi, pi, c))\r
+       v128.store(q, v128.bitselect(pi, qi, c))\r
+\r
+       pi = v128.load(p, 16)\r
+       qi = v128.load(q, 16)\r
+       v128.store(p, v128.bitselect(qi, pi, c), 16)\r
+       v128.store(q, v128.bitselect(pi, qi, c), 16)\r
+\r
+       pi = v128.load(p, 32)\r
+       qi = v128.load(q, 32)\r
+       v128.store(p, v128.bitselect(qi, pi, c), 32)\r
+       v128.store(q, v128.bitselect(pi, qi, c), 32)\r
+\r
+       pi = v128.load(p, 48)\r
+       qi = v128.load(q, 48)\r
+       v128.store(p, v128.bitselect(qi, pi, c), 48)\r
+       v128.store(q, v128.bitselect(pi, qi, c), 48)\r
 }\r
 \r
-function unpack25519 (o: StaticArray<i32>, n: StaticArray<u8>): void {\r
+function unpack25519 (oo: usize, n: StaticArray<u8>): void {\r
+       const o = changetype<StaticArray<i32>>(oo)\r
        for (let i = 0; i < 16; i++) {\r
                o[i] = i32(n[i << 1]) + (i32(n[(i << 1) + 1]) << 8)\r
        }\r
        o[15] &= (1 << 15) - 1\r
 }\r
 \r
+// o, a, b = StaticArray<i32>[16]\r
 @inline\r
-function Add (o: StaticArray<i32>, a: StaticArray<i32>, b: StaticArray<i32>): void {\r
-       o[0] = a[0] + b[0]\r
-       o[1] = a[1] + b[1]\r
-       o[2] = a[2] + b[2]\r
-       o[3] = a[3] + b[3]\r
-       o[4] = a[4] + b[4]\r
-       o[5] = a[5] + b[5]\r
-       o[6] = a[6] + b[6]\r
-       o[7] = a[7] + b[7]\r
-       o[8] = a[8] + b[8]\r
-       o[9] = a[9] + b[9]\r
-       o[10] = a[10] + b[10]\r
-       o[11] = a[11] + b[11]\r
-       o[12] = a[12] + b[12]\r
-       o[13] = a[13] + b[13]\r
-       o[14] = a[14] + b[14]\r
-       o[15] = a[15] + b[15]\r
+function Add (o: usize, a: usize, b: usize): void {\r
+       store<i32>(o, load<i32>(a) + load<i32>(b))\r
+       store<i32>(o, load<i32>(a, 4) + load<i32>(b, 4), 4)\r
+       store<i32>(o, load<i32>(a, 8) + load<i32>(b, 8), 8)\r
+       store<i32>(o, load<i32>(a, 12) + load<i32>(b, 12), 12)\r
+       store<i32>(o, load<i32>(a, 16) + load<i32>(b, 16), 16)\r
+       store<i32>(o, load<i32>(a, 20) + load<i32>(b, 20), 20)\r
+       store<i32>(o, load<i32>(a, 24) + load<i32>(b, 24), 24)\r
+       store<i32>(o, load<i32>(a, 28) + load<i32>(b, 28), 28)\r
+       store<i32>(o, load<i32>(a, 32) + load<i32>(b, 32), 32)\r
+       store<i32>(o, load<i32>(a, 36) + load<i32>(b, 36), 36)\r
+       store<i32>(o, load<i32>(a, 40) + load<i32>(b, 40), 40)\r
+       store<i32>(o, load<i32>(a, 44) + load<i32>(b, 44), 44)\r
+       store<i32>(o, load<i32>(a, 48) + load<i32>(b, 48), 48)\r
+       store<i32>(o, load<i32>(a, 52) + load<i32>(b, 52), 52)\r
+       store<i32>(o, load<i32>(a, 56) + load<i32>(b, 56), 56)\r
+       store<i32>(o, load<i32>(a, 60) + load<i32>(b, 60), 60)\r
 }\r
 \r
+// o, a, b = StaticArray<i32>[16]\r
 @inline\r
-function Subtract (o: StaticArray<i32>, a: StaticArray<i32>, b: StaticArray<i32>): void {\r
-       o[0] = a[0] - b[0]\r
-       o[1] = a[1] - b[1]\r
-       o[2] = a[2] - b[2]\r
-       o[3] = a[3] - b[3]\r
-       o[4] = a[4] - b[4]\r
-       o[5] = a[5] - b[5]\r
-       o[6] = a[6] - b[6]\r
-       o[7] = a[7] - b[7]\r
-       o[8] = a[8] - b[8]\r
-       o[9] = a[9] - b[9]\r
-       o[10] = a[10] - b[10]\r
-       o[11] = a[11] - b[11]\r
-       o[12] = a[12] - b[12]\r
-       o[13] = a[13] - b[13]\r
-       o[14] = a[14] - b[14]\r
-       o[15] = a[15] - b[15]\r
+function Subtract (o: usize, a: usize, b: usize): void {\r
+       store<i32>(o, load<i32>(a) - load<i32>(b))\r
+       store<i32>(o, load<i32>(a, 4) - load<i32>(b, 4), 4)\r
+       store<i32>(o, load<i32>(a, 8) - load<i32>(b, 8), 8)\r
+       store<i32>(o, load<i32>(a, 12) - load<i32>(b, 12), 12)\r
+       store<i32>(o, load<i32>(a, 16) - load<i32>(b, 16), 16)\r
+       store<i32>(o, load<i32>(a, 20) - load<i32>(b, 20), 20)\r
+       store<i32>(o, load<i32>(a, 24) - load<i32>(b, 24), 24)\r
+       store<i32>(o, load<i32>(a, 28) - load<i32>(b, 28), 28)\r
+       store<i32>(o, load<i32>(a, 32) - load<i32>(b, 32), 32)\r
+       store<i32>(o, load<i32>(a, 36) - load<i32>(b, 36), 36)\r
+       store<i32>(o, load<i32>(a, 40) - load<i32>(b, 40), 40)\r
+       store<i32>(o, load<i32>(a, 44) - load<i32>(b, 44), 44)\r
+       store<i32>(o, load<i32>(a, 48) - load<i32>(b, 48), 48)\r
+       store<i32>(o, load<i32>(a, 52) - load<i32>(b, 52), 52)\r
+       store<i32>(o, load<i32>(a, 56) - load<i32>(b, 56), 56)\r
+       store<i32>(o, load<i32>(a, 60) - load<i32>(b, 60), 60)\r
 }\r
 \r
+// o, a, b = StaticArray<i32>[16]\r
 const multiply_t = new StaticArray<i64>(32)\r
-function Multiply (oo: StaticArray<i32>, aa: StaticArray<i32>, bb: StaticArray<i32>): void {\r
-       const a = changetype<usize>(aa)\r
-       const b = changetype<usize>(bb)\r
-       const o = changetype<usize>(oo)\r
+function Multiply (o: usize, a: usize, b: usize): void {\r
        const t = changetype<usize>(multiply_t.fill(0))\r
-\r
        const b0 = v128.load(b)\r
        const b4 = v128.load(b + 16)\r
        const b8 = v128.load(b + 32)\r
@@ -425,7 +446,8 @@ function Multiply (oo: StaticArray<i32>, aa: StaticArray<i32>, bb: StaticArray<i
        Normalize(o, t)\r
 }\r
 \r
-function Square (o: StaticArray<i32>, a: StaticArray<i32>): void {\r
+// o, a = StaticArray<i32>[16]\r
+function Square (o: usize, a: usize): void {\r
        Multiply(o, a, a)\r
 }\r
 \r
@@ -444,128 +466,128 @@ function Square (o: StaticArray<i32>, a: StaticArray<i32>): void {
 function Normalize (o: usize, t: usize): void {\r
        // reduce\r
        let x = load<i64>(t)\r
-       let y = load<i64>(t + 128)\r
+       let y = load<i64>(t, 128)\r
        store<i64>(t, x + (38 * y))\r
 \r
-       x = load<i64>(t + 8)\r
-       y = load<i64>(t + 136)\r
-       store<i64>(t + 8, x + (38 * y))\r
+       x = load<i64>(t, 8)\r
+       y = load<i64>(t, 136)\r
+       store<i64>(t, x + (38 * y), 8)\r
 \r
-       x = load<i64>(t + 16)\r
-       y = load<i64>(t + 144)\r
-       store<i64>(t + 16, x + (38 * y))\r
+       x = load<i64>(t, 16)\r
+       y = load<i64>(t, 144)\r
+       store<i64>(t, x + (38 * y), 16)\r
 \r
-       x = load<i64>(t + 24)\r
-       y = load<i64>(t + 152)\r
-       store<i64>(t + 24, x + (38 * y))\r
+       x = load<i64>(t, 24)\r
+       y = load<i64>(t, 152)\r
+       store<i64>(t, x + (38 * y), 24)\r
 \r
-       x = load<i64>(t + 32)\r
-       y = load<i64>(t + 160)\r
-       store<i64>(t + 32, x + (38 * y))\r
+       x = load<i64>(t, 32)\r
+       y = load<i64>(t, 160)\r
+       store<i64>(t, x + (38 * y), 32)\r
 \r
-       x = load<i64>(t + 40)\r
-       y = load<i64>(t + 168)\r
-       store<i64>(t + 40, x + (38 * y))\r
+       x = load<i64>(t, 40)\r
+       y = load<i64>(t, 168)\r
+       store<i64>(t, x + (38 * y), 40)\r
 \r
-       x = load<i64>(t + 48)\r
-       y = load<i64>(t + 176)\r
-       store<i64>(t + 48, x + (38 * y))\r
+       x = load<i64>(t, 48)\r
+       y = load<i64>(t, 176)\r
+       store<i64>(t, x + (38 * y), 48)\r
 \r
-       x = load<i64>(t + 56)\r
-       y = load<i64>(t + 184)\r
-       store<i64>(t + 56, x + (38 * y))\r
+       x = load<i64>(t, 56)\r
+       y = load<i64>(t, 184)\r
+       store<i64>(t, x + (38 * y), 56)\r
 \r
-       x = load<i64>(t + 64)\r
-       y = load<i64>(t + 192)\r
-       store<i64>(t + 64, x + (38 * y))\r
+       x = load<i64>(t, 64)\r
+       y = load<i64>(t, 192)\r
+       store<i64>(t, x + (38 * y), 64)\r
 \r
-       x = load<i64>(t + 72)\r
-       y = load<i64>(t + 200)\r
-       store<i64>(t + 72, x + (38 * y))\r
+       x = load<i64>(t, 72)\r
+       y = load<i64>(t, 200)\r
+       store<i64>(t, x + (38 * y), 72)\r
 \r
-       x = load<i64>(t + 80)\r
-       y = load<i64>(t + 208)\r
-       store<i64>(t + 80, x + (38 * y))\r
+       x = load<i64>(t, 80)\r
+       y = load<i64>(t, 208)\r
+       store<i64>(t, x + (38 * y), 80)\r
 \r
-       x = load<i64>(t + 88)\r
-       y = load<i64>(t + 216)\r
-       store<i64>(t + 88, x + (38 * y))\r
+       x = load<i64>(t, 88)\r
+       y = load<i64>(t, 216)\r
+       store<i64>(t, x + (38 * y), 88)\r
 \r
-       x = load<i64>(t + 96)\r
-       y = load<i64>(t + 224)\r
-       store<i64>(t + 96, x + (38 * y))\r
+       x = load<i64>(t, 96)\r
+       y = load<i64>(t, 224)\r
+       store<i64>(t, x + (38 * y), 96)\r
 \r
-       x = load<i64>(t + 104)\r
-       y = load<i64>(t + 232)\r
-       store<i64>(t + 104, x + (38 * y))\r
+       x = load<i64>(t, 104)\r
+       y = load<i64>(t, 232)\r
+       store<i64>(t, x + (38 * y), 104)\r
 \r
-       x = load<i64>(t + 112)\r
-       y = load<i64>(t + 240)\r
-       store<i64>(t + 112, x + (38 * y))\r
+       x = load<i64>(t, 112)\r
+       y = load<i64>(t, 240)\r
+       store<i64>(t, x + (38 * y), 112)\r
 \r
        // first carry\r
        let c: i64 = load<i64>(t)\r
        store<i64>(t, c & 0xFFFF)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 8)\r
-       store<i64>(t + 8, c & 0xFFFF)\r
+       c += load<i64>(t, 8)\r
+       store<i64>(t, c & 0xFFFF, 8)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 16)\r
-       store<i64>(t + 16, c & 0xFFFF)\r
+       c += load<i64>(t, 16)\r
+       store<i64>(t, c & 0xFFFF, 16)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 24)\r
-       store<i64>(t + 24, c & 0xFFFF)\r
+       c += load<i64>(t, 24)\r
+       store<i64>(t, c & 0xFFFF, 24)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 32)\r
-       store<i64>(t + 32, c & 0xFFFF)\r
+       c += load<i64>(t, 32)\r
+       store<i64>(t, c & 0xFFFF, 32)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 40)\r
-       store<i64>(t + 40, c & 0xFFFF)\r
+       c += load<i64>(t, 40)\r
+       store<i64>(t, c & 0xFFFF, 40)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 48)\r
-       store<i64>(t + 48, c & 0xFFFF)\r
+       c += load<i64>(t, 48)\r
+       store<i64>(t, c & 0xFFFF, 48)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 56)\r
-       store<i64>(t + 56, c & 0xFFFF)\r
+       c += load<i64>(t, 56)\r
+       store<i64>(t, c & 0xFFFF, 56)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 64)\r
-       store<i64>(t + 64, c & 0xFFFF)\r
+       c += load<i64>(t, 64)\r
+       store<i64>(t, c & 0xFFFF, 64)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 72)\r
-       store<i64>(t + 72, c & 0xFFFF)\r
+       c += load<i64>(t, 72)\r
+       store<i64>(t, c & 0xFFFF, 72)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 80)\r
-       store<i64>(t + 80, c & 0xFFFF)\r
+       c += load<i64>(t, 80)\r
+       store<i64>(t, c & 0xFFFF, 80)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 88)\r
-       store<i64>(t + 88, c & 0xFFFF)\r
+       c += load<i64>(t, 88)\r
+       store<i64>(t, c & 0xFFFF, 88)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 96)\r
-       store<i64>(t + 96, c & 0xFFFF)\r
+       c += load<i64>(t, 96)\r
+       store<i64>(t, c & 0xFFFF, 96)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 104)\r
-       store<i64>(t + 104, c & 0xFFFF)\r
+       c += load<i64>(t, 104)\r
+       store<i64>(t, c & 0xFFFF, 104)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 112)\r
-       store<i64>(t + 112, c & 0xFFFF)\r
+       c += load<i64>(t, 112)\r
+       store<i64>(t, c & 0xFFFF, 112)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 120)\r
-       store<i64>(t + 120, c & 0xFFFF)\r
+       c += load<i64>(t, 120)\r
+       store<i64>(t, c & 0xFFFF, 120)\r
        c >>= 16\r
 \r
        store<i64>(t, load<i64>(t) + (38 * c))\r
@@ -575,146 +597,215 @@ function Normalize (o: usize, t: usize): void {
        store<i32>(o, c & 0xFFFF)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 8)\r
-       store<i32>(o + 4, c & 0xFFFF)\r
+       c += load<i64>(t, 8)\r
+       store<i32>(o, c & 0xFFFF, 4)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 16)\r
-       store<i32>(o + 8, c & 0xFFFF)\r
+       c += load<i64>(t, 16)\r
+       store<i32>(o, c & 0xFFFF, 8)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 24)\r
-       store<i32>(o + 12, c & 0xFFFF)\r
+       c += load<i64>(t, 24)\r
+       store<i32>(o, c & 0xFFFF, 12)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 32)\r
-       store<i32>(o + 16, c & 0xFFFF)\r
+       c += load<i64>(t, 32)\r
+       store<i32>(o, c & 0xFFFF, 16)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 40)\r
-       store<i32>(o + 20, c & 0xFFFF)\r
+       c += load<i64>(t, 40)\r
+       store<i32>(o, c & 0xFFFF, 20)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 48)\r
-       store<i32>(o + 24, c & 0xFFFF)\r
+       c += load<i64>(t, 48)\r
+       store<i32>(o, c & 0xFFFF, 24)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 56)\r
-       store<i32>(o + 28, c & 0xFFFF)\r
+       c += load<i64>(t, 56)\r
+       store<i32>(o, c & 0xFFFF, 28)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 64)\r
-       store<i32>(o + 32, c & 0xFFFF)\r
+       c += load<i64>(t, 64)\r
+       store<i32>(o, c & 0xFFFF, 32)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 72)\r
-       store<i32>(o + 36, c & 0xFFFF)\r
+       c += load<i64>(t, 72)\r
+       store<i32>(o, c & 0xFFFF, 36)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 80)\r
-       store<i32>(o + 40, c & 0xFFFF)\r
+       c += load<i64>(t, 80)\r
+       store<i32>(o, c & 0xFFFF, 40)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 88)\r
-       store<i32>(o + 44, c & 0xFFFF)\r
+       c += load<i64>(t, 88)\r
+       store<i32>(o, c & 0xFFFF, 44)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 96)\r
-       store<i32>(o + 48, c & 0xFFFF)\r
+       c += load<i64>(t, 96)\r
+       store<i32>(o, c & 0xFFFF, 48)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 104)\r
-       store<i32>(o + 52, c & 0xFFFF)\r
+       c += load<i64>(t, 104)\r
+       store<i32>(o, c & 0xFFFF, 52)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 112)\r
-       store<i32>(o + 56, c & 0xFFFF)\r
+       c += load<i64>(t, 112)\r
+       store<i32>(o, c & 0xFFFF, 56)\r
        c >>= 16\r
 \r
-       c += load<i64>(t + 120)\r
-       store<i32>(o + 60, c & 0xFFFF)\r
+       c += load<i64>(t, 120)\r
+       store<i32>(o, c & 0xFFFF, 60)\r
        c >>= 16\r
 \r
        store<i64>(o, load<i64>(o) + (38 * c))\r
 }\r
 \r
-const a: StaticArray<i32> = new StaticArray<i32>(16)\r
-const b: StaticArray<i32> = new StaticArray<i32>(16)\r
-const c: StaticArray<i32> = new StaticArray<i32>(16)\r
-const d: StaticArray<i32> = new StaticArray<i32>(16)\r
-const e: StaticArray<i32> = new StaticArray<i32>(16)\r
-const f: StaticArray<i32> = new StaticArray<i32>(16)\r
-const g: StaticArray<i32> = new StaticArray<i32>(16)\r
-const h: StaticArray<i32> = new StaticArray<i32>(16)\r
-const t: StaticArray<i32> = new StaticArray<i32>(16)\r
-function add (p: StaticArray<i32>[], q: StaticArray<i32>[]): void {\r
-       Subtract(a, p[1], p[0])\r
-       Subtract(t, q[1], q[0])\r
+// p, q = StaticArray<i32>[4][16]\r
+const add_a: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_b: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_c: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_d: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_e: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_f: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_g: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_h: StaticArray<i32> = new StaticArray<i32>(16)\r
+const add_t: StaticArray<i32> = new StaticArray<i32>(16)\r
+function add (p: usize, q: usize): void {\r
+       const a = changetype<usize>(add_a)\r
+       const b = changetype<usize>(add_b)\r
+       const c = changetype<usize>(add_c)\r
+       const d = changetype<usize>(add_d)\r
+       const e = changetype<usize>(add_e)\r
+       const f = changetype<usize>(add_f)\r
+       const g = changetype<usize>(add_g)\r
+       const h = changetype<usize>(add_h)\r
+       const t = changetype<usize>(add_t)\r
+\r
+       const px = p\r
+       const py = p + 64\r
+       const pz = p + 128\r
+       const pt = p + 192\r
+\r
+       const qx = q\r
+       const qy = q + 64\r
+       const qz = q + 128\r
+       const qt = q + 192\r
+\r
+       Subtract(a, py, px)\r
+       Subtract(t, qy, qx)\r
        Multiply(a, a, t)\r
-       Add(b, p[0], p[1])\r
-       Add(t, q[0], q[1])\r
+       Add(b, px, py)\r
+       Add(t, qx, qy)\r
        Multiply(b, b, t)\r
-       Multiply(c, p[3], q[3])\r
+       Multiply(c, pt, qt)\r
        Multiply(c, c, D2)\r
-       Multiply(d, p[2], q[2])\r
+       Multiply(d, pz, qz)\r
        Add(d, d, d)\r
        Subtract(e, b, a)\r
        Subtract(f, d, c)\r
        Add(g, d, c)\r
        Add(h, b, a)\r
 \r
-       Multiply(p[0], e, f)\r
-       Multiply(p[1], h, g)\r
-       Multiply(p[2], g, f)\r
-       Multiply(p[3], e, h)\r
+       Multiply(px, e, f)\r
+       Multiply(py, h, g)\r
+       Multiply(pz, g, f)\r
+       Multiply(pt, e, h)\r
 }\r
 \r
-function cswap (p: StaticArray<i32>[], q: StaticArray<i32>[], b: i32): void {\r
-       for (let i = 0; i < 4; i++) {\r
-               sel25519(p[i], q[i], b)\r
-       }\r
+/**\r
+ * A = X^2, B = Y^2, C = 2*Z^2, D = -A  (in mod p, Negate is p - A; tweetnacl typically does 0 - A)\r
+ * E = (X+Y)^2 - A - B\r
+ * G = D + B, F = G - C, H = D - B\r
+ * X3 = E*F, Y3 = G*H, Z3 = F*G, T3 = E*H\r
+ */\r
+function double (p: usize): void {\r
+       const a = changetype<usize>(add_a)\r
+       const b = changetype<usize>(add_b)\r
+       const c = changetype<usize>(add_c)\r
+       const d = changetype<usize>(add_d)\r
+       const e = changetype<usize>(add_e)\r
+       const f = changetype<usize>(add_f)\r
+       const g = changetype<usize>(add_g)\r
+       const h = changetype<usize>(add_h)\r
+\r
+       const px = p\r
+       const py = p + 64\r
+       const pz = p + 128\r
+       const pt = p + 192\r
+\r
+       Square(a, px)\r
+       Square(b, py)\r
+       Square(c, pz)\r
+       Add(c, c, c)\r
+       Subtract(d, ZERO, a)\r
+\r
+       Add(e, px, py)\r
+       Square(e, e)\r
+       Subtract(e, e, a)\r
+       Subtract(e, e, b)\r
+\r
+       Add(g, d, b)\r
+       Subtract(f, g, c)\r
+       Subtract(h, d, b)\r
+\r
+       Multiply(px, e, f)\r
+       Multiply(py, g, h)\r
+       Multiply(pz, f, g)\r
+       Multiply(pt, e, h)\r
 }\r
 \r
+// p, q = StaticArray<i32>[16]\r
+// offsets i32x16 = 64 bytes\r
+@inline\r
+function cswap (p: usize, q: usize, b: i32): void {\r
+       sel25519(p, q, b)\r
+       sel25519(p + 64, q + 64, b)\r
+       sel25519(p + 128, q + 128, b)\r
+       sel25519(p + 192, q + 192, b)\r
+}\r
+\r
+// p = StaticArray<i32>[4][16]\r
 const tx: StaticArray<i32> = new StaticArray<i32>(16)\r
 const ty: StaticArray<i32> = new StaticArray<i32>(16)\r
 const zi: StaticArray<i32> = new StaticArray<i32>(16)\r
-function pack (r: StaticArray<u8>, p: StaticArray<i32>[]): void {\r
-       inv25519(zi, p[2])\r
-       Multiply(tx, p[0], zi)\r
-       Multiply(ty, p[1], zi)\r
+function pack (r: StaticArray<u8>, p: usize): void {\r
+       inv25519(zi, p + 128)\r
+       Multiply(changetype<usize>(tx), p, changetype<usize>(zi))\r
+       Multiply(changetype<usize>(ty), p + 64, changetype<usize>(zi))\r
        pack25519(r, ty)\r
-       r[31] ^= par25519(tx) << 7\r
+       r[31] ^= par25519(changetype<usize>(tx)) << 7\r
 }\r
 \r
-function scalarmult (p: StaticArray<i32>[], q: StaticArray<i32>[], s: StaticArray<u8>): void {\r
+// p, q = StaticArray<i32>[4][16]\r
+function scalarmult (p: usize, q: usize, s: StaticArray<u8>): void {\r
        for (let i = 255; i >= 0; i--) {\r
                const b: i32 = (s[i >> 3] >> u8(i & 7)) & 1\r
                cswap(p, q, b)\r
                add(q, p)\r
-               add(p, p)\r
+               double(p)\r
                cswap(p, q, b)\r
        }\r
 }\r
 \r
-const scalarbase_q: StaticArray<i32>[] = [new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16)]\r
-function scalarbase (p: StaticArray<i32>[], s: StaticArray<u8>): void {\r
-       const q = scalarbase_q\r
-       for (let i = 0; i < 16; i++) {\r
-               q[0][i] = X[i]\r
-               q[1][i] = Y[i]\r
-               q[2][i] = 0\r
-               q[3][i] = XY[i]\r
-       }\r
-       q[2][0] = 1\r
+// p = StaticArray<i32>[4][16]\r
+const scalarbase_q = new StaticArray<i32>(64)\r
+function scalarbase (p: usize, s: StaticArray<u8>): void {\r
+       const q = changetype<usize>(scalarbase_q)\r
+       memory.copy(q, X, 64)\r
+       memory.copy(q + 64, Y, 64)\r
+       memory.fill(q + 128, 0, 64)\r
+       memory.copy(q + 192, XY, 64)\r
+       store<i32>(q, 1, 128)\r
        scalarmult(p, q, s)\r
 }\r
 \r
-const L: StaticArray<i32> = StaticArray.fromArray<i32>([\r
+// Group order of the curve ≈ 2²⁵²\r
+const L: usize = changetype<usize>(StaticArray.fromArray<i32>([\r
        0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,\r
        0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,\r
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10\r
-])\r
+]))\r
 \r
 function modL (r: StaticArray<u8>, x: StaticArray<i32>): void {\r
        let c: i32\r
@@ -724,7 +815,7 @@ function modL (r: StaticArray<u8>, x: StaticArray<i32>): void {
                c = 0\r
                const xi = x[i]\r
                for (let j = i - 32, k = i - 12; j < k; j++) {\r
-                       t = (xi * L[j - (i - 32)]) << 4\r
+                       t = (xi * load<i32>(L + ((j - (i - 32)) << 2))) << 4\r
                        v = x[j] + c - t\r
                        c = (v + 128) >> 8\r
                        x[j] = v - (c << 8)\r
@@ -735,12 +826,12 @@ function modL (r: StaticArray<u8>, x: StaticArray<i32>): void {
        c = 0\r
        const x31 = x[31]\r
        for (let j = 0; j < 32; j++) {\r
-               x[j] += c - (x31 >> 4) * L[j]\r
+               x[j] += c - (x31 >> 4) * load<i32>(L + (j << 2))\r
                c = x[j] >> 8\r
                x[j] &= 255\r
        }\r
        for (let j = 0; j < 32; j++) {\r
-               x[j] -= c * L[j]\r
+               x[j] -= c * load<i32>(L + (j << 2))\r
        }\r
        for (let i = 0; i < 32; i++) {\r
                x[i + 1] += x[i] >> 8\r
@@ -748,8 +839,9 @@ function modL (r: StaticArray<u8>, x: StaticArray<i32>): void {
        }\r
 }\r
 \r
-const x = new StaticArray<i32>(64)\r
+const reduce_x = new StaticArray<i32>(64)\r
 function reduce (r: StaticArray<u8>): void {\r
+       const x = reduce_x\r
        for (let i = 0; i < 64; i++) {\r
                x[i] = i32(r[i])\r
                r[i] = 0\r
@@ -757,22 +849,28 @@ function reduce (r: StaticArray<u8>): void {
        modL(r, x)\r
 }\r
 \r
+// r = StaticArray<i32>[4][16]\r
+const unpack_chk: StaticArray<i32> = new StaticArray<i32>(16)\r
+const unpack_num: StaticArray<i32> = new StaticArray<i32>(16)\r
+const unpack_den: StaticArray<i32> = new StaticArray<i32>(16)\r
+const unpack_den2: StaticArray<i32> = new StaticArray<i32>(16)\r
+const unpack_den4: StaticArray<i32> = new StaticArray<i32>(16)\r
+const unpack_den6: StaticArray<i32> = new StaticArray<i32>(16)\r
 const unpack_t: StaticArray<i32> = new StaticArray<i32>(16)\r
-const chk: StaticArray<i32> = new StaticArray<i32>(16)\r
-const num: StaticArray<i32> = new StaticArray<i32>(16)\r
-const den: StaticArray<i32> = new StaticArray<i32>(16)\r
-const den2: StaticArray<i32> = new StaticArray<i32>(16)\r
-const den4: StaticArray<i32> = new StaticArray<i32>(16)\r
-const den6: StaticArray<i32> = new StaticArray<i32>(16)\r
-const z: StaticArray<i32> = new StaticArray<i32>(16)\r
-function unpackneg (r: Array<StaticArray<i32>>, p: StaticArray<u8>): i8 {\r
-       const t = unpack_t\r
-\r
-       unpack25519(r[1], p)\r
-       Square(num, r[1])\r
+function unpackneg (r: usize, p: StaticArray<u8>): i8 {\r
+       const chk = changetype<usize>(unpack_chk)\r
+       const num = changetype<usize>(unpack_num)\r
+       const den = changetype<usize>(unpack_den)\r
+       const den2 = changetype<usize>(unpack_den2)\r
+       const den4 = changetype<usize>(unpack_den4)\r
+       const den6 = changetype<usize>(unpack_den6)\r
+       const t = changetype<usize>(unpack_t)\r
+\r
+       unpack25519(r + 64, p)\r
+       Square(num, r + 64)\r
        Multiply(den, num, D)\r
-       Subtract(num, num, r[2])\r
-       Add(den, r[2], den)\r
+       Subtract(num, num, r + 128)\r
+       Add(den, r + 128, den)\r
 \r
        Square(den2, den)\r
        Square(den4, den2)\r
@@ -784,37 +882,37 @@ function unpackneg (r: Array<StaticArray<i32>>, p: StaticArray<u8>): i8 {
        Multiply(t, t, num)\r
        Multiply(t, t, den)\r
        Multiply(t, t, den)\r
-       Multiply(r[0], t, den)\r
+       Multiply(r, t, den)\r
 \r
-       Square(chk, r[0])\r
+       Square(chk, r)\r
        Multiply(chk, chk, den)\r
-       if (neq25519(chk, num)) {\r
-               Multiply(r[0], r[0], I)\r
+       if (neq25519(changetype<StaticArray<i32>>(chk), changetype<StaticArray<i32>>(num))) {\r
+               Multiply(r, r, I)\r
        }\r
 \r
-       Square(chk, r[0])\r
+       Square(chk, r)\r
        Multiply(chk, chk, den)\r
 \r
-       if (neq25519(chk, num)) {\r
+       if (neq25519(changetype<StaticArray<i32>>(chk), changetype<StaticArray<i32>>(num))) {\r
                return -1\r
        }\r
 \r
-       if (par25519(r[0]) === (p[31] >> 7)) {\r
-               Subtract(r[0], z, r[0])\r
+       if (par25519(r) === (p[31] >> 7)) {\r
+               Subtract(r, ZERO, r)\r
        }\r
-       Multiply(r[3], r[0], r[1])\r
+       Multiply(r + 192, r, r + 64)\r
        return 0\r
 }\r
 \r
 // Validate signature scalar S is canonical (S < L)\r
 function canonical (S: StaticArray<u8>): boolean {\r
        // If S >= 2^253 then S >= L for sure.\r
-       if ((S[32] & 0xE0) != 0) return false\r
+       if ((S[31] & 0xE0) != 0) return false\r
 \r
        // Check S-L for underflow (c=1) which means S < L\r
        let c = 0\r
        for (let i = 0; i < 32; i++) {\r
-               const diff = S[i] - L[i] - c\r
+               const diff = S[i] - load<i32>(L + (i << 2)) - c\r
                c = (diff >> 31) & 1\r
        }\r
        return c == 1\r
@@ -826,14 +924,14 @@ function crypto_hash (o: StaticArray<u8>, i: StaticArray<u8>): void {
 }\r
 \r
 const crypto_convert_h = new StaticArray<u8>(64)\r
-const crypto_convert_p = [new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16)]\r
+const crypto_convert_p = new StaticArray<i32>(64)\r
 function crypto_convert (pk: StaticArray<u8>, sk: StaticArray<u8>): void {\r
        const h = crypto_convert_h\r
-       const p = crypto_convert_p\r
-       p[0].fill(0)\r
-       p[1].fill(0); p[1][0] = 1\r
-       p[2].fill(0); p[2][0] = 1\r
-       p[3].fill(0)\r
+       const p = changetype<usize>(crypto_convert_p)\r
+       memory.fill(p, 0, 256)\r
+       store<i32>(p, 1, 64)\r
+       store<i32>(p, 1, 128)\r
+\r
        crypto_hash(h, sk)\r
        h[0] &= 248\r
        h[31] &= 127\r
@@ -844,7 +942,7 @@ function crypto_convert (pk: StaticArray<u8>, sk: StaticArray<u8>): void {
 \r
 const crypto_sign_d = new StaticArray<u8>(64)\r
 const crypto_sign_h = new StaticArray<u8>(64)\r
-const crypto_sign_p = [new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16)]\r
+const crypto_sign_p = new StaticArray<i32>(64)\r
 const crypto_sign_r = new StaticArray<u8>(64)\r
 const crypto_sign_x = new StaticArray<i32>(64)\r
 const crypto_sign_s = new StaticArray<u8>(SIGNATURE_BYTES)\r
@@ -852,15 +950,15 @@ const crypto_sign_prv = new StaticArray<u8>(PRIVATEKEY_BYTES)
 function crypto_sign (sm: StaticArray<u8>, m: StaticArray<u8>, sk: StaticArray<u8>): void {\r
        const d = crypto_sign_d\r
        const h = crypto_sign_h\r
-       const p = crypto_sign_p\r
+       const p = changetype<usize>(crypto_sign_p)\r
+       memory.fill(p, 0, 256)\r
+       store<i32>(p, 1, 64)\r
+       store<i32>(p, 1, 128)\r
+\r
        const r = crypto_sign_r\r
        const x = crypto_sign_x\r
        const s = crypto_sign_s\r
        const prv = crypto_sign_prv\r
-       p[0].fill(0)\r
-       p[1].fill(0); p[1][0] = 1\r
-       p[2].fill(0); p[2][0] = 1\r
-       p[3].fill(0)\r
 \r
        for (let i = 0; i < PRIVATEKEY_BYTES; i++) {\r
                prv[i] = sk[i]\r
@@ -906,8 +1004,8 @@ function crypto_sign (sm: StaticArray<u8>, m: StaticArray<u8>, sk: StaticArray<u
 }\r
 \r
 const crypto_verify_open_d = new StaticArray<u8>(64)\r
-const crypto_verify_open_p = [new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16)]\r
-const crypto_verify_open_q = [new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16), new StaticArray<i32>(16)]\r
+const crypto_verify_open_p = new StaticArray<i32>(64)\r
+const crypto_verify_open_q = new StaticArray<i32>(64)\r
 const crypto_verify_open_t = new StaticArray<u8>(32)\r
 const crypto_verify_open_sm = new StaticArray<u8>(SIGNEDBLOCKHASH_BYTES)\r
 const crypto_verify_open_S = new StaticArray<u8>(32)\r
@@ -916,19 +1014,17 @@ const crypto_verify_open_S = new StaticArray<u8>(32)
 */\r
 function crypto_verify (h: StaticArray<u8>, s: StaticArray<u8>, k: StaticArray<u8>): bool {\r
        const d = crypto_verify_open_d\r
-       const p = crypto_verify_open_p\r
-       const q = crypto_verify_open_q\r
+       const p = changetype<usize>(crypto_verify_open_p)\r
+       memory.fill(p, 0, 256)\r
+       store<i32>(p, 1, 64)\r
+       store<i32>(p, 1, 128)\r
+       const q = changetype<usize>(crypto_verify_open_q)\r
+       memory.fill(q, 0, 256)\r
+       store<i32>(q, 1, 128)\r
+\r
        const t = crypto_verify_open_t\r
        const sm = crypto_verify_open_sm\r
        const S = crypto_verify_open_S\r
-       p[0].fill(0)\r
-       p[1].fill(0); p[1][0] = 1\r
-       p[2].fill(0); p[2][0] = 1\r
-       p[3].fill(0)\r
-       q[0].fill(0)\r
-       q[1].fill(0)\r
-       q[2].fill(0); q[2][0] = 1\r
-       q[3].fill(0)\r
 \r
        // fail\r
        if (unpackneg(q, k)) return false\r
@@ -950,10 +1046,9 @@ function crypto_verify (h: StaticArray<u8>, s: StaticArray<u8>, k: StaticArray<u
        reduce(d)\r
        scalarmult(p, q, d)\r
 \r
-       q[0].fill(0)\r
-       q[1].fill(0); q[1][0] = 1\r
-       q[2].fill(0); q[2][0] = 1\r
-       q[3].fill(0)\r
+       memory.fill(q, 0, 256)\r
+       store<i32>(q, 1, 64)\r
+       store<i32>(q, 1, 128)\r
        scalarbase(q, S)\r
        add(p, q)\r
        pack(t, p)\r
index 736abf832daff3373b7667743ff4bfbeb3a65b23..3d8f001a5ce004cc2a9bd31821812d387aa3323c 100644 (file)
--- a/index.ts
+++ b/index.ts
@@ -33,8 +33,13 @@ const NanoNaCl = async (bytes: number[]): Promise<void> => {
                        instance = await WebAssembly.instantiate(module, {
                                env: {
                                        abort: (msg: any, file: any, row: any, col: any) => {
-                                               console.error('Wasm abort:', `msg ${msg}`, `file ${file}`, `row ${row}`, `col ${col}`)
-                                               throw new Error(`Wasm abort: ${msg}`)
+                                               // ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
+                                               // msg = __liftString(msg >>> 0)
+                                               // file = __liftString(file >>> 0)
+                                               row = row >>> 0
+                                               col = col >>> 0
+                                               console.error('wasm abort:', `msg ${msg}`, `file ${file}`, `row ${row}`, `col ${col}`)
+                                               throw new Error(msg, { cause: { file, row, col } })
                                        },
                                        "performance.now" () {
                                                // ~lib/bindings/dom/performance.now() => f64