ox 1.0.4 → 1.1.0
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 +62 -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 +124 -0
- package/dist/core/Engine.d.ts.map +1 -0
- package/dist/core/Engine.js +180 -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 +35 -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 +35 -0
- package/dist/index.js.map +1 -1
- package/dist/node/Engine.d.ts +55 -0
- package/dist/node/Engine.d.ts.map +1 -0
- package/dist/node/Engine.js +51 -0
- package/dist/node/Engine.js.map +1 -0
- package/dist/node/Hash.d.ts +39 -0
- package/dist/node/Hash.d.ts.map +1 -0
- package/dist/node/Hash.js +37 -0
- package/dist/node/Hash.js.map +1 -0
- package/dist/node/index.d.ts +39 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +39 -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/ZoneId.d.ts +35 -17
- package/dist/tempo/ZoneId.d.ts.map +1 -1
- package/dist/tempo/ZoneId.js +41 -16
- package/dist/tempo/ZoneId.js.map +1 -1
- package/dist/tempo/index.d.ts +5 -6
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +5 -6
- package/dist/tempo/index.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/Engine.d.ts +62 -0
- package/dist/wasm/Engine.d.ts.map +1 -0
- package/dist/wasm/Engine.js +57 -0
- package/dist/wasm/Engine.js.map +1 -0
- package/dist/wasm/Hash.d.ts +49 -0
- package/dist/wasm/Hash.d.ts.map +1 -0
- package/dist/wasm/Hash.js +70 -0
- package/dist/wasm/Hash.js.map +1 -0
- package/dist/wasm/index.d.ts +46 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js +46 -0
- package/dist/wasm/index.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.wasm.d.ts +5 -0
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.wasm.js +12 -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/zod/TypedData.d.ts +12 -12
- package/package.json +36 -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 +235 -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 +84 -0
- package/src/core/_test/Engine.test.ts +523 -0
- package/src/core/_test/Hash.vectors.test.ts +56 -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 +36 -0
- package/src/node/Engine.ts +69 -0
- package/src/node/Hash.ts +56 -0
- package/src/node/_test/Engine.test.ts +62 -0
- package/src/node/_test/Hash.test-d.ts +26 -0
- package/src/node/_test/Hash.test.ts +102 -0
- package/src/node/index.ts +40 -0
- package/src/tempo/VirtualMaster.test.ts +75 -0
- package/src/tempo/VirtualMaster.ts +28 -6
- package/src/tempo/ZoneId.test-d.ts +16 -0
- package/src/tempo/ZoneId.test.ts +48 -13
- package/src/tempo/ZoneId.ts +55 -19
- package/src/tempo/index.ts +5 -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/Engine.ts +76 -0
- package/src/wasm/Hash.bench.ts +60 -0
- package/src/wasm/Hash.ts +109 -0
- package/src/wasm/_test/Engine.test.ts +62 -0
- package/src/wasm/_test/Hash.browser.test.ts +50 -0
- package/src/wasm/_test/Hash.fuzz.ts +188 -0
- package/src/wasm/_test/Hash.test-d.ts +28 -0
- package/src/wasm/_test/Hash.test.ts +211 -0
- package/src/wasm/_test/Hash.vectors.test.ts +117 -0
- package/src/wasm/_test/Runtime.test.ts +21 -0
- package/src/wasm/_test/runtime.wasm.ts +11 -0
- package/src/wasm/index.ts +47 -0
- package/src/wasm/internal/hash.ts +50 -0
- package/src/wasm/internal/hashes.wasm.ts +14 -0
- package/src/wasm/internal/instantiate.ts +135 -0
- package/src/zod/tempo/_test/ZoneId.test.ts +2 -2
- package/src/tempo/internal/mine.c +0 -182
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { hmac } from '@noble/hashes/hmac.js'
|
|
2
|
+
import { ripemd160 } from '@noble/hashes/legacy.js'
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
4
|
+
import { keccak_256 } from '@noble/hashes/sha3.js'
|
|
5
|
+
import { Bytes, Engine, Hash } from 'ox'
|
|
6
|
+
import { Hash as WasmHash } from 'ox/wasm'
|
|
7
|
+
import { beforeAll, describe, expect, test } from 'vp/test'
|
|
8
|
+
import { hmacSha256ScratchSize, wasmBase64 } from '../internal/hashes.wasm.js'
|
|
9
|
+
import * as hash from '../internal/hash.js'
|
|
10
|
+
import * as internal from '../internal/instantiate.js'
|
|
11
|
+
|
|
12
|
+
let engine: WasmHash.create.ReturnType
|
|
13
|
+
|
|
14
|
+
beforeAll(async () => {
|
|
15
|
+
engine = await WasmHash.create()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('create', () => {
|
|
19
|
+
test('default', async () => {
|
|
20
|
+
expect(Object.keys(await WasmHash.create())).toMatchInlineSnapshot(`
|
|
21
|
+
[
|
|
22
|
+
"Hash",
|
|
23
|
+
]
|
|
24
|
+
`)
|
|
25
|
+
expect(Object.keys((await WasmHash.create()).Hash)).toMatchInlineSnapshot(`
|
|
26
|
+
[
|
|
27
|
+
"hmacSha256",
|
|
28
|
+
"keccak256",
|
|
29
|
+
"ripemd160",
|
|
30
|
+
"sha256",
|
|
31
|
+
]
|
|
32
|
+
`)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('behavior: hands every caller its own engine', async () => {
|
|
36
|
+
const [a, b] = await Promise.all([WasmHash.create(), WasmHash.create()])
|
|
37
|
+
|
|
38
|
+
// Deliberately not the same object. A shared slot lets one caller's
|
|
39
|
+
// customisation for composition leak into what a later `create` -- or
|
|
40
|
+
// `Engine.load` -- installs.
|
|
41
|
+
expect(a).not.toBe(b)
|
|
42
|
+
expect(a.Hash).not.toBe(b.Hash)
|
|
43
|
+
|
|
44
|
+
a.Hash.keccak256 = () => new Uint8Array(32).fill(9)
|
|
45
|
+
const c = await WasmHash.create()
|
|
46
|
+
expect(c.Hash.keccak256(Bytes.from('0xdeadbeef'))).toEqual(
|
|
47
|
+
b.Hash.keccak256(Bytes.from('0xdeadbeef')),
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// Sizes chosen around the block boundaries where padding bugs live: keccak256's
|
|
53
|
+
// rate is 136 bytes, sha256 and ripemd160 use 64-byte blocks and need a second
|
|
54
|
+
// block once the remainder reaches 56.
|
|
55
|
+
const sizes = [
|
|
56
|
+
0, 1, 2, 31, 32, 55, 56, 63, 64, 65, 71, 72, 111, 135, 136, 137, 199, 200,
|
|
57
|
+
271, 272, 1000,
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
function input(size: number) {
|
|
61
|
+
return new Uint8Array(size).map((_, index) => (index * 37 + 11) & 0xff)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe('Hash', () => {
|
|
65
|
+
test.each(sizes)('keccak256 matches the default at %i bytes', (size) => {
|
|
66
|
+
expect(engine.Hash.keccak256(input(size))).toEqual(keccak_256(input(size)))
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test.each(sizes)('sha256 matches the default at %i bytes', (size) => {
|
|
70
|
+
expect(engine.Hash.sha256(input(size))).toEqual(sha256(input(size)))
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test.each(sizes)('ripemd160 matches the default at %i bytes', (size) => {
|
|
74
|
+
expect(engine.Hash.ripemd160(input(size))).toEqual(ripemd160(input(size)))
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test.each([0, 1, 32, 63, 64, 65, 200])(
|
|
78
|
+
'hmacSha256 matches the default with a %i byte key',
|
|
79
|
+
(size) => {
|
|
80
|
+
const key = new Uint8Array(size).fill(0xa5)
|
|
81
|
+
const message = input(100)
|
|
82
|
+
expect(engine.Hash.hmacSha256(key, message)).toEqual(
|
|
83
|
+
hmac(sha256, key, message),
|
|
84
|
+
)
|
|
85
|
+
},
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
test('behavior: known vectors', () => {
|
|
89
|
+
expect(Bytes.toHex(engine.Hash.keccak256(new Uint8Array(0)))).toBe(
|
|
90
|
+
'0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
|
|
91
|
+
)
|
|
92
|
+
expect(Bytes.toHex(engine.Hash.sha256(new Uint8Array(0)))).toBe(
|
|
93
|
+
'0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
|
|
94
|
+
)
|
|
95
|
+
expect(Bytes.toHex(engine.Hash.ripemd160(new Uint8Array(0)))).toBe(
|
|
96
|
+
'0x9c1185a5c5e9fc54612808977ee8f548b2258d31',
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('behavior: grows memory past 64 MiB, then still hashes small inputs', () => {
|
|
101
|
+
// The input itself is exactly 64 MiB, so the heap base and digest force
|
|
102
|
+
// memory past that boundary. Growing detaches the previous `ArrayBuffer`; a
|
|
103
|
+
// retained view would silently read zero bytes in the assertion below.
|
|
104
|
+
const large = new Uint8Array(64 * 1024 * 1024).fill(7)
|
|
105
|
+
expect(engine.Hash.sha256(large)).toEqual(sha256(large))
|
|
106
|
+
|
|
107
|
+
const small = input(32)
|
|
108
|
+
expect(engine.Hash.sha256(small)).toEqual(sha256(small))
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('behavior: hmacSha256 clears its complete memory region', async () => {
|
|
112
|
+
const module = await internal.instantiate<hash.Exports>(wasmBase64)
|
|
113
|
+
const key = input(120)
|
|
114
|
+
const message = input(17)
|
|
115
|
+
const out = 32
|
|
116
|
+
const messagePtr = module.heapBase
|
|
117
|
+
const keyPtr = messagePtr + message.length
|
|
118
|
+
const outPtr = keyPtr + key.length
|
|
119
|
+
const scratchPtr = Math.ceil((outPtr + out) / 4) * 4
|
|
120
|
+
const end = scratchPtr + hmacSha256ScratchSize
|
|
121
|
+
const stack = module.view().slice(0, module.heapBase)
|
|
122
|
+
|
|
123
|
+
expect(hash.hmacSha256(module, key, message)).toEqual(
|
|
124
|
+
hmac(sha256, key, message),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
expect(module.view().slice(0, module.heapBase)).toEqual(stack)
|
|
128
|
+
expect(module.view().slice(messagePtr, end)).toEqual(
|
|
129
|
+
new Uint8Array(end - messagePtr),
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('behavior: hmacSha256 clears its complete region after a trap', async () => {
|
|
134
|
+
const module = await internal.instantiate<hash.Exports>(wasmBase64)
|
|
135
|
+
const key = input(120)
|
|
136
|
+
const message = input(17)
|
|
137
|
+
const out = 32
|
|
138
|
+
const messagePtr = module.heapBase
|
|
139
|
+
const keyPtr = messagePtr + message.length
|
|
140
|
+
const validOutPtr = keyPtr + key.length
|
|
141
|
+
const scratchPtr = Math.ceil((validOutPtr + out) / 4) * 4
|
|
142
|
+
const end = scratchPtr + hmacSha256ScratchSize
|
|
143
|
+
const stack = module.view().slice(0, module.heapBase)
|
|
144
|
+
// Preserve the production boundary while making the real export trap only
|
|
145
|
+
// after it has populated the scratch buffer.
|
|
146
|
+
const exports = {
|
|
147
|
+
hmac_sha256(
|
|
148
|
+
keyPtr: number,
|
|
149
|
+
keyLength: number,
|
|
150
|
+
messagePtr: number,
|
|
151
|
+
messageLength: number,
|
|
152
|
+
_outPtr: number,
|
|
153
|
+
scratchPtr: number,
|
|
154
|
+
) {
|
|
155
|
+
module.exports.hmac_sha256(
|
|
156
|
+
keyPtr,
|
|
157
|
+
keyLength,
|
|
158
|
+
messagePtr,
|
|
159
|
+
messageLength,
|
|
160
|
+
module.view().length - 16,
|
|
161
|
+
scratchPtr,
|
|
162
|
+
)
|
|
163
|
+
},
|
|
164
|
+
zero: (ptr: number, length: number) => module.exports.zero(ptr, length),
|
|
165
|
+
}
|
|
166
|
+
const trappingModule = { ...module, exports }
|
|
167
|
+
|
|
168
|
+
expect(() => hash.hmacSha256(trappingModule, key, message)).toThrow(
|
|
169
|
+
WebAssembly.RuntimeError,
|
|
170
|
+
)
|
|
171
|
+
expect(module.view().slice(0, module.heapBase)).toEqual(stack)
|
|
172
|
+
expect(module.view().slice(messagePtr, end)).toEqual(
|
|
173
|
+
new Uint8Array(end - messagePtr),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
module.exports.zero(module.view().length - 16, 16)
|
|
177
|
+
expect(hash.hmacSha256(module, key, message)).toEqual(
|
|
178
|
+
hmac(sha256, key, message),
|
|
179
|
+
)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
test('behavior: consecutive calls do not corrupt each other', () => {
|
|
183
|
+
const a = input(200)
|
|
184
|
+
const b = input(7)
|
|
185
|
+
expect(engine.Hash.keccak256(a)).toEqual(keccak_256(a))
|
|
186
|
+
expect(engine.Hash.keccak256(b)).toEqual(keccak_256(b))
|
|
187
|
+
expect(engine.Hash.keccak256(a)).toEqual(keccak_256(a))
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('behavior: results do not alias WASM memory', () => {
|
|
191
|
+
const first = engine.Hash.keccak256(input(32))
|
|
192
|
+
const snapshot = first.slice()
|
|
193
|
+
engine.Hash.keccak256(input(64))
|
|
194
|
+
expect(first).toEqual(snapshot)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('Engine.set', () => {
|
|
199
|
+
test('behavior: ox uses the WASM implementation once installed', () => {
|
|
200
|
+
Engine.set(engine)
|
|
201
|
+
expect(Hash.keccak256('0xdeadbeef')).toBe(
|
|
202
|
+
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1',
|
|
203
|
+
)
|
|
204
|
+
expect(Hash.sha256('0xdeadbeef')).toBe(
|
|
205
|
+
'0x5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953',
|
|
206
|
+
)
|
|
207
|
+
expect(Hash.ripemd160('0xdeadbeef')).toBe(
|
|
208
|
+
'0x226821c2f5423e11fe9af68bd285c249db2e4b5a',
|
|
209
|
+
)
|
|
210
|
+
})
|
|
211
|
+
})
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Hash as WasmHash } from 'ox/wasm'
|
|
2
|
+
import { beforeAll, describe, expect, test } from 'vp/test'
|
|
3
|
+
import * as vectors from '../../../test/vectors/hashes/index.js'
|
|
4
|
+
import { wasmBase64 } from '../internal/hashes.wasm.js'
|
|
5
|
+
import { instantiate } from '../internal/instantiate.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Published vectors against the WASM implementations.
|
|
9
|
+
*
|
|
10
|
+
* The differential tests in `Hash.test.ts` and `Hash.fuzz.ts` prove the WASM
|
|
11
|
+
* agrees with `@noble/hashes`. These prove it agrees with the specifications, so
|
|
12
|
+
* a fault the two implementations happened to share would still be caught.
|
|
13
|
+
* See `test/vectors/hashes/README.md`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
let engine: WasmHash.create.ReturnType
|
|
17
|
+
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
engine = await WasmHash.create()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
describe('sha256', () => {
|
|
23
|
+
test(`matches ${vectors.sha256.length} NIST CAVP vectors`, () => {
|
|
24
|
+
for (const { digest, message } of vectors.sha256)
|
|
25
|
+
expect(engine.Hash.sha256(message)).toEqual(digest)
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('hmacSha256', () => {
|
|
30
|
+
test(`matches ${vectors.hmacSha256.length} RFC 4231 vectors`, () => {
|
|
31
|
+
// Two of these use 131-byte keys, which is the only coverage of the
|
|
32
|
+
// longer-than-a-block path where the key is hashed before padding.
|
|
33
|
+
for (const { digest, key, message } of vectors.hmacSha256)
|
|
34
|
+
expect(engine.Hash.hmacSha256(key, message)).toEqual(digest)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('ripemd160', () => {
|
|
39
|
+
test(`matches ${vectors.ripemd160.length} reference vectors`, () => {
|
|
40
|
+
for (const { digest, message } of vectors.ripemd160)
|
|
41
|
+
expect(engine.Hash.ripemd160(message)).toEqual(digest)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('matches the million-`a` reference vector', () => {
|
|
45
|
+
const { digest, message } = vectors.ripemd160MillionA
|
|
46
|
+
expect(engine.Hash.ripemd160(message)).toEqual(digest)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
describe('keccak256', () => {
|
|
51
|
+
test(`matches ${vectors.keccak256.length} OpenSSL vectors`, () => {
|
|
52
|
+
for (const { digest, message } of vectors.keccak256)
|
|
53
|
+
expect(engine.Hash.keccak256(message)).toEqual(digest)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
describe('keccak_f1600', () => {
|
|
58
|
+
type Exports = { keccak_f1600(state: number): void }
|
|
59
|
+
|
|
60
|
+
/** Writes 25 lanes as little-endian 64-bit words, permutes, and reads back. */
|
|
61
|
+
async function permute(lanes: readonly bigint[]) {
|
|
62
|
+
// A separate instance, because this export is not part of the engine and so
|
|
63
|
+
// is deliberately not reachable through `WasmHash.load`.
|
|
64
|
+
const module = await instantiate<Exports>(wasmBase64)
|
|
65
|
+
module.reserve(200)
|
|
66
|
+
const view = module.view()
|
|
67
|
+
for (let lane = 0; lane < 25; lane++) {
|
|
68
|
+
let value = lanes[lane]!
|
|
69
|
+
for (let byte = 0; byte < 8; byte++) {
|
|
70
|
+
view[module.heapBase + lane * 8 + byte] = Number(value & 0xffn)
|
|
71
|
+
value >>= 8n
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports.keccak_f1600(module.heapBase)
|
|
76
|
+
|
|
77
|
+
const after = module.view()
|
|
78
|
+
const result: bigint[] = []
|
|
79
|
+
for (let lane = 0; lane < 25; lane++) {
|
|
80
|
+
let value = 0n
|
|
81
|
+
for (let byte = 7; byte >= 0; byte--)
|
|
82
|
+
value =
|
|
83
|
+
(value << 8n) | BigInt(after[module.heapBase + lane * 8 + byte]!)
|
|
84
|
+
result.push(value)
|
|
85
|
+
}
|
|
86
|
+
return result
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
test('matches the Keccak team‘s reference examples', async () => {
|
|
90
|
+
for (const example of vectors.keccakPermutation.examples)
|
|
91
|
+
expect(await permute(example.input)).toEqual(example.output)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('reference examples chain, so the second is not a restatement', () => {
|
|
95
|
+
// XKCP's second example feeds the first one's output back in. Asserting the
|
|
96
|
+
// link means a parser that silently read the same block twice would fail
|
|
97
|
+
// here rather than quietly halving the coverage above.
|
|
98
|
+
const [first, second] = vectors.keccakPermutation.examples
|
|
99
|
+
expect(second!.input).toEqual(first!.output)
|
|
100
|
+
expect(second!.output).not.toEqual(first!.output)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('the parsed fixture is internally consistent', () => {
|
|
104
|
+
// Checks the fixture, not the implementation. Each `rounds[n]` is the state
|
|
105
|
+
// after round `n`'s iota step, and nothing exported reaches a single round,
|
|
106
|
+
// so per-round agreement is not observable from here -- the permutation
|
|
107
|
+
// itself is covered above, end to end against `input`/`output`. What this
|
|
108
|
+
// catches is a parser that mis-read the file and quietly weakened that.
|
|
109
|
+
const { examples, rhoOffsets, roundConstants } = vectors.keccakPermutation
|
|
110
|
+
expect(roundConstants).toHaveLength(24)
|
|
111
|
+
expect(rhoOffsets).toHaveLength(25)
|
|
112
|
+
for (const example of examples) {
|
|
113
|
+
expect(example.rounds).toHaveLength(24)
|
|
114
|
+
expect(example.rounds.at(-1)).toEqual(example.output)
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { expect, test } from 'vp/test'
|
|
3
|
+
import { instantiate } from '../internal/instantiate.js'
|
|
4
|
+
import { wasmBase64 } from './runtime.wasm.js'
|
|
5
|
+
|
|
6
|
+
test('freestanding runtime preserves memmove and realloc semantics', async () => {
|
|
7
|
+
const module = await instantiate<{ run(): number }>(wasmBase64)
|
|
8
|
+
expect(module.exports.run()).toBe(0)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('memmove compares flat-memory offsets rather than C object pointers', () => {
|
|
12
|
+
const source = readFileSync(
|
|
13
|
+
new URL('../../../wasm/src/ox_rt.c', import.meta.url),
|
|
14
|
+
'utf8',
|
|
15
|
+
)
|
|
16
|
+
const body = source.match(/void \*memmove\([\s\S]*?\n}\n\nvoid \*memset/)?.[0]
|
|
17
|
+
|
|
18
|
+
expect(body).toBeDefined()
|
|
19
|
+
expect(body).toContain('if ((size_t)d < (size_t)s)')
|
|
20
|
+
expect(body).not.toMatch(/if\s*\(\s*d\s*<\s*s\s*\)/)
|
|
21
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Generated by `pnpm wasm:build --target=runtime-test`. Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// Compiled from wasm/test/ox_rt.c, wasm/src/ox_rt.c
|
|
4
|
+
// with wasi-sdk 25.0 + binaryen 123.
|
|
5
|
+
//
|
|
6
|
+
// `pnpm wasm:check` rebuilds this file and fails if the bytes differ, so any
|
|
7
|
+
// change to the C or to `wasm/targets.ts` must be followed by `pnpm wasm:build`.
|
|
8
|
+
|
|
9
|
+
/** Base64-encoded WASM binary. */
|
|
10
|
+
export const wasmBase64 =
|
|
11
|
+
'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'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** @entrypointCategory WASM */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* WASM implementations of ox's hash primitives, compiled from C.
|
|
5
|
+
*
|
|
6
|
+
* Load it and hand the result to {@link ox#Engine.set}. WASM must be compiled
|
|
7
|
+
* asynchronously, so the `await` lives here -- every call afterwards is
|
|
8
|
+
* synchronous.
|
|
9
|
+
*
|
|
10
|
+
* :::note
|
|
11
|
+
* Performance varies by primitive, input size, runtime, and processor. Run
|
|
12
|
+
* `pnpm bench:engines` to compare the available implementations on your target
|
|
13
|
+
* machine.
|
|
14
|
+
* :::
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts twoslash
|
|
18
|
+
* // @noErrors
|
|
19
|
+
* import { Hash } from 'ox'
|
|
20
|
+
* import { Engine } from 'ox/wasm'
|
|
21
|
+
*
|
|
22
|
+
* await Engine.load()
|
|
23
|
+
*
|
|
24
|
+
* Hash.keccak256('0xdeadbeef')
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @category Crypto
|
|
28
|
+
*/
|
|
29
|
+
export * as Engine from './Engine.js'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* WASM implementations of Ox's supported hash primitives.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts twoslash
|
|
36
|
+
* // @noErrors
|
|
37
|
+
* import { Engine, Hash } from 'ox'
|
|
38
|
+
* import * as WasmHash from 'ox/wasm/Hash'
|
|
39
|
+
*
|
|
40
|
+
* Engine.set(await WasmHash.create())
|
|
41
|
+
*
|
|
42
|
+
* Hash.keccak256('0xdeadbeef')
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @category Crypto
|
|
46
|
+
*/
|
|
47
|
+
export * as Hash from './Hash.js'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { hmacSha256ScratchSize } from './hashes.wasm.js'
|
|
2
|
+
import type { Module } from './instantiate.js'
|
|
3
|
+
|
|
4
|
+
/** WASM exports used by the HMAC-SHA256 loader. @internal */
|
|
5
|
+
export type Exports = {
|
|
6
|
+
hmac_sha256(
|
|
7
|
+
key: number,
|
|
8
|
+
keyLength: number,
|
|
9
|
+
message: number,
|
|
10
|
+
messageLength: number,
|
|
11
|
+
out: number,
|
|
12
|
+
scratch: number,
|
|
13
|
+
): void
|
|
14
|
+
zero(ptr: number, length: number): void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Calls HMAC-SHA256 and clears its complete linear-memory region. @internal */
|
|
18
|
+
export function hmacSha256(
|
|
19
|
+
module: Module<Exports>,
|
|
20
|
+
key: Uint8Array,
|
|
21
|
+
message: Uint8Array,
|
|
22
|
+
): Uint8Array {
|
|
23
|
+
const keyLength = key.length
|
|
24
|
+
const messageLength = message.length
|
|
25
|
+
const out = 32
|
|
26
|
+
const messagePtr = module.heapBase
|
|
27
|
+
const keyPtr = messagePtr + messageLength
|
|
28
|
+
const outPtr = keyPtr + keyLength
|
|
29
|
+
const scratchPtr = Math.ceil((outPtr + out) / 4) * 4
|
|
30
|
+
const end = scratchPtr + hmacSha256ScratchSize
|
|
31
|
+
module.reserve(end - messagePtr)
|
|
32
|
+
const view = module.view()
|
|
33
|
+
try {
|
|
34
|
+
view.set(message, messagePtr)
|
|
35
|
+
view.set(key, keyPtr)
|
|
36
|
+
module.exports.hmac_sha256(
|
|
37
|
+
keyPtr,
|
|
38
|
+
keyLength,
|
|
39
|
+
messagePtr,
|
|
40
|
+
messageLength,
|
|
41
|
+
outPtr,
|
|
42
|
+
scratchPtr,
|
|
43
|
+
)
|
|
44
|
+
return module.view().slice(outPtr, outPtr + out)
|
|
45
|
+
} finally {
|
|
46
|
+
// Clear every byte this call owns, including HMAC working state when
|
|
47
|
+
// copying, hashing, or copying the digest back out throws.
|
|
48
|
+
module.exports.zero(messagePtr, end - messagePtr)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Generated by `pnpm wasm:build --target=hashes`. Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// Compiled from wasm/src/hashes.c, wasm/src/ox_rt.c
|
|
4
|
+
// with wasi-sdk 25.0 + binaryen 123.
|
|
5
|
+
//
|
|
6
|
+
// `pnpm wasm:check` rebuilds this file and fails if the bytes differ, so any
|
|
7
|
+
// change to the C or to `wasm/targets.ts` must be followed by `pnpm wasm:build`.
|
|
8
|
+
|
|
9
|
+
/** Base64-encoded WASM binary. */
|
|
10
|
+
export const wasmBase64 =
|
|
11
|
+
'AGFzbQEAAAABHQVgA39/fwBgBn9/f39/fwBgAX8AYAJ/fwBgAAF/AwwLAQEAAAICAAMABAMFAwEAEAYIAX8BQfCOBAsHWwgGbWVtb3J5AgAMa2VjY2FrX2YxNjAwAAUJa2VjY2FrMjU2AAMGc2hhMjU2AAgLaG1hY19zaGEyNTYAAAR6ZXJvAAoJcmlwZW1kMTYwAAYJaGVhcF9iYXNlAAkKmTsLvA4CG38BfiAFQgA3ADggBUIANwAwIAVCADcAKCAFQgA3ACAgBUIANwAYIAVCADcAECAFQgA3AAggBUIANwAAIAVB4AFqIQsgBUFAayEMIAVB4ABqIQ0CQCABQcAATQRAIAFFDQEgAUEDcSEHIAFBBE8EQCABQfwAcSEJA0AgBSAGaiIBIAAgBmoiCC0AADoAACABQQFqIAhBAWotAAA6AAAgAUECaiAIQQJqLQAAOgAAIAFBA2ogCEEDai0AADoAACAJIAZBBGoiBkcNAAsLIAdFDQEgACAGaiEBIAUgBmohBgNAIAYgAS0AADoAACABQQFqIQEgBkEBaiEGIAdBAWsiBw0ACwwBCyAAIAEgBSAMIA0gCxABCyAFQquzj/yRo7Pw2wA3AlggBUL/pLmIxZHagpt/NwJQIAVC8ua746On/aelfzcCSCAFQufMp9DW0Ouzu383AkBBACEBA0AgASAFaiIAQeAAaiAALQAAQTZzOgAAIABB4QBqIABBAWotAABBNnM6AAAgAEHiAGogAEECai0AAEE2czoAACAAQeMAaiAAQQNqLQAAQTZzOgAAIAFBBGoiAUHAAEcNAAsgDCANIAsQAkEAIQZBACEBIAMiAEHAAE8EQANAIAwgASACaiALEAIgAUFAayEBIABBQGoiAEE/Sw0ACwtBgAFBwAAgAEE3SxshCgNAIAUgBmpB4ABqQgA3AAAgCiAGQQhqIgZHDQALAkAgAEUNACAAQQNxIQdBACEGIABBBE8EQCABIAJqIQ4gAEE8cSEPA0AgBSAGaiIIQeAAaiAGIA5qIgktAAA6AAAgCEHhAGogCUEBai0AADoAACAIQeIAaiAJQQJqLQAAOgAAIAhB4wBqIAlBA2otAAA6AAAgDyAGQQRqIgZHDQALCyAHRQ0AIAIgASAGamohASAFIAZqQeAAaiEGA0AgBiABLQAAOgAAIAFBAWohASAGQQFqIQYgB0EBayIHDQALCyAAIA1qQYABOgAAIAogDWoiAkEBayADrUIDhiIhPAAAQQAhASACQQZrQQA6AAAgAkEIa0EAOwAAIAJBAmsgIUKABHwiIUIIiDwAACACQQNrICFCEIg8AAAgAkEEayAhQhiIPAAAIAJBBWsgIUIgiDwAACAMIA0gCxACIABBN0sEQCAMIAVBoAFqIAsQAgsgBSAFKAJAIgBBGHQgAEGA/gNxQQh0ciAAQQh2QYD+A3EgAEEYdnJyNgDgAyAFIAUoAkQiCkEYdCAKQYD+A3FBCHRyIApBCHZBgP4DcSAKQRh2cnI2AOQDIAUoAkgiAkEYdiEOIAUgAkEYdCACQYD+A3FBCHRyIA4gAkEIdiIUQYD+A3FycjYA6AMgBSgCTCIDQRh2IQ8gBSADQRh0IANBgP4DcUEIdHIgDyADQQh2IhVBgP4DcXJyNgDsAyAFKAJQIgZBGHYhECAFIAZBGHQgBkGA/gNxQQh0ciAQIAZBCHYiFkGA/gNxcnI2APADIAUoAlQiB0EYdiERIAUgB0EYdCAHQYD+A3FBCHRyIBEgB0EIdiIXQYD+A3FycjYA9AMgBSgCWCIIQRh2IRIgBSAIQRh0IAhBgP4DcUEIdHIgEiAIQQh2IhhBgP4DcXJyNgD4AyAFKAJcIglBGHYhEyAFIAlBGHQgCUGA/gNxQQh0ciATIAlBCHYiGUGA/gNxcnI2APwDIAVBgARqIAlBEHYhGyAIQRB2IRwgB0EQdiEdIAZBEHYhHiADQRB2IR8gAkEQdiEgA0AgASAFaiIAQYAEaiAALQAAQdwAczoAACAAQYEEaiAAQQFqLQAAQdwAczoAACAAQYIEaiAAQQJqLQAAQdwAczoAACAAQYMEaiAAQQNqLQAAQdwAczoAACABQQRqIgFBwABHDQALIAUgCToA3wQgBSAZOgDeBCAFIBs6AN0EIAUgEzoA3AQgBSAIOgDbBCAFIBg6ANoEIAUgHDoA2QQgBSASOgDYBCAFIAc6ANcEIAUgFzoA1gQgBSAdOgDVBCAFIBE6ANQEIAUgBjoA0wQgBSAWOgDSBCAFIB46ANEEIAUgEDoA0AQgBSADOgDPBCAFIBU6AM4EIAUgHzoAzQQgBSAPOgDMBCAFIAI6AMsEIAUgFDoAygQgBSAgOgDJBCAFIA46AMgEIAUgCjoAxwQgBSAFLQDgAzoAwAQgBSAFLwDhAzsAwQQgBSAFKADjAzYAwwRB4AAgBCAMIA0gCxABQQAhAQNAIAEgBWoiAEEAOgAAIABBAWpBADoAACAAQQJqQQA6AAAgAEEDakEAOgAAIABBBGpBADoAACAAQQVqQQA6AAAgAEEGakEAOgAAIABBB2pBADoAACAAQQhqQQA6AAAgAEEJakEAOgAAIABBCmpBADoAACAAQQtqQQA6AAAgAEEMakEAOgAAIABBDWpBADoAACAAQQ5qQQA6AAAgAEEPakEAOgAAIAFBEGoiAUHgBEcNAAsLpQYBCX8gA0Krs4/8kaOz8NsANwIYIANC/6S5iMWR2oKbfzcCECADQvLmu+Ojp/2npX83AgggA0LnzKfQ1tDrs7t/NwIAIAEiB0HAAE8EQANAIAMgACAJaiAFEAIgCUFAayEJIAdBQGoiB0E/Sw0ACwtBgAFBwAAgB0E3SxshDANAIAQgBmpCADcAACAMIAZBCGoiBkcNAAsCQCAHRQ0AIAdBA3EhCkEAIQYgB0EETwRAIAAgCWohDSAHQTxxIQ4DQCAEIAZqIgggBiANaiILLQAAOgAAIAhBAWogC0EBai0AADoAACAIQQJqIAtBAmotAAA6AAAgCEEDaiALQQNqLQAAOgAAIA4gBkEEaiIGRw0ACwsgCkUNACAEIAZqIQggACAGIAlqaiEGA0AgCCAGLQAAOgAAIAZBAWohBiAIQQFqIQggCkEBayIKDQALCyAEIAdqQYABOgAAIAQgDGoiAEECayABQQV2OgAAIABBAWsgAUEDdDoAACAAQQNrIAFBDXY6AAAgAEEEayABQRV2OgAAIABBBWsgAUEddjoAACAAQQZrQQA6AAAgAEEIa0EAOwAAIAMgBCAFEAIgB0E3SwRAIAMgBEFAayAFEAILIAIgAygCACIAQRh0IABBgP4DcUEIdHIgAEEIdkGA/gNxIABBGHZycjYAACACIAMoAgQiAEEYdCAAQYD+A3FBCHRyIABBCHZBgP4DcSAAQRh2cnI2AAQgAiADKAIIIgBBGHQgAEGA/gNxQQh0ciAAQQh2QYD+A3EgAEEYdnJyNgAIIAIgAygCDCIAQRh0IABBgP4DcUEIdHIgAEEIdkGA/gNxIABBGHZycjYADCACIAMoAhAiAEEYdCAAQYD+A3FBCHRyIABBCHZBgP4DcSAAQRh2cnI2ABAgAiADKAIUIgBBGHQgAEGA/gNxQQh0ciAAQQh2QYD+A3EgAEEYdnJyNgAUIAIgAygCGCIAQRh0IABBgP4DcUEIdHIgAEEIdkGA/gNxIABBGHZycjYAGCACIAMoAhwiAEEYdCAAQYD+A3FBCHRyIABBCHZBgP4DcSAAQRh2cnI2ABwLvwgBEn8gAiABKAAAIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyNgIAIAIgASgABCIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZycjYCBCACIAEoAAgiA0EYdCADQYD+A3FBCHRyIANBCHZBgP4DcSADQRh2cnI2AgggAiABKAAMIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyNgIMIAIgASgAECIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZycjYCECACIAEoABQiA0EYdCADQYD+A3FBCHRyIANBCHZBgP4DcSADQRh2cnI2AhQgAiABKAAYIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyNgIYIAIgASgAHCIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZycjYCHCACIAEoACAiA0EYdCADQYD+A3FBCHRyIANBCHZBgP4DcSADQRh2cnI2AiAgAiABKAAkIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyNgIkIAIgASgAKCIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZycjYCKCACIAEoACwiA0EYdCADQYD+A3FBCHRyIANBCHZBgP4DcSADQRh2cnI2AiwgAiABKAAwIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyNgIwIAIgASgANCIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZycjYCNCACIAEoADgiA0EYdCADQYD+A3FBCHRyIANBCHZBgP4DcSADQRh2cnI2AjggAiABKAA8IgFBGHQgAUGA/gNxQQh0ciABQQh2QYD+A3EgAUEYdnJyNgI8QQAhAQNAIAEgAmoiBEEEaigCACEDIARBQGsgBEEkaigCACAEKAIAIANBGXcgA0EOd3MgA0EDdnNqaiAEQThqKAIAIgNBD3cgA0ENd3MgA0EKdnNqNgIAIAFBBGoiAUHAAUcNAAsgACgCACINIQkgACgCBCIOIQEgACgCCCIPIQUgACgCDCIQIQwgACgCHCIRIQogACgCGCISIQggACgCFCITIQMgACgCECIUIQYDQCAFIQQgASEFIAIgC2ooAgAgC0HgCWooAgAgCiAGIgdBGncgB0EVd3MgB0EHd3NqIAdBf3MgCHEgAyAHcXJqamoiBiAJIgFBHncgAUETd3MgAUEKd3MgASAEIAVzcSAEIAVxc2pqIQkgBiAMaiEGIAQhDCAIIQogAyEIIAchAyALQQRqIgtBgAJHDQALIAAgCiARajYCHCAAIAggEmo2AhggACADIBNqNgIUIAAgBiAUajYCECAAIAQgEGo2AgwgACAFIA9qNgIIIAAgASAOajYCBCAAIAkgDWo2AgALkgkBBn8jAEHgAmsiAyQAIANCADcD0AIgA0IANwPIAiADQgA3A8ACIANCADcDuAIgA0IANwOwAiADQgA3A6gCIANCADcDoAIgA0IANwOYAiADQgA3A5ACIANCADcDiAIgA0IANwOAAiADQgA3A/gBIANCADcD8AEgA0IANwPoASADQgA3A+ABIANCADcD2AEgA0IANwPQASADQgA3A8gBIANCADcDwAEgA0IANwO4ASADQgA3A7ABIANCADcDqAEgA0IANwOgASADQgA3A5gBIANCADcDkAEgAUGIAU8EQANAIAMgAykDkAEgACAGaiIEKQAAhTcDkAEgAyADKQOYASAEKQAIhTcDmAEgAyADKQOgASAEQRBqKQAAhTcDoAEgAyADKQOoASAEQRhqKQAAhTcDqAEgAyADKQOwASAEQSBqKQAAhTcDsAEgAyADKQO4ASAEQShqKQAAhTcDuAEgAyADKQPAASAEQTBqKQAAhTcDwAEgAyADKQPIASAEQThqKQAAhTcDyAEgAyADKQPQASAEQUBrKQAAhTcD0AEgAyADKQPYASAEQcgAaikAAIU3A9gBIAMgAykD4AEgBEHQAGopAACFNwPgASADIAMpA+gBIARB2ABqKQAAhTcD6AEgAyADKQPwASAEQeAAaikAAIU3A/ABIAMgAykD+AEgBEHoAGopAACFNwP4ASADIAMpA4ACIARB8ABqKQAAhTcDgAIgAyADKQOIAiAEQfgAaikAAIU3A4gCIAMgAykDkAIgBEGAAWopAACF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'
|
|
12
|
+
|
|
13
|
+
/** Constant shared with the module's C source. */
|
|
14
|
+
export const hmacSha256ScratchSize = 608
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as Errors from '../../core/Errors.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared WASM instantiation and memory plumbing.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** An instantiated WASM module, with helpers for moving bytes across. */
|
|
10
|
+
export type Module<exports extends Record<string, unknown>> = {
|
|
11
|
+
/** The module's exported functions. */
|
|
12
|
+
exports: exports
|
|
13
|
+
/** Address of the first byte we may write to. */
|
|
14
|
+
heapBase: number
|
|
15
|
+
/**
|
|
16
|
+
* Grows linear memory so `bytes` are available above `heapBase`.
|
|
17
|
+
*
|
|
18
|
+
* @throws {@link MemoryError} when the runtime refuses to grow.
|
|
19
|
+
*/
|
|
20
|
+
reserve(bytes: number): void
|
|
21
|
+
/**
|
|
22
|
+
* A view over the module's current memory.
|
|
23
|
+
*
|
|
24
|
+
* Must be called after {@link Module.reserve} and again after anything that
|
|
25
|
+
* could grow memory: `WebAssembly.Memory.grow` detaches the previous
|
|
26
|
+
* `ArrayBuffer`, which silently turns any retained view into a zero-length one.
|
|
27
|
+
*/
|
|
28
|
+
view(): Uint8Array
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const pageSize = 65_536
|
|
32
|
+
|
|
33
|
+
function decode(base64: string): Uint8Array {
|
|
34
|
+
// `Uint8Array.fromBase64` where available, then Node/Bun, then browsers and
|
|
35
|
+
// edge runtimes.
|
|
36
|
+
const fromBase64 = (
|
|
37
|
+
Uint8Array as unknown as {
|
|
38
|
+
fromBase64?: ((value: string) => Uint8Array) | undefined
|
|
39
|
+
}
|
|
40
|
+
).fromBase64
|
|
41
|
+
if (fromBase64) return fromBase64(base64)
|
|
42
|
+
if (typeof Buffer !== 'undefined')
|
|
43
|
+
return new Uint8Array(Buffer.from(base64, 'base64'))
|
|
44
|
+
const binary = atob(base64)
|
|
45
|
+
const bytes = new Uint8Array(binary.length)
|
|
46
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)
|
|
47
|
+
return bytes
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Instantiates a base64-encoded WASM module.
|
|
52
|
+
*
|
|
53
|
+
* Always asynchronous: browsers refuse to compile modules larger than a few
|
|
54
|
+
* kilobytes synchronously on the main thread, so there is no synchronous path to
|
|
55
|
+
* fall back to. Callers await this once and then call the module synchronously.
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export async function instantiate<exports extends Record<string, unknown>>(
|
|
60
|
+
base64: string,
|
|
61
|
+
): Promise<Module<exports>> {
|
|
62
|
+
const { instance } = await WebAssembly.instantiate(decode(base64), {})
|
|
63
|
+
const exports = instance.exports as {
|
|
64
|
+
heap_base(): number
|
|
65
|
+
memory: WebAssembly.Memory
|
|
66
|
+
} & exports
|
|
67
|
+
|
|
68
|
+
const { memory } = exports
|
|
69
|
+
const heapBase = exports.heap_base()
|
|
70
|
+
|
|
71
|
+
let cached = new Uint8Array(memory.buffer)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
exports,
|
|
75
|
+
heapBase,
|
|
76
|
+
reserve(bytes) {
|
|
77
|
+
const required = heapBase + bytes
|
|
78
|
+
if (memory.buffer.byteLength >= required) return
|
|
79
|
+
const pages = Math.ceil((required - memory.buffer.byteLength) / pageSize)
|
|
80
|
+
try {
|
|
81
|
+
memory.grow(pages)
|
|
82
|
+
} catch (cause) {
|
|
83
|
+
throw new MemoryError({ bytes: required, cause: cause as Error })
|
|
84
|
+
}
|
|
85
|
+
cached = new Uint8Array(memory.buffer)
|
|
86
|
+
},
|
|
87
|
+
view() {
|
|
88
|
+
// `grow` detaches the old buffer, so compare identity rather than trusting
|
|
89
|
+
// the cached view.
|
|
90
|
+
if (cached.buffer !== memory.buffer)
|
|
91
|
+
cached = new Uint8Array(memory.buffer)
|
|
92
|
+
return cached
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Memoizes a loader so concurrent callers compile the module once.
|
|
99
|
+
*
|
|
100
|
+
* The promise is memoized rather than its result, so a second call made while
|
|
101
|
+
* the first is still compiling awaits the same compilation. A rejected attempt
|
|
102
|
+
* is discarded, so a later call can try again.
|
|
103
|
+
*
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
export function memoize<value>(
|
|
107
|
+
load: () => Promise<value>,
|
|
108
|
+
): () => Promise<value> {
|
|
109
|
+
let cached: Promise<value> | undefined
|
|
110
|
+
return () => {
|
|
111
|
+
// Only success is memoized. Compilation can fail for reasons that pass --
|
|
112
|
+
// a runtime briefly out of memory, say -- and caching the rejection would
|
|
113
|
+
// make one bad moment permanent for the life of the process.
|
|
114
|
+
cached ??= load().catch((error) => {
|
|
115
|
+
cached = undefined
|
|
116
|
+
throw error
|
|
117
|
+
})
|
|
118
|
+
return cached
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Thrown when a WASM module cannot grow its memory to the required size. */
|
|
123
|
+
export class MemoryError extends Errors.BaseError<Error> {
|
|
124
|
+
override readonly name = 'Wasm.MemoryError'
|
|
125
|
+
|
|
126
|
+
constructor({ bytes, cause }: { bytes: number; cause: Error }) {
|
|
127
|
+
super('WASM memory could not be grown to the required size.', {
|
|
128
|
+
cause,
|
|
129
|
+
metaMessages: [
|
|
130
|
+
`Required: ${bytes} bytes`,
|
|
131
|
+
'The input may be too large for this runtime. Reset the engine slot with `Engine.reset` to fall back to the default implementation.',
|
|
132
|
+
],
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -11,7 +11,7 @@ describe('ZoneId', () => {
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
test('decodes and encodes chain ids', () => {
|
|
14
|
-
expect(z.decode(z_ZoneId.chainId,
|
|
15
|
-
expect(z.encode(z_ZoneId.chainId,
|
|
14
|
+
expect(z.decode(z_ZoneId.chainId, 421_700_001)).toMatchInlineSnapshot(`1`)
|
|
15
|
+
expect(z.encode(z_ZoneId.chainId, 1)).toMatchInlineSnapshot(`421700001`)
|
|
16
16
|
})
|
|
17
17
|
})
|