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.
Files changed (337) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/dist/core/Base64.d.ts +10 -21
  3. package/dist/core/Base64.d.ts.map +1 -1
  4. package/dist/core/Base64.js +8 -127
  5. package/dist/core/Base64.js.map +1 -1
  6. package/dist/core/BinaryStateTree.d.ts.map +1 -1
  7. package/dist/core/BinaryStateTree.js +2 -2
  8. package/dist/core/BinaryStateTree.js.map +1 -1
  9. package/dist/core/Bls.d.ts.map +1 -1
  10. package/dist/core/Bls.js +19 -44
  11. package/dist/core/Bls.js.map +1 -1
  12. package/dist/core/Ed25519.d.ts.map +1 -1
  13. package/dist/core/Ed25519.js +7 -6
  14. package/dist/core/Ed25519.js.map +1 -1
  15. package/dist/core/Engine.d.ts +156 -0
  16. package/dist/core/Engine.d.ts.map +1 -0
  17. package/dist/core/Engine.js +210 -0
  18. package/dist/core/Engine.js.map +1 -0
  19. package/dist/core/Hash.d.ts +4 -4
  20. package/dist/core/Hash.d.ts.map +1 -1
  21. package/dist/core/Hash.js +9 -12
  22. package/dist/core/Hash.js.map +1 -1
  23. package/dist/core/Keystore.d.ts.map +1 -1
  24. package/dist/core/Keystore.js +15 -10
  25. package/dist/core/Keystore.js.map +1 -1
  26. package/dist/core/Mnemonic.d.ts.map +1 -1
  27. package/dist/core/Mnemonic.js +3 -2
  28. package/dist/core/Mnemonic.js.map +1 -1
  29. package/dist/core/P256.d.ts.map +1 -1
  30. package/dist/core/P256.js +8 -9
  31. package/dist/core/P256.js.map +1 -1
  32. package/dist/core/Secp256k1.d.ts.map +1 -1
  33. package/dist/core/Secp256k1.js +8 -9
  34. package/dist/core/Secp256k1.js.map +1 -1
  35. package/dist/core/WebCryptoP256.d.ts.map +1 -1
  36. package/dist/core/WebCryptoP256.js +2 -2
  37. package/dist/core/WebCryptoP256.js.map +1 -1
  38. package/dist/core/X25519.d.ts.map +1 -1
  39. package/dist/core/X25519.js +4 -3
  40. package/dist/core/X25519.js.map +1 -1
  41. package/dist/core/internal/bls.d.ts +12 -0
  42. package/dist/core/internal/bls.d.ts.map +1 -0
  43. package/dist/core/internal/bls.js +79 -0
  44. package/dist/core/internal/bls.js.map +1 -0
  45. package/dist/core/internal/codec/base64.d.ts +84 -0
  46. package/dist/core/internal/codec/base64.d.ts.map +1 -0
  47. package/dist/core/internal/codec/base64.js +177 -0
  48. package/dist/core/internal/codec/base64.js.map +1 -0
  49. package/dist/core/internal/codec/hex.d.ts +49 -4
  50. package/dist/core/internal/codec/hex.d.ts.map +1 -1
  51. package/dist/core/internal/codec/hex.js +109 -35
  52. package/dist/core/internal/codec/hex.js.map +1 -1
  53. package/dist/core/internal/curves.d.ts +17 -0
  54. package/dist/core/internal/curves.d.ts.map +1 -0
  55. package/dist/core/internal/curves.js +17 -0
  56. package/dist/core/internal/curves.js.map +1 -0
  57. package/dist/core/internal/ed25519.d.ts +14 -0
  58. package/dist/core/internal/ed25519.d.ts.map +1 -0
  59. package/dist/core/internal/ed25519.js +29 -0
  60. package/dist/core/internal/ed25519.js.map +1 -0
  61. package/dist/core/internal/engine.d.ts +278 -0
  62. package/dist/core/internal/engine.d.ts.map +1 -0
  63. package/dist/core/internal/engine.js +131 -0
  64. package/dist/core/internal/engine.js.map +1 -0
  65. package/dist/core/internal/hash.d.ts +12 -0
  66. package/dist/core/internal/hash.d.ts.map +1 -0
  67. package/dist/core/internal/hash.js +30 -0
  68. package/dist/core/internal/hash.js.map +1 -0
  69. package/dist/core/internal/keystore.d.ts +14 -0
  70. package/dist/core/internal/keystore.d.ts.map +1 -0
  71. package/dist/core/internal/keystore.js +32 -0
  72. package/dist/core/internal/keystore.js.map +1 -0
  73. package/dist/core/internal/mnemonic.d.ts +4 -0
  74. package/dist/core/internal/mnemonic.d.ts.map +1 -0
  75. package/dist/core/internal/mnemonic.js +14 -0
  76. package/dist/core/internal/mnemonic.js.map +1 -0
  77. package/dist/core/internal/p256.d.ts +14 -0
  78. package/dist/core/internal/p256.d.ts.map +1 -0
  79. package/dist/core/internal/p256.js +36 -0
  80. package/dist/core/internal/p256.js.map +1 -0
  81. package/dist/core/internal/secp256k1.d.ts +14 -0
  82. package/dist/core/internal/secp256k1.d.ts.map +1 -0
  83. package/dist/core/internal/secp256k1.js +36 -0
  84. package/dist/core/internal/secp256k1.js.map +1 -0
  85. package/dist/core/internal/x25519.d.ts +8 -0
  86. package/dist/core/internal/x25519.d.ts.map +1 -0
  87. package/dist/core/internal/x25519.js +20 -0
  88. package/dist/core/internal/x25519.js.map +1 -0
  89. package/dist/index.d.ts +38 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.docs.d.ts +2 -0
  92. package/dist/index.docs.d.ts.map +1 -1
  93. package/dist/index.docs.js +2 -0
  94. package/dist/index.docs.js.map +1 -1
  95. package/dist/index.js +38 -0
  96. package/dist/index.js.map +1 -1
  97. package/dist/node/Ed25519.d.ts +33 -0
  98. package/dist/node/Ed25519.d.ts.map +1 -0
  99. package/dist/node/Ed25519.js +67 -0
  100. package/dist/node/Ed25519.js.map +1 -0
  101. package/dist/node/Engine.d.ts +68 -0
  102. package/dist/node/Engine.d.ts.map +1 -0
  103. package/dist/node/Engine.js +75 -0
  104. package/dist/node/Engine.js.map +1 -0
  105. package/dist/node/Hash.d.ts +37 -0
  106. package/dist/node/Hash.d.ts.map +1 -0
  107. package/dist/node/Hash.js +35 -0
  108. package/dist/node/Hash.js.map +1 -0
  109. package/dist/node/Keystore.d.ts +36 -0
  110. package/dist/node/Keystore.d.ts.map +1 -0
  111. package/dist/node/Keystore.js +72 -0
  112. package/dist/node/Keystore.js.map +1 -0
  113. package/dist/node/Mnemonic.d.ts +35 -0
  114. package/dist/node/Mnemonic.d.ts.map +1 -0
  115. package/dist/node/Mnemonic.js +46 -0
  116. package/dist/node/Mnemonic.js.map +1 -0
  117. package/dist/node/P256.d.ts +32 -0
  118. package/dist/node/P256.d.ts.map +1 -0
  119. package/dist/node/P256.js +34 -0
  120. package/dist/node/P256.js.map +1 -0
  121. package/dist/node/X25519.d.ts +31 -0
  122. package/dist/node/X25519.d.ts.map +1 -0
  123. package/dist/node/X25519.js +71 -0
  124. package/dist/node/X25519.js.map +1 -0
  125. package/dist/node/index.d.ts +126 -0
  126. package/dist/node/index.d.ts.map +1 -0
  127. package/dist/node/index.js +126 -0
  128. package/dist/node/index.js.map +1 -0
  129. package/dist/tempo/VirtualMaster.d.ts +2 -0
  130. package/dist/tempo/VirtualMaster.d.ts.map +1 -1
  131. package/dist/tempo/VirtualMaster.js +19 -5
  132. package/dist/tempo/VirtualMaster.js.map +1 -1
  133. package/dist/tempo/internal/mine.wasm.d.ts +2 -4
  134. package/dist/tempo/internal/mine.wasm.d.ts.map +1 -1
  135. package/dist/tempo/internal/mine.wasm.js +7 -12
  136. package/dist/tempo/internal/mine.wasm.js.map +1 -1
  137. package/dist/tempo/internal/virtualMasterPool.js +4 -1
  138. package/dist/tempo/internal/virtualMasterPool.js.map +1 -1
  139. package/dist/wasm/Ed25519.d.ts +35 -0
  140. package/dist/wasm/Ed25519.d.ts.map +1 -0
  141. package/dist/wasm/Ed25519.js +88 -0
  142. package/dist/wasm/Ed25519.js.map +1 -0
  143. package/dist/wasm/Engine.d.ts +71 -0
  144. package/dist/wasm/Engine.d.ts.map +1 -0
  145. package/dist/wasm/Engine.js +76 -0
  146. package/dist/wasm/Engine.js.map +1 -0
  147. package/dist/wasm/Hash.d.ts +43 -0
  148. package/dist/wasm/Hash.d.ts.map +1 -0
  149. package/dist/wasm/Hash.js +64 -0
  150. package/dist/wasm/Hash.js.map +1 -0
  151. package/dist/wasm/Keystore.d.ts +37 -0
  152. package/dist/wasm/Keystore.d.ts.map +1 -0
  153. package/dist/wasm/Keystore.js +34 -0
  154. package/dist/wasm/Keystore.js.map +1 -0
  155. package/dist/wasm/Mnemonic.d.ts +33 -0
  156. package/dist/wasm/Mnemonic.d.ts.map +1 -0
  157. package/dist/wasm/Mnemonic.js +30 -0
  158. package/dist/wasm/Mnemonic.js.map +1 -0
  159. package/dist/wasm/X25519.d.ts +33 -0
  160. package/dist/wasm/X25519.d.ts.map +1 -0
  161. package/dist/wasm/X25519.js +53 -0
  162. package/dist/wasm/X25519.js.map +1 -0
  163. package/dist/wasm/index.d.ts +115 -0
  164. package/dist/wasm/index.d.ts.map +1 -0
  165. package/dist/wasm/index.js +115 -0
  166. package/dist/wasm/index.js.map +1 -0
  167. package/dist/wasm/internal/blake3.d.ts +11 -0
  168. package/dist/wasm/internal/blake3.d.ts.map +1 -0
  169. package/dist/wasm/internal/blake3.js +31 -0
  170. package/dist/wasm/internal/blake3.js.map +1 -0
  171. package/dist/wasm/internal/blake3.wasm.d.ts +3 -0
  172. package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -0
  173. package/dist/wasm/internal/blake3.wasm.js +10 -0
  174. package/dist/wasm/internal/blake3.wasm.js.map +1 -0
  175. package/dist/wasm/internal/crypto25519.d.ts +16 -0
  176. package/dist/wasm/internal/crypto25519.d.ts.map +1 -0
  177. package/dist/wasm/internal/crypto25519.js +5 -0
  178. package/dist/wasm/internal/crypto25519.js.map +1 -0
  179. package/dist/wasm/internal/crypto25519.wasm.d.ts +3 -0
  180. package/dist/wasm/internal/crypto25519.wasm.d.ts.map +1 -0
  181. package/dist/wasm/internal/crypto25519.wasm.js +10 -0
  182. package/dist/wasm/internal/crypto25519.wasm.js.map +1 -0
  183. package/dist/wasm/internal/ed25519.d.ts +4 -0
  184. package/dist/wasm/internal/ed25519.d.ts.map +1 -0
  185. package/dist/wasm/internal/ed25519.js +21 -0
  186. package/dist/wasm/internal/ed25519.js.map +1 -0
  187. package/dist/wasm/internal/hash.d.ts +9 -0
  188. package/dist/wasm/internal/hash.d.ts.map +1 -0
  189. package/dist/wasm/internal/hash.js +26 -0
  190. package/dist/wasm/internal/hash.js.map +1 -0
  191. package/dist/wasm/internal/hashes.d.ts +12 -0
  192. package/dist/wasm/internal/hashes.d.ts.map +1 -0
  193. package/dist/wasm/internal/hashes.js +8 -0
  194. package/dist/wasm/internal/hashes.js.map +1 -0
  195. package/dist/wasm/internal/hashes.wasm.d.ts +7 -0
  196. package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
  197. package/dist/wasm/internal/hashes.wasm.js +14 -0
  198. package/dist/wasm/internal/hashes.wasm.js.map +1 -0
  199. package/dist/wasm/internal/instantiate.d.ts +56 -0
  200. package/dist/wasm/internal/instantiate.d.ts.map +1 -0
  201. package/dist/wasm/internal/instantiate.js +92 -0
  202. package/dist/wasm/internal/instantiate.js.map +1 -0
  203. package/dist/wasm/internal/mnemonic.d.ts +4 -0
  204. package/dist/wasm/internal/mnemonic.d.ts.map +1 -0
  205. package/dist/wasm/internal/mnemonic.js +45 -0
  206. package/dist/wasm/internal/mnemonic.js.map +1 -0
  207. package/dist/wasm/internal/pbkdf2.d.ts +12 -0
  208. package/dist/wasm/internal/pbkdf2.d.ts.map +1 -0
  209. package/dist/wasm/internal/pbkdf2.js +51 -0
  210. package/dist/wasm/internal/pbkdf2.js.map +1 -0
  211. package/dist/wasm/internal/x25519.d.ts +4 -0
  212. package/dist/wasm/internal/x25519.d.ts.map +1 -0
  213. package/dist/wasm/internal/x25519.js +21 -0
  214. package/dist/wasm/internal/x25519.js.map +1 -0
  215. package/dist/zod/TypedData.d.ts +12 -12
  216. package/package.json +81 -1
  217. package/src/core/Base64.ts +19 -166
  218. package/src/core/BinaryStateTree.ts +2 -3
  219. package/src/core/Bls.ts +27 -77
  220. package/src/core/Ed25519.ts +7 -7
  221. package/src/core/Engine.ts +308 -0
  222. package/src/core/Hash.ts +9 -12
  223. package/src/core/Keystore.ts +17 -17
  224. package/src/core/Mnemonic.ts +3 -6
  225. package/src/core/P256.ts +15 -24
  226. package/src/core/Rlp_tx.bench.ts +2 -4
  227. package/src/core/Secp256k1.ts +9 -14
  228. package/src/core/TxEnvelopeEip1559.bench.ts +0 -5
  229. package/src/core/WebCryptoP256.ts +2 -2
  230. package/src/core/X25519.ts +4 -3
  231. package/src/core/_test/AbiParameters.adversarial.fuzz.ts +1 -2
  232. package/src/core/_test/AbiParameters.fuzz.ts +1 -2
  233. package/src/core/_test/Base.fuzz.ts +1 -2
  234. package/src/core/_test/Cbor.fuzz.ts +1 -2
  235. package/src/core/_test/Engine.fuzz.ts +293 -0
  236. package/src/core/_test/Engine.test-d.ts +140 -0
  237. package/src/core/_test/Engine.test.ts +618 -0
  238. package/src/core/_test/Hash.vectors.test.ts +64 -0
  239. package/src/core/_test/Hex.fuzz.ts +1 -2
  240. package/src/core/_test/Rlp.fuzz.ts +1 -2
  241. package/src/core/_test/Signature.fuzz.ts +1 -2
  242. package/src/core/_test/curves.test.ts +7 -0
  243. package/src/core/_test/index.test.ts +1 -0
  244. package/src/core/internal/bls.ts +121 -0
  245. package/src/core/internal/codec/_test/base64.conformance.ts +156 -0
  246. package/src/core/internal/codec/_test/hex.conformance.ts +204 -0
  247. package/src/core/internal/codec/_test/hex.fuzz.ts +234 -0
  248. package/src/core/internal/codec/_test/hex.test.ts +124 -0
  249. package/src/core/internal/codec/base64.ts +222 -0
  250. package/src/core/internal/codec/hex.ts +115 -34
  251. package/src/core/internal/curves.ts +18 -0
  252. package/src/core/internal/ed25519.ts +64 -0
  253. package/src/core/internal/engine.ts +410 -0
  254. package/src/core/internal/hash.ts +48 -0
  255. package/src/core/internal/keystore.ts +107 -0
  256. package/src/core/internal/mnemonic.ts +18 -0
  257. package/src/core/internal/p256.ts +91 -0
  258. package/src/core/internal/secp256k1.ts +91 -0
  259. package/src/core/internal/x25519.ts +40 -0
  260. package/src/index.docs.ts +2 -0
  261. package/src/index.ts +39 -0
  262. package/src/node/Ed25519.ts +87 -0
  263. package/src/node/Engine.ts +125 -0
  264. package/src/node/Hash.ts +51 -0
  265. package/src/node/Keystore.ts +103 -0
  266. package/src/node/Mnemonic.ts +68 -0
  267. package/src/node/P256.ts +48 -0
  268. package/src/node/X25519.ts +93 -0
  269. package/src/node/_test/Curves.fuzz.ts +76 -0
  270. package/src/node/_test/Ed25519.test-d.ts +35 -0
  271. package/src/node/_test/Ed25519.test.ts +220 -0
  272. package/src/node/_test/Engine.test-d.ts +28 -0
  273. package/src/node/_test/Engine.test.ts +102 -0
  274. package/src/node/_test/Hash.test-d.ts +32 -0
  275. package/src/node/_test/Hash.test.ts +101 -0
  276. package/src/node/_test/Keystore.fuzz.ts +58 -0
  277. package/src/node/_test/Keystore.test-d.ts +43 -0
  278. package/src/node/_test/Keystore.test.ts +198 -0
  279. package/src/node/_test/Mnemonic.fuzz.ts +31 -0
  280. package/src/node/_test/Mnemonic.test-d.ts +21 -0
  281. package/src/node/_test/Mnemonic.test.ts +98 -0
  282. package/src/node/_test/P256.test-d.ts +29 -0
  283. package/src/node/_test/P256.test.ts +102 -0
  284. package/src/node/_test/X25519.test-d.ts +28 -0
  285. package/src/node/_test/X25519.test.ts +239 -0
  286. package/src/node/index.ts +132 -0
  287. package/src/tempo/VirtualMaster.test.ts +75 -0
  288. package/src/tempo/VirtualMaster.ts +28 -6
  289. package/src/tempo/internal/mine.wasm.ts +7 -13
  290. package/src/tempo/internal/virtualMasterPool.ts +4 -1
  291. package/src/tsconfig.json +2 -1
  292. package/src/version.ts +1 -1
  293. package/src/wasm/Ed25519.ts +114 -0
  294. package/src/wasm/Engine.ts +121 -0
  295. package/src/wasm/Hash.bench.ts +60 -0
  296. package/src/wasm/Hash.ts +88 -0
  297. package/src/wasm/Keystore.ts +48 -0
  298. package/src/wasm/Mnemonic.ts +44 -0
  299. package/src/wasm/X25519.ts +70 -0
  300. package/src/wasm/_test/Crypto25519.conformance.ts +57 -0
  301. package/src/wasm/_test/Crypto25519.fuzz.ts +187 -0
  302. package/src/wasm/_test/Ed25519.test-d.ts +28 -0
  303. package/src/wasm/_test/Ed25519.test.ts +168 -0
  304. package/src/wasm/_test/Ed25519.vectors.test.ts +73 -0
  305. package/src/wasm/_test/Engine.test-d.ts +28 -0
  306. package/src/wasm/_test/Engine.test.ts +96 -0
  307. package/src/wasm/_test/Hash.browser.test.ts +54 -0
  308. package/src/wasm/_test/Hash.fuzz.ts +223 -0
  309. package/src/wasm/_test/Hash.test-d.ts +33 -0
  310. package/src/wasm/_test/Hash.test.ts +311 -0
  311. package/src/wasm/_test/Hash.vectors.test.ts +124 -0
  312. package/src/wasm/_test/Keystore.browser.test.ts +42 -0
  313. package/src/wasm/_test/Keystore.fuzz.ts +113 -0
  314. package/src/wasm/_test/Keystore.test-d.ts +33 -0
  315. package/src/wasm/_test/Keystore.test.ts +192 -0
  316. package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
  317. package/src/wasm/_test/Mnemonic.test-d.ts +17 -0
  318. package/src/wasm/_test/Mnemonic.test.ts +110 -0
  319. package/src/wasm/_test/Runtime.test.ts +21 -0
  320. package/src/wasm/_test/X25519.test-d.ts +21 -0
  321. package/src/wasm/_test/X25519.test.ts +194 -0
  322. package/src/wasm/_test/fixtures.ts +4 -0
  323. package/src/wasm/_test/runtime.wasm.ts +11 -0
  324. package/src/wasm/index.ts +120 -0
  325. package/src/wasm/internal/blake3.ts +45 -0
  326. package/src/wasm/internal/blake3.wasm.ts +11 -0
  327. package/src/wasm/internal/crypto25519.ts +43 -0
  328. package/src/wasm/internal/crypto25519.wasm.ts +11 -0
  329. package/src/wasm/internal/ed25519.ts +31 -0
  330. package/src/wasm/internal/hash.ts +50 -0
  331. package/src/wasm/internal/hashes.ts +29 -0
  332. package/src/wasm/internal/hashes.wasm.ts +17 -0
  333. package/src/wasm/internal/instantiate.ts +135 -0
  334. package/src/wasm/internal/mnemonic.ts +56 -0
  335. package/src/wasm/internal/pbkdf2.ts +86 -0
  336. package/src/wasm/internal/x25519.ts +29 -0
  337. 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
+ })