ox 1.0.5 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/dist/core/Base64.d.ts +10 -21
- package/dist/core/Base64.d.ts.map +1 -1
- package/dist/core/Base64.js +8 -127
- package/dist/core/Base64.js.map +1 -1
- package/dist/core/BinaryStateTree.d.ts.map +1 -1
- package/dist/core/BinaryStateTree.js +2 -2
- package/dist/core/BinaryStateTree.js.map +1 -1
- package/dist/core/Bls.d.ts.map +1 -1
- package/dist/core/Bls.js +19 -44
- package/dist/core/Bls.js.map +1 -1
- package/dist/core/Ed25519.d.ts.map +1 -1
- package/dist/core/Ed25519.js +7 -6
- package/dist/core/Ed25519.js.map +1 -1
- package/dist/core/Engine.d.ts +156 -0
- package/dist/core/Engine.d.ts.map +1 -0
- package/dist/core/Engine.js +210 -0
- package/dist/core/Engine.js.map +1 -0
- package/dist/core/Hash.d.ts +4 -4
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +9 -12
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/Keystore.d.ts.map +1 -1
- package/dist/core/Keystore.js +15 -10
- package/dist/core/Keystore.js.map +1 -1
- package/dist/core/Mnemonic.d.ts.map +1 -1
- package/dist/core/Mnemonic.js +3 -2
- package/dist/core/Mnemonic.js.map +1 -1
- package/dist/core/P256.d.ts.map +1 -1
- package/dist/core/P256.js +8 -9
- package/dist/core/P256.js.map +1 -1
- package/dist/core/Secp256k1.d.ts.map +1 -1
- package/dist/core/Secp256k1.js +8 -9
- package/dist/core/Secp256k1.js.map +1 -1
- package/dist/core/WebCryptoP256.d.ts.map +1 -1
- package/dist/core/WebCryptoP256.js +2 -2
- package/dist/core/WebCryptoP256.js.map +1 -1
- package/dist/core/X25519.d.ts.map +1 -1
- package/dist/core/X25519.js +4 -3
- package/dist/core/X25519.js.map +1 -1
- package/dist/core/internal/bls.d.ts +12 -0
- package/dist/core/internal/bls.d.ts.map +1 -0
- package/dist/core/internal/bls.js +79 -0
- package/dist/core/internal/bls.js.map +1 -0
- package/dist/core/internal/codec/base64.d.ts +84 -0
- package/dist/core/internal/codec/base64.d.ts.map +1 -0
- package/dist/core/internal/codec/base64.js +177 -0
- package/dist/core/internal/codec/base64.js.map +1 -0
- package/dist/core/internal/codec/hex.d.ts +49 -4
- package/dist/core/internal/codec/hex.d.ts.map +1 -1
- package/dist/core/internal/codec/hex.js +109 -35
- package/dist/core/internal/codec/hex.js.map +1 -1
- package/dist/core/internal/curves.d.ts +17 -0
- package/dist/core/internal/curves.d.ts.map +1 -0
- package/dist/core/internal/curves.js +17 -0
- package/dist/core/internal/curves.js.map +1 -0
- package/dist/core/internal/ed25519.d.ts +14 -0
- package/dist/core/internal/ed25519.d.ts.map +1 -0
- package/dist/core/internal/ed25519.js +29 -0
- package/dist/core/internal/ed25519.js.map +1 -0
- package/dist/core/internal/engine.d.ts +278 -0
- package/dist/core/internal/engine.d.ts.map +1 -0
- package/dist/core/internal/engine.js +131 -0
- package/dist/core/internal/engine.js.map +1 -0
- package/dist/core/internal/hash.d.ts +12 -0
- package/dist/core/internal/hash.d.ts.map +1 -0
- package/dist/core/internal/hash.js +30 -0
- package/dist/core/internal/hash.js.map +1 -0
- package/dist/core/internal/keystore.d.ts +14 -0
- package/dist/core/internal/keystore.d.ts.map +1 -0
- package/dist/core/internal/keystore.js +32 -0
- package/dist/core/internal/keystore.js.map +1 -0
- package/dist/core/internal/mnemonic.d.ts +4 -0
- package/dist/core/internal/mnemonic.d.ts.map +1 -0
- package/dist/core/internal/mnemonic.js +14 -0
- package/dist/core/internal/mnemonic.js.map +1 -0
- package/dist/core/internal/p256.d.ts +14 -0
- package/dist/core/internal/p256.d.ts.map +1 -0
- package/dist/core/internal/p256.js +36 -0
- package/dist/core/internal/p256.js.map +1 -0
- package/dist/core/internal/secp256k1.d.ts +14 -0
- package/dist/core/internal/secp256k1.d.ts.map +1 -0
- package/dist/core/internal/secp256k1.js +36 -0
- package/dist/core/internal/secp256k1.js.map +1 -0
- package/dist/core/internal/x25519.d.ts +8 -0
- package/dist/core/internal/x25519.d.ts.map +1 -0
- package/dist/core/internal/x25519.js +20 -0
- package/dist/core/internal/x25519.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.docs.d.ts +2 -0
- package/dist/index.docs.d.ts.map +1 -1
- package/dist/index.docs.js +2 -0
- package/dist/index.docs.js.map +1 -1
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -1
- package/dist/node/Ed25519.d.ts +33 -0
- package/dist/node/Ed25519.d.ts.map +1 -0
- package/dist/node/Ed25519.js +67 -0
- package/dist/node/Ed25519.js.map +1 -0
- package/dist/node/Engine.d.ts +68 -0
- package/dist/node/Engine.d.ts.map +1 -0
- package/dist/node/Engine.js +75 -0
- package/dist/node/Engine.js.map +1 -0
- package/dist/node/Hash.d.ts +37 -0
- package/dist/node/Hash.d.ts.map +1 -0
- package/dist/node/Hash.js +35 -0
- package/dist/node/Hash.js.map +1 -0
- package/dist/node/Keystore.d.ts +36 -0
- package/dist/node/Keystore.d.ts.map +1 -0
- package/dist/node/Keystore.js +72 -0
- package/dist/node/Keystore.js.map +1 -0
- package/dist/node/Mnemonic.d.ts +35 -0
- package/dist/node/Mnemonic.d.ts.map +1 -0
- package/dist/node/Mnemonic.js +46 -0
- package/dist/node/Mnemonic.js.map +1 -0
- package/dist/node/P256.d.ts +32 -0
- package/dist/node/P256.d.ts.map +1 -0
- package/dist/node/P256.js +34 -0
- package/dist/node/P256.js.map +1 -0
- package/dist/node/X25519.d.ts +31 -0
- package/dist/node/X25519.d.ts.map +1 -0
- package/dist/node/X25519.js +71 -0
- package/dist/node/X25519.js.map +1 -0
- package/dist/node/index.d.ts +126 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +126 -0
- package/dist/node/index.js.map +1 -0
- package/dist/tempo/VirtualMaster.d.ts +2 -0
- package/dist/tempo/VirtualMaster.d.ts.map +1 -1
- package/dist/tempo/VirtualMaster.js +19 -5
- package/dist/tempo/VirtualMaster.js.map +1 -1
- package/dist/tempo/internal/mine.wasm.d.ts +2 -4
- package/dist/tempo/internal/mine.wasm.d.ts.map +1 -1
- package/dist/tempo/internal/mine.wasm.js +7 -12
- package/dist/tempo/internal/mine.wasm.js.map +1 -1
- package/dist/tempo/internal/virtualMasterPool.js +4 -1
- package/dist/tempo/internal/virtualMasterPool.js.map +1 -1
- package/dist/wasm/Ed25519.d.ts +35 -0
- package/dist/wasm/Ed25519.d.ts.map +1 -0
- package/dist/wasm/Ed25519.js +88 -0
- package/dist/wasm/Ed25519.js.map +1 -0
- package/dist/wasm/Engine.d.ts +71 -0
- package/dist/wasm/Engine.d.ts.map +1 -0
- package/dist/wasm/Engine.js +76 -0
- package/dist/wasm/Engine.js.map +1 -0
- package/dist/wasm/Hash.d.ts +43 -0
- package/dist/wasm/Hash.d.ts.map +1 -0
- package/dist/wasm/Hash.js +64 -0
- package/dist/wasm/Hash.js.map +1 -0
- package/dist/wasm/Keystore.d.ts +37 -0
- package/dist/wasm/Keystore.d.ts.map +1 -0
- package/dist/wasm/Keystore.js +34 -0
- package/dist/wasm/Keystore.js.map +1 -0
- package/dist/wasm/Mnemonic.d.ts +33 -0
- package/dist/wasm/Mnemonic.d.ts.map +1 -0
- package/dist/wasm/Mnemonic.js +30 -0
- package/dist/wasm/Mnemonic.js.map +1 -0
- package/dist/wasm/X25519.d.ts +33 -0
- package/dist/wasm/X25519.d.ts.map +1 -0
- package/dist/wasm/X25519.js +53 -0
- package/dist/wasm/X25519.js.map +1 -0
- package/dist/wasm/index.d.ts +115 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js +115 -0
- package/dist/wasm/index.js.map +1 -0
- package/dist/wasm/internal/blake3.d.ts +11 -0
- package/dist/wasm/internal/blake3.d.ts.map +1 -0
- package/dist/wasm/internal/blake3.js +31 -0
- package/dist/wasm/internal/blake3.js.map +1 -0
- package/dist/wasm/internal/blake3.wasm.d.ts +3 -0
- package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/blake3.wasm.js +10 -0
- package/dist/wasm/internal/blake3.wasm.js.map +1 -0
- package/dist/wasm/internal/crypto25519.d.ts +16 -0
- package/dist/wasm/internal/crypto25519.d.ts.map +1 -0
- package/dist/wasm/internal/crypto25519.js +5 -0
- package/dist/wasm/internal/crypto25519.js.map +1 -0
- package/dist/wasm/internal/crypto25519.wasm.d.ts +3 -0
- package/dist/wasm/internal/crypto25519.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/crypto25519.wasm.js +10 -0
- package/dist/wasm/internal/crypto25519.wasm.js.map +1 -0
- package/dist/wasm/internal/ed25519.d.ts +4 -0
- package/dist/wasm/internal/ed25519.d.ts.map +1 -0
- package/dist/wasm/internal/ed25519.js +21 -0
- package/dist/wasm/internal/ed25519.js.map +1 -0
- package/dist/wasm/internal/hash.d.ts +9 -0
- package/dist/wasm/internal/hash.d.ts.map +1 -0
- package/dist/wasm/internal/hash.js +26 -0
- package/dist/wasm/internal/hash.js.map +1 -0
- package/dist/wasm/internal/hashes.d.ts +12 -0
- package/dist/wasm/internal/hashes.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.js +8 -0
- package/dist/wasm/internal/hashes.js.map +1 -0
- package/dist/wasm/internal/hashes.wasm.d.ts +7 -0
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.wasm.js +14 -0
- package/dist/wasm/internal/hashes.wasm.js.map +1 -0
- package/dist/wasm/internal/instantiate.d.ts +56 -0
- package/dist/wasm/internal/instantiate.d.ts.map +1 -0
- package/dist/wasm/internal/instantiate.js +92 -0
- package/dist/wasm/internal/instantiate.js.map +1 -0
- package/dist/wasm/internal/mnemonic.d.ts +4 -0
- package/dist/wasm/internal/mnemonic.d.ts.map +1 -0
- package/dist/wasm/internal/mnemonic.js +45 -0
- package/dist/wasm/internal/mnemonic.js.map +1 -0
- package/dist/wasm/internal/pbkdf2.d.ts +12 -0
- package/dist/wasm/internal/pbkdf2.d.ts.map +1 -0
- package/dist/wasm/internal/pbkdf2.js +51 -0
- package/dist/wasm/internal/pbkdf2.js.map +1 -0
- package/dist/wasm/internal/x25519.d.ts +4 -0
- package/dist/wasm/internal/x25519.d.ts.map +1 -0
- package/dist/wasm/internal/x25519.js +21 -0
- package/dist/wasm/internal/x25519.js.map +1 -0
- package/dist/zod/TypedData.d.ts +12 -12
- package/package.json +81 -1
- package/src/core/Base64.ts +19 -166
- package/src/core/BinaryStateTree.ts +2 -3
- package/src/core/Bls.ts +27 -77
- package/src/core/Ed25519.ts +7 -7
- package/src/core/Engine.ts +308 -0
- package/src/core/Hash.ts +9 -12
- package/src/core/Keystore.ts +17 -17
- package/src/core/Mnemonic.ts +3 -6
- package/src/core/P256.ts +15 -24
- package/src/core/Rlp_tx.bench.ts +2 -4
- package/src/core/Secp256k1.ts +9 -14
- package/src/core/TxEnvelopeEip1559.bench.ts +0 -5
- package/src/core/WebCryptoP256.ts +2 -2
- package/src/core/X25519.ts +4 -3
- package/src/core/_test/AbiParameters.adversarial.fuzz.ts +1 -2
- package/src/core/_test/AbiParameters.fuzz.ts +1 -2
- package/src/core/_test/Base.fuzz.ts +1 -2
- package/src/core/_test/Cbor.fuzz.ts +1 -2
- package/src/core/_test/Engine.fuzz.ts +293 -0
- package/src/core/_test/Engine.test-d.ts +140 -0
- package/src/core/_test/Engine.test.ts +618 -0
- package/src/core/_test/Hash.vectors.test.ts +64 -0
- package/src/core/_test/Hex.fuzz.ts +1 -2
- package/src/core/_test/Rlp.fuzz.ts +1 -2
- package/src/core/_test/Signature.fuzz.ts +1 -2
- package/src/core/_test/curves.test.ts +7 -0
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/bls.ts +121 -0
- package/src/core/internal/codec/_test/base64.conformance.ts +156 -0
- package/src/core/internal/codec/_test/hex.conformance.ts +204 -0
- package/src/core/internal/codec/_test/hex.fuzz.ts +234 -0
- package/src/core/internal/codec/_test/hex.test.ts +124 -0
- package/src/core/internal/codec/base64.ts +222 -0
- package/src/core/internal/codec/hex.ts +115 -34
- package/src/core/internal/curves.ts +18 -0
- package/src/core/internal/ed25519.ts +64 -0
- package/src/core/internal/engine.ts +410 -0
- package/src/core/internal/hash.ts +48 -0
- package/src/core/internal/keystore.ts +107 -0
- package/src/core/internal/mnemonic.ts +18 -0
- package/src/core/internal/p256.ts +91 -0
- package/src/core/internal/secp256k1.ts +91 -0
- package/src/core/internal/x25519.ts +40 -0
- package/src/index.docs.ts +2 -0
- package/src/index.ts +39 -0
- package/src/node/Ed25519.ts +87 -0
- package/src/node/Engine.ts +125 -0
- package/src/node/Hash.ts +51 -0
- package/src/node/Keystore.ts +103 -0
- package/src/node/Mnemonic.ts +68 -0
- package/src/node/P256.ts +48 -0
- package/src/node/X25519.ts +93 -0
- package/src/node/_test/Curves.fuzz.ts +76 -0
- package/src/node/_test/Ed25519.test-d.ts +35 -0
- package/src/node/_test/Ed25519.test.ts +220 -0
- package/src/node/_test/Engine.test-d.ts +28 -0
- package/src/node/_test/Engine.test.ts +102 -0
- package/src/node/_test/Hash.test-d.ts +32 -0
- package/src/node/_test/Hash.test.ts +101 -0
- package/src/node/_test/Keystore.fuzz.ts +58 -0
- package/src/node/_test/Keystore.test-d.ts +43 -0
- package/src/node/_test/Keystore.test.ts +198 -0
- package/src/node/_test/Mnemonic.fuzz.ts +31 -0
- package/src/node/_test/Mnemonic.test-d.ts +21 -0
- package/src/node/_test/Mnemonic.test.ts +98 -0
- package/src/node/_test/P256.test-d.ts +29 -0
- package/src/node/_test/P256.test.ts +102 -0
- package/src/node/_test/X25519.test-d.ts +28 -0
- package/src/node/_test/X25519.test.ts +239 -0
- package/src/node/index.ts +132 -0
- package/src/tempo/VirtualMaster.test.ts +75 -0
- package/src/tempo/VirtualMaster.ts +28 -6
- package/src/tempo/internal/mine.wasm.ts +7 -13
- package/src/tempo/internal/virtualMasterPool.ts +4 -1
- package/src/tsconfig.json +2 -1
- package/src/version.ts +1 -1
- package/src/wasm/Ed25519.ts +114 -0
- package/src/wasm/Engine.ts +121 -0
- package/src/wasm/Hash.bench.ts +60 -0
- package/src/wasm/Hash.ts +88 -0
- package/src/wasm/Keystore.ts +48 -0
- package/src/wasm/Mnemonic.ts +44 -0
- package/src/wasm/X25519.ts +70 -0
- package/src/wasm/_test/Crypto25519.conformance.ts +57 -0
- package/src/wasm/_test/Crypto25519.fuzz.ts +187 -0
- package/src/wasm/_test/Ed25519.test-d.ts +28 -0
- package/src/wasm/_test/Ed25519.test.ts +168 -0
- package/src/wasm/_test/Ed25519.vectors.test.ts +73 -0
- package/src/wasm/_test/Engine.test-d.ts +28 -0
- package/src/wasm/_test/Engine.test.ts +96 -0
- package/src/wasm/_test/Hash.browser.test.ts +54 -0
- package/src/wasm/_test/Hash.fuzz.ts +223 -0
- package/src/wasm/_test/Hash.test-d.ts +33 -0
- package/src/wasm/_test/Hash.test.ts +311 -0
- package/src/wasm/_test/Hash.vectors.test.ts +124 -0
- package/src/wasm/_test/Keystore.browser.test.ts +42 -0
- package/src/wasm/_test/Keystore.fuzz.ts +113 -0
- package/src/wasm/_test/Keystore.test-d.ts +33 -0
- package/src/wasm/_test/Keystore.test.ts +192 -0
- package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
- package/src/wasm/_test/Mnemonic.test-d.ts +17 -0
- package/src/wasm/_test/Mnemonic.test.ts +110 -0
- package/src/wasm/_test/Runtime.test.ts +21 -0
- package/src/wasm/_test/X25519.test-d.ts +21 -0
- package/src/wasm/_test/X25519.test.ts +194 -0
- package/src/wasm/_test/fixtures.ts +4 -0
- package/src/wasm/_test/runtime.wasm.ts +11 -0
- package/src/wasm/index.ts +120 -0
- package/src/wasm/internal/blake3.ts +45 -0
- package/src/wasm/internal/blake3.wasm.ts +11 -0
- package/src/wasm/internal/crypto25519.ts +43 -0
- package/src/wasm/internal/crypto25519.wasm.ts +11 -0
- package/src/wasm/internal/ed25519.ts +31 -0
- package/src/wasm/internal/hash.ts +50 -0
- package/src/wasm/internal/hashes.ts +29 -0
- package/src/wasm/internal/hashes.wasm.ts +17 -0
- package/src/wasm/internal/instantiate.ts +135 -0
- package/src/wasm/internal/mnemonic.ts +56 -0
- package/src/wasm/internal/pbkdf2.ts +86 -0
- package/src/wasm/internal/x25519.ts +29 -0
- package/src/tempo/internal/mine.c +0 -182
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Engine as CoreEngine } from 'ox'
|
|
2
|
+
import { Engine, Hash } from 'ox/wasm'
|
|
3
|
+
import { describe, expect, test } from 'vp/test'
|
|
4
|
+
|
|
5
|
+
describe('engine', () => {
|
|
6
|
+
test('behavior: does not install', async () => {
|
|
7
|
+
const engine = await Engine.engine()
|
|
8
|
+
expect(Object.keys(engine)).toMatchInlineSnapshot(`
|
|
9
|
+
[
|
|
10
|
+
"Ed25519",
|
|
11
|
+
"Hash",
|
|
12
|
+
"Keystore",
|
|
13
|
+
"Mnemonic",
|
|
14
|
+
"X25519",
|
|
15
|
+
]
|
|
16
|
+
`)
|
|
17
|
+
// Benches, differential tests, and composition need an implementation
|
|
18
|
+
// value without touching global state.
|
|
19
|
+
expect(CoreEngine.get()).toMatchInlineSnapshot('{}')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('behavior: installs for the duration of a call', async () => {
|
|
23
|
+
// `with` is the case that genuinely needs a value: there is nothing
|
|
24
|
+
// installed for `set` to merge into.
|
|
25
|
+
const wasm = await Engine.engine()
|
|
26
|
+
const inside = CoreEngine.with(wasm, () => Hash.sha256('0xdeadbeef'))
|
|
27
|
+
expect(inside).toEqual(Hash.sha256('0xdeadbeef'))
|
|
28
|
+
expect(CoreEngine.get()).toMatchInlineSnapshot('{}')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('install', () => {
|
|
33
|
+
test('behavior: merges with a later set, rather than being replaced', async () => {
|
|
34
|
+
await Engine.install()
|
|
35
|
+
CoreEngine.set({ Bls: { randomSecretKey: () => new Uint8Array(32) } })
|
|
36
|
+
expect(Object.keys(CoreEngine.get()).sort()).toMatchInlineSnapshot(`
|
|
37
|
+
[
|
|
38
|
+
"Bls",
|
|
39
|
+
"Ed25519",
|
|
40
|
+
"Hash",
|
|
41
|
+
"Keystore",
|
|
42
|
+
"Mnemonic",
|
|
43
|
+
"X25519",
|
|
44
|
+
]
|
|
45
|
+
`)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('behavior: installs, and returns what it installed', async () => {
|
|
49
|
+
const before = Hash.sha256('0xdeadbeef')
|
|
50
|
+
|
|
51
|
+
const engine = await Engine.install()
|
|
52
|
+
|
|
53
|
+
expect(Object.keys(CoreEngine.get())).toEqual(Object.keys(engine))
|
|
54
|
+
// Installing changes which implementation runs, never the answer.
|
|
55
|
+
expect(Hash.sha256('0xdeadbeef')).toEqual(before)
|
|
56
|
+
expect(Engine.get()).toEqual(CoreEngine.get())
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('behavior: routes every slot it reports', async () => {
|
|
60
|
+
await Engine.install()
|
|
61
|
+
expect(
|
|
62
|
+
Object.fromEntries(
|
|
63
|
+
Object.entries(CoreEngine.get()).map(([slot, value]) => [
|
|
64
|
+
slot,
|
|
65
|
+
Object.keys(value ?? {}).sort(),
|
|
66
|
+
]),
|
|
67
|
+
),
|
|
68
|
+
).toMatchInlineSnapshot(`
|
|
69
|
+
{
|
|
70
|
+
"Ed25519": [
|
|
71
|
+
"getPublicKey",
|
|
72
|
+
"sign",
|
|
73
|
+
"toMontgomerySecret",
|
|
74
|
+
"verify",
|
|
75
|
+
],
|
|
76
|
+
"Hash": [
|
|
77
|
+
"blake3",
|
|
78
|
+
"hmacSha256",
|
|
79
|
+
"keccak256",
|
|
80
|
+
"ripemd160",
|
|
81
|
+
"sha256",
|
|
82
|
+
],
|
|
83
|
+
"Keystore": [
|
|
84
|
+
"pbkdf2Sha256",
|
|
85
|
+
],
|
|
86
|
+
"Mnemonic": [
|
|
87
|
+
"toSeed",
|
|
88
|
+
],
|
|
89
|
+
"X25519": [
|
|
90
|
+
"getPublicKey",
|
|
91
|
+
"getSharedSecret",
|
|
92
|
+
],
|
|
93
|
+
}
|
|
94
|
+
`)
|
|
95
|
+
})
|
|
96
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { blake3 } from '@noble/hashes/blake3.js'
|
|
2
|
+
import { keccak_256 } from '@noble/hashes/sha3.js'
|
|
3
|
+
import { describe, expect, test, vi } from 'vp/test'
|
|
4
|
+
import * as Engine from '../../core/Engine.js'
|
|
5
|
+
import * as Hash from '../../core/Hash.js'
|
|
6
|
+
import * as WasmHash from '../Hash.js'
|
|
7
|
+
|
|
8
|
+
describe('engine', () => {
|
|
9
|
+
test('behavior: instantiates asynchronously', async () => {
|
|
10
|
+
// Chrome refuses to compile modules above a few kilobytes synchronously on
|
|
11
|
+
// the main thread, so `new WebAssembly.Module` must never be reached. A spy
|
|
12
|
+
// is the only way to assert that, since the artifact happens to be small
|
|
13
|
+
// enough today that a synchronous compile would succeed.
|
|
14
|
+
const Module = vi.spyOn(globalThis.WebAssembly, 'Module')
|
|
15
|
+
const Instance = vi.spyOn(globalThis.WebAssembly, 'Instance')
|
|
16
|
+
try {
|
|
17
|
+
const engine = await WasmHash.engine()
|
|
18
|
+
expect(Module).not.toHaveBeenCalled()
|
|
19
|
+
expect(Instance).not.toHaveBeenCalled()
|
|
20
|
+
|
|
21
|
+
const input = new Uint8Array(32).fill(1)
|
|
22
|
+
expect(engine.keccak256(input)).toEqual(keccak_256(input))
|
|
23
|
+
expect(engine.blake3(input)).toEqual(blake3(input))
|
|
24
|
+
} finally {
|
|
25
|
+
Module.mockRestore()
|
|
26
|
+
Instance.mockRestore()
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('behavior: grows memory in a real browser, then hashes a small input', async () => {
|
|
31
|
+
const engine = await WasmHash.engine()
|
|
32
|
+
|
|
33
|
+
const large = new Uint8Array(3 * 1024 * 1024).fill(7)
|
|
34
|
+
expect(engine.keccak256(large)).toEqual(keccak_256(large))
|
|
35
|
+
expect(engine.blake3(large)).toEqual(blake3(large))
|
|
36
|
+
|
|
37
|
+
// `memory.grow` detached the previous `ArrayBuffer`; a retained view would
|
|
38
|
+
// now read zero bytes.
|
|
39
|
+
const small = new Uint8Array(32).fill(1)
|
|
40
|
+
expect(engine.keccak256(small)).toEqual(keccak_256(small))
|
|
41
|
+
expect(engine.blake3(small)).toEqual(blake3(small))
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('behavior: ox uses the WASM implementation once installed', async () => {
|
|
45
|
+
await Engine.install({ Hash: WasmHash.engine() })
|
|
46
|
+
try {
|
|
47
|
+
expect(Hash.keccak256('0xdeadbeef')).toBe(
|
|
48
|
+
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1',
|
|
49
|
+
)
|
|
50
|
+
} finally {
|
|
51
|
+
Engine.reset()
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
})
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { fc, test } from '@fast-check/vitest'
|
|
2
|
+
import { blake3 } from '@noble/hashes/blake3.js'
|
|
3
|
+
import { hmac } from '@noble/hashes/hmac.js'
|
|
4
|
+
import { ripemd160 } from '@noble/hashes/legacy.js'
|
|
5
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
6
|
+
import { keccak_256 } from '@noble/hashes/sha3.js'
|
|
7
|
+
import { Hash as WasmHash } from 'ox/wasm'
|
|
8
|
+
import { beforeAll, describe, expect } from 'vp/test'
|
|
9
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
10
|
+
|
|
11
|
+
let engine: WasmHash.engine.ReturnType
|
|
12
|
+
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
engine = await WasmHash.engine()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `@noble/hashes` is the oracle: it is audited and it is what ox ships by
|
|
19
|
+
* default, so any divergence here is a bug in the WASM implementation. Published
|
|
20
|
+
* vectors live in `Hash.vectors.test.ts` and cover the case where both
|
|
21
|
+
* implementations could be wrong together.
|
|
22
|
+
*
|
|
23
|
+
* The distribution is weighted toward the sizes where padding and block-boundary
|
|
24
|
+
* bugs hide -- empty input, exact multiples of the keccak256 rate (136) and the
|
|
25
|
+
* SHA-2 block (64), BLAKE3 chunk (1024), and the 56-byte threshold at which
|
|
26
|
+
* the SHA-2 length counter no longer fits in the final block.
|
|
27
|
+
*/
|
|
28
|
+
const arbitraryInput = fc.oneof(
|
|
29
|
+
{ arbitrary: fc.uint8Array({ maxLength: 300, minLength: 0 }), weight: 6 },
|
|
30
|
+
{
|
|
31
|
+
arbitrary: fc
|
|
32
|
+
.constantFrom(
|
|
33
|
+
0,
|
|
34
|
+
1,
|
|
35
|
+
55,
|
|
36
|
+
56,
|
|
37
|
+
63,
|
|
38
|
+
64,
|
|
39
|
+
65,
|
|
40
|
+
111,
|
|
41
|
+
112,
|
|
42
|
+
135,
|
|
43
|
+
136,
|
|
44
|
+
137,
|
|
45
|
+
272,
|
|
46
|
+
1023,
|
|
47
|
+
1024,
|
|
48
|
+
1025,
|
|
49
|
+
2048,
|
|
50
|
+
2049,
|
|
51
|
+
)
|
|
52
|
+
.chain((size) => fc.uint8Array({ maxLength: size, minLength: size })),
|
|
53
|
+
weight: 3,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
arbitrary: fc.uint8Array({ maxLength: 4096, minLength: 1024 }),
|
|
57
|
+
weight: 1,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* HMAC key lengths straddling the 64-byte block. At or under it the key is
|
|
63
|
+
* zero-padded; over it, it is hashed first -- a different code path that the
|
|
64
|
+
* message-shaped arbitrary above would only reach by chance.
|
|
65
|
+
*/
|
|
66
|
+
const arbitraryKey = fc.oneof(
|
|
67
|
+
{
|
|
68
|
+
arbitrary: fc
|
|
69
|
+
.constantFrom(0, 1, 32, 63, 64, 65, 96, 128, 129)
|
|
70
|
+
.chain((size) => fc.uint8Array({ maxLength: size, minLength: size })),
|
|
71
|
+
weight: 3,
|
|
72
|
+
},
|
|
73
|
+
{ arbitrary: fc.uint8Array({ maxLength: 200, minLength: 0 }), weight: 1 },
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const primitives = {
|
|
77
|
+
blake3: {
|
|
78
|
+
reference: (input: Uint8Array) => blake3(input),
|
|
79
|
+
wasm: (input: Uint8Array) => engine.blake3(input),
|
|
80
|
+
},
|
|
81
|
+
hmacSha256: {
|
|
82
|
+
reference: (input: Uint8Array, key: Uint8Array) => hmac(sha256, key, input),
|
|
83
|
+
wasm: (input: Uint8Array, key: Uint8Array) => engine.hmacSha256(key, input),
|
|
84
|
+
},
|
|
85
|
+
keccak256: {
|
|
86
|
+
reference: (input: Uint8Array) => keccak_256(input),
|
|
87
|
+
wasm: (input: Uint8Array) => engine.keccak256(input),
|
|
88
|
+
},
|
|
89
|
+
ripemd160: {
|
|
90
|
+
reference: (input: Uint8Array) => ripemd160(input),
|
|
91
|
+
wasm: (input: Uint8Array) => engine.ripemd160(input),
|
|
92
|
+
},
|
|
93
|
+
sha256: {
|
|
94
|
+
reference: (input: Uint8Array) => sha256(input),
|
|
95
|
+
wasm: (input: Uint8Array) => engine.sha256(input),
|
|
96
|
+
},
|
|
97
|
+
} as const
|
|
98
|
+
|
|
99
|
+
type Name = keyof typeof primitives
|
|
100
|
+
|
|
101
|
+
describe('Hash', () => {
|
|
102
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
103
|
+
'blake3 ≡ @noble/hashes',
|
|
104
|
+
({ input }) => {
|
|
105
|
+
expect(engine.blake3(input)).toEqual(blake3(input))
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
110
|
+
'keccak256 ≡ @noble/hashes',
|
|
111
|
+
({ input }) => {
|
|
112
|
+
expect(engine.keccak256(input)).toEqual(keccak_256(input))
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
117
|
+
'sha256 ≡ @noble/hashes',
|
|
118
|
+
({ input }) => {
|
|
119
|
+
expect(engine.sha256(input)).toEqual(sha256(input))
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
124
|
+
'ripemd160 ≡ @noble/hashes',
|
|
125
|
+
({ input }) => {
|
|
126
|
+
expect(engine.ripemd160(input)).toEqual(ripemd160(input))
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
test.prop({ input: arbitraryInput, key: arbitraryKey }, { numRuns })(
|
|
131
|
+
'hmacSha256 ≡ @noble/hashes',
|
|
132
|
+
({ input, key }) => {
|
|
133
|
+
expect(engine.hmacSha256(key, input)).toEqual(hmac(sha256, key, input))
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('memory', () => {
|
|
139
|
+
test.prop(
|
|
140
|
+
{
|
|
141
|
+
operations: fc.array(
|
|
142
|
+
fc.record({
|
|
143
|
+
input: arbitraryInput,
|
|
144
|
+
key: arbitraryKey,
|
|
145
|
+
name: fc.constantFrom<Name>(
|
|
146
|
+
'blake3',
|
|
147
|
+
'hmacSha256',
|
|
148
|
+
'keccak256',
|
|
149
|
+
'ripemd160',
|
|
150
|
+
'sha256',
|
|
151
|
+
),
|
|
152
|
+
}),
|
|
153
|
+
{ maxLength: 24, minLength: 2 },
|
|
154
|
+
),
|
|
155
|
+
},
|
|
156
|
+
{ numRuns },
|
|
157
|
+
)('an arbitrary sequence of calls agrees at every step', ({ operations }) => {
|
|
158
|
+
// Every primitive shares one region of WASM linear memory, reusing it call
|
|
159
|
+
// after call. A mis-sized reservation, an off-by-one write, or a digest read
|
|
160
|
+
// from the wrong offset can leave earlier bytes behind and still produce a
|
|
161
|
+
// correct answer in isolation -- it only shows up when calls of differing
|
|
162
|
+
// sizes and kinds are interleaved. Comparing every step of a random sequence
|
|
163
|
+
// is what catches that; a fixed a/b/a pattern does not.
|
|
164
|
+
for (const { input, key, name } of operations) {
|
|
165
|
+
const primitive = primitives[name]
|
|
166
|
+
expect(
|
|
167
|
+
primitive.wasm(input, key),
|
|
168
|
+
`${name} with a ${input.length} byte input`,
|
|
169
|
+
).toEqual(primitive.reference(input, key))
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test.prop(
|
|
174
|
+
{
|
|
175
|
+
sizes: fc.array(fc.integer({ max: 20, min: 0 }), {
|
|
176
|
+
maxLength: 6,
|
|
177
|
+
minLength: 2,
|
|
178
|
+
}),
|
|
179
|
+
},
|
|
180
|
+
{ numRuns: Math.min(numRuns, 20) },
|
|
181
|
+
)('repeated growth keeps results correct', ({ sizes }) => {
|
|
182
|
+
// Each size is a page count. Going up grows linear memory and detaches the
|
|
183
|
+
// previous `ArrayBuffer`; coming back down must not, since WASM memory never
|
|
184
|
+
// shrinks. Either way the view has to be re-derived, and a stale one reads
|
|
185
|
+
// as zeroes rather than throwing.
|
|
186
|
+
for (const pages of sizes) {
|
|
187
|
+
const input = new Uint8Array(pages * 65_536).fill(pages & 0xff)
|
|
188
|
+
expect(engine.keccak256(input), `${pages} pages`).toEqual(
|
|
189
|
+
keccak_256(input),
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
195
|
+
'digests never alias WASM memory',
|
|
196
|
+
({ input }) => {
|
|
197
|
+
// A digest returned as a view over linear memory would be silently
|
|
198
|
+
// rewritten by the next call. Hold one across a larger call and check it.
|
|
199
|
+
const digest = engine.keccak256(input)
|
|
200
|
+
const snapshot = digest.slice()
|
|
201
|
+
engine.keccak256(new Uint8Array(input.length + 1024).fill(0xaa))
|
|
202
|
+
expect(digest).toEqual(snapshot)
|
|
203
|
+
|
|
204
|
+
const blake3Digest = engine.blake3(input)
|
|
205
|
+
const blake3Snapshot = blake3Digest.slice()
|
|
206
|
+
engine.blake3(new Uint8Array(input.length + 1024).fill(0xaa))
|
|
207
|
+
expect(blake3Digest).toEqual(blake3Snapshot)
|
|
208
|
+
},
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
test.prop({ input: arbitraryInput }, { numRuns })(
|
|
212
|
+
'inputs are not mutated',
|
|
213
|
+
({ input }) => {
|
|
214
|
+
const snapshot = input.slice()
|
|
215
|
+
engine.blake3(input)
|
|
216
|
+
engine.keccak256(input)
|
|
217
|
+
engine.sha256(input)
|
|
218
|
+
engine.ripemd160(input)
|
|
219
|
+
engine.hmacSha256(input, input)
|
|
220
|
+
expect(input).toEqual(snapshot)
|
|
221
|
+
},
|
|
222
|
+
)
|
|
223
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Hash as WasmHash } from 'ox/wasm'
|
|
2
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
3
|
+
import type * as CoreEngine from '../../core/Engine.js'
|
|
4
|
+
import * as CoreHash from '../../core/Hash.js'
|
|
5
|
+
|
|
6
|
+
type Slot = Awaited<ReturnType<typeof WasmHash.engine>>
|
|
7
|
+
|
|
8
|
+
test('every primitive is present, so callers need no assertion', () => {
|
|
9
|
+
expectTypeOf<Slot['blake3']>().toEqualTypeOf<
|
|
10
|
+
(input: Uint8Array) => Uint8Array
|
|
11
|
+
>()
|
|
12
|
+
expectTypeOf<Slot['keccak256']>().toEqualTypeOf<
|
|
13
|
+
(input: Uint8Array) => Uint8Array
|
|
14
|
+
>()
|
|
15
|
+
expectTypeOf<Slot['sha256']>().toEqualTypeOf<
|
|
16
|
+
(input: Uint8Array) => Uint8Array
|
|
17
|
+
>()
|
|
18
|
+
expectTypeOf<Slot['ripemd160']>().toEqualTypeOf<
|
|
19
|
+
(input: Uint8Array) => Uint8Array
|
|
20
|
+
>()
|
|
21
|
+
expectTypeOf<Slot['hmacSha256']>().toEqualTypeOf<
|
|
22
|
+
(key: Uint8Array, message: Uint8Array) => Uint8Array
|
|
23
|
+
>()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('the result is the raw slot, so `Engine.install` accepts it', () => {
|
|
27
|
+
expectTypeOf<{ Hash: Slot }>().toExtend<CoreEngine.Engine>()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('the WASM namespace exposes the public Hash API', () => {
|
|
31
|
+
expectTypeOf(WasmHash.sha256).toEqualTypeOf(CoreHash.sha256)
|
|
32
|
+
expectTypeOf<typeof WasmHash>().not.toHaveProperty('create')
|
|
33
|
+
})
|