ox 1.1.0 → 1.2.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 +54 -0
- package/dist/core/Engine.d.ts +43 -11
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +40 -10
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Hash.d.ts +36 -0
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +35 -0
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/internal/engine.d.ts +8 -8
- package/dist/core/internal/engine.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- 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 +29 -16
- package/dist/node/Engine.d.ts.map +1 -1
- package/dist/node/Engine.js +38 -14
- package/dist/node/Engine.js.map +1 -1
- package/dist/node/Hash.d.ts +17 -19
- package/dist/node/Hash.d.ts.map +1 -1
- package/dist/node/Hash.js +17 -19
- package/dist/node/Hash.js.map +1 -1
- 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 +95 -8
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +95 -8
- package/dist/node/index.js.map +1 -1
- package/dist/trusted-setups/Paths.d.ts +1 -0
- package/dist/trusted-setups/Paths.d.ts.map +1 -1
- package/dist/trusted-setups/Paths.js +1 -0
- package/dist/trusted-setups/Paths.js.map +1 -1
- package/dist/trusted-setups/Setups.d.ts +35 -0
- package/dist/trusted-setups/Setups.d.ts.map +1 -0
- package/dist/trusted-setups/Setups.js +29 -0
- package/dist/trusted-setups/Setups.js.map +1 -0
- package/dist/trusted-setups/index.d.ts +20 -0
- package/dist/trusted-setups/index.d.ts.map +1 -1
- package/dist/trusted-setups/index.js +20 -0
- package/dist/trusted-setups/index.js.map +1 -1
- package/dist/trusted-setups/internal/paths.d.ts.map +1 -1
- package/dist/trusted-setups/internal/paths.js +1 -1
- package/dist/trusted-setups/internal/paths.js.map +1 -1
- package/dist/trusted-setups/internal/setups/mainnet.d.ts +7 -0
- package/dist/trusted-setups/internal/setups/mainnet.d.ts.map +1 -0
- package/dist/trusted-setups/internal/setups/mainnet.js +11 -0
- package/dist/trusted-setups/internal/setups/mainnet.js.map +1 -0
- 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 +36 -26
- package/dist/wasm/Engine.d.ts.map +1 -1
- package/dist/wasm/Engine.js +44 -25
- package/dist/wasm/Engine.js.map +1 -1
- package/dist/wasm/Hash.d.ts +13 -19
- package/dist/wasm/Hash.d.ts.map +1 -1
- package/dist/wasm/Hash.js +21 -27
- package/dist/wasm/Hash.js.map +1 -1
- package/dist/wasm/Keystore.d.ts +51 -0
- package/dist/wasm/Keystore.d.ts.map +1 -0
- package/dist/wasm/Keystore.js +51 -0
- package/dist/wasm/Keystore.js.map +1 -0
- package/dist/wasm/Kzg.d.ts +112 -0
- package/dist/wasm/Kzg.d.ts.map +1 -0
- package/dist/wasm/Kzg.js +333 -0
- package/dist/wasm/Kzg.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/Secp256k1.d.ts +55 -0
- package/dist/wasm/Secp256k1.d.ts.map +1 -0
- package/dist/wasm/Secp256k1.js +181 -0
- package/dist/wasm/Secp256k1.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 +124 -12
- package/dist/wasm/index.d.ts.map +1 -1
- package/dist/wasm/index.js +124 -12
- package/dist/wasm/index.js.map +1 -1
- 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/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 +4 -2
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.wasm.js +4 -2
- package/dist/wasm/internal/hashes.wasm.js.map +1 -1
- package/dist/wasm/internal/instantiate.d.ts +12 -0
- package/dist/wasm/internal/instantiate.d.ts.map +1 -1
- package/dist/wasm/internal/instantiate.js +23 -7
- package/dist/wasm/internal/instantiate.js.map +1 -1
- package/dist/wasm/internal/keystore.d.ts +10 -0
- package/dist/wasm/internal/keystore.d.ts.map +1 -0
- package/dist/wasm/internal/keystore.js +10 -0
- package/dist/wasm/internal/keystore.js.map +1 -0
- package/dist/wasm/internal/kzg.d.ts +17 -0
- package/dist/wasm/internal/kzg.d.ts.map +1 -0
- package/dist/wasm/internal/kzg.js +8 -0
- package/dist/wasm/internal/kzg.js.map +1 -0
- package/dist/wasm/internal/kzg.wasm.d.ts +3 -0
- package/dist/wasm/internal/kzg.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/kzg.wasm.js +10 -0
- package/dist/wasm/internal/kzg.wasm.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/scrypt.d.ts +16 -0
- package/dist/wasm/internal/scrypt.d.ts.map +1 -0
- package/dist/wasm/internal/scrypt.js +78 -0
- package/dist/wasm/internal/scrypt.js.map +1 -0
- package/dist/wasm/internal/scrypt.wasm.d.ts +7 -0
- package/dist/wasm/internal/scrypt.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/scrypt.wasm.js +14 -0
- package/dist/wasm/internal/scrypt.wasm.js.map +1 -0
- package/dist/wasm/internal/secp256k1.d.ts +16 -0
- package/dist/wasm/internal/secp256k1.d.ts.map +1 -0
- package/dist/wasm/internal/secp256k1.js +20 -0
- package/dist/wasm/internal/secp256k1.js.map +1 -0
- package/dist/wasm/internal/secp256k1.wasm.d.ts +3 -0
- package/dist/wasm/internal/secp256k1.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/secp256k1.wasm.js +10 -0
- package/dist/wasm/internal/secp256k1.wasm.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/package.json +64 -2
- package/src/core/Engine.ts +84 -11
- package/src/core/Hash.ts +59 -0
- package/src/core/_test/Block.test.ts +9 -2
- package/src/core/_test/Engine.test-d.ts +56 -0
- package/src/core/_test/Engine.test.ts +95 -0
- package/src/core/_test/Hash.test-d.ts +18 -0
- package/src/core/_test/Hash.test.ts +100 -1
- package/src/core/_test/Hash.vectors.test.ts +7 -0
- package/src/core/_test/Transaction.test.ts +11 -2
- package/src/core/internal/engine.ts +8 -8
- package/src/index.ts +5 -2
- package/src/node/Ed25519.ts +87 -0
- package/src/node/Engine.ts +79 -23
- package/src/node/Hash.ts +25 -30
- 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 +62 -22
- package/src/node/_test/Hash.test-d.ts +16 -9
- package/src/node/_test/Hash.test.ts +10 -11
- 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 +100 -8
- package/src/trusted-setups/Paths.ts +1 -0
- package/src/trusted-setups/README.md +39 -0
- package/src/trusted-setups/Setups.ts +46 -0
- package/src/trusted-setups/_test/Paths.test.ts +16 -0
- package/src/trusted-setups/_test/Setups.test-d.ts +7 -0
- package/src/trusted-setups/_test/Setups.test.ts +43 -0
- package/src/trusted-setups/_test/index.test.ts +1 -0
- package/src/trusted-setups/index.ts +21 -0
- package/src/trusted-setups/internal/paths.ts +4 -1
- package/src/trusted-setups/internal/setups/mainnet.source.json +7 -0
- package/src/trusted-setups/internal/setups/mainnet.ts +16 -0
- package/src/version.ts +1 -1
- package/src/wasm/Ed25519.ts +114 -0
- package/src/wasm/Engine.ts +78 -31
- package/src/wasm/Hash.bench.ts +2 -2
- package/src/wasm/Hash.ts +29 -50
- package/src/wasm/Keystore.bench.ts +26 -0
- package/src/wasm/Keystore.ts +66 -0
- package/src/wasm/Kzg.bench.ts +63 -0
- package/src/wasm/Kzg.ts +518 -0
- package/src/wasm/Mnemonic.ts +44 -0
- package/src/wasm/Secp256k1.bench.ts +79 -0
- package/src/wasm/Secp256k1.ts +248 -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 +29 -0
- package/src/wasm/_test/Engine.test.ts +59 -25
- package/src/wasm/_test/Hash.browser.test.ts +14 -7
- package/src/wasm/_test/Hash.fuzz.ts +58 -23
- package/src/wasm/_test/Hash.test-d.ts +16 -10
- package/src/wasm/_test/Hash.test.ts +148 -48
- package/src/wasm/_test/Hash.vectors.test.ts +15 -8
- package/src/wasm/_test/Keystore.browser.test.ts +73 -0
- package/src/wasm/_test/Keystore.fuzz.ts +163 -0
- package/src/wasm/_test/Keystore.test-d.ts +42 -0
- package/src/wasm/_test/Keystore.test.ts +477 -0
- package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
- package/src/wasm/_test/Kzg.test-d.ts +19 -0
- package/src/wasm/_test/Kzg.test.ts +220 -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 +9 -0
- package/src/wasm/_test/Secp256k1.test-d.ts +35 -0
- package/src/wasm/_test/Secp256k1.test.ts +354 -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/index.ts +130 -12
- 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/hashes.ts +29 -0
- package/src/wasm/internal/hashes.wasm.ts +5 -2
- package/src/wasm/internal/instantiate.ts +29 -9
- package/src/wasm/internal/keystore.ts +19 -0
- package/src/wasm/internal/kzg.ts +50 -0
- package/src/wasm/internal/kzg.wasm.ts +11 -0
- package/src/wasm/internal/mnemonic.ts +56 -0
- package/src/wasm/internal/pbkdf2.ts +86 -0
- package/src/wasm/internal/scrypt.ts +131 -0
- package/src/wasm/internal/scrypt.wasm.ts +17 -0
- package/src/wasm/internal/secp256k1.ts +62 -0
- package/src/wasm/internal/secp256k1.wasm.ts +11 -0
- package/src/wasm/internal/x25519.ts +29 -0
- package/wasm/vendor/c-kzg-4844/LICENSE +201 -0
- package/wasm/vendor/c-kzg-4844/blst/LICENSE +201 -0
- package/src/trusted-setups/internal/setups/mainnet.txt +0 -4163
package/src/core/Hash.ts
CHANGED
|
@@ -3,6 +3,65 @@ import type * as Errors from './Errors.js'
|
|
|
3
3
|
import * as Hex from './Hex.js'
|
|
4
4
|
import * as engine from './internal/hash.js'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Calculates the [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) hash of a {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value.
|
|
8
|
+
*
|
|
9
|
+
* Backed by `blake3` from [`@noble/hashes`](https://github.com/paulmillr/noble-hashes), an audited & minimal JS hashing library, unless another implementation is installed with {@link ox#Engine.set}.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts twoslash
|
|
13
|
+
* import { Hash } from 'ox'
|
|
14
|
+
*
|
|
15
|
+
* Hash.blake3('0xdeadbeef')
|
|
16
|
+
* // @log: '0x53147f3ce49ed4f60dfa5b9654c36ba6103c11f5737df3dabd4cbd296c4161bd'
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ### Configure Return Type
|
|
21
|
+
*
|
|
22
|
+
* ```ts twoslash
|
|
23
|
+
* import { Hash } from 'ox'
|
|
24
|
+
*
|
|
25
|
+
* Hash.blake3('0xdeadbeef', { as: 'Bytes' })
|
|
26
|
+
* // @log: Uint8Array [...]
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param value - {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value.
|
|
30
|
+
* @param options - Options.
|
|
31
|
+
* @returns BLAKE3 hash.
|
|
32
|
+
*/
|
|
33
|
+
export function blake3<
|
|
34
|
+
value extends Hex.Hex | Bytes.Bytes,
|
|
35
|
+
as extends 'Hex' | 'Bytes' =
|
|
36
|
+
| (value extends Hex.Hex ? 'Hex' : never)
|
|
37
|
+
| (value extends Bytes.Bytes ? 'Bytes' : never),
|
|
38
|
+
>(
|
|
39
|
+
value: value | Hex.Hex | Bytes.Bytes,
|
|
40
|
+
options: blake3.Options<as> = {},
|
|
41
|
+
): blake3.ReturnType<as> {
|
|
42
|
+
const isBytes = value instanceof Uint8Array
|
|
43
|
+
const { as = isBytes ? 'Bytes' : 'Hex' } = options
|
|
44
|
+
const bytes = engine.blake3(isBytes ? value : Bytes.from(value))
|
|
45
|
+
if (as === 'Bytes') return bytes as never
|
|
46
|
+
return Hex.fromBytes(bytes) as never
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export declare namespace blake3 {
|
|
50
|
+
type Options<as extends 'Hex' | 'Bytes' = 'Hex' | 'Bytes'> = {
|
|
51
|
+
/** The return type. Defaults to the input format. */
|
|
52
|
+
as?: as | 'Hex' | 'Bytes' | undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type ReturnType<as extends 'Hex' | 'Bytes' = 'Hex' | 'Bytes'> =
|
|
56
|
+
| (as extends 'Bytes' ? Bytes.Bytes : never)
|
|
57
|
+
| (as extends 'Hex' ? Hex.Hex : never)
|
|
58
|
+
|
|
59
|
+
type ErrorType =
|
|
60
|
+
| Bytes.from.ErrorType
|
|
61
|
+
| Hex.fromBytes.ErrorType
|
|
62
|
+
| Errors.GlobalErrorType
|
|
63
|
+
}
|
|
64
|
+
|
|
6
65
|
/**
|
|
7
66
|
* Calculates the [Keccak256](https://en.wikipedia.org/wiki/SHA-3) hash of a {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value.
|
|
8
67
|
*
|
|
@@ -400,9 +400,16 @@ describe('fromRpc', () => {
|
|
|
400
400
|
method: 'eth_getBlockByNumber',
|
|
401
401
|
params: ['latest', true],
|
|
402
402
|
})
|
|
403
|
-
.then(Block.fromRpc)
|
|
403
|
+
.then((block) => Block.fromRpc(block, { includeTransactions: true }))
|
|
404
404
|
|
|
405
|
-
|
|
405
|
+
const transactions = block?.transactions.map((transaction) => {
|
|
406
|
+
const { blockTimestamp: _, ...transaction_ } = {
|
|
407
|
+
blockTimestamp: undefined,
|
|
408
|
+
...transaction,
|
|
409
|
+
}
|
|
410
|
+
return transaction_
|
|
411
|
+
})
|
|
412
|
+
expect({ ...block, transactions }).toMatchSnapshot()
|
|
406
413
|
})
|
|
407
414
|
})
|
|
408
415
|
|
|
@@ -17,6 +17,62 @@ type Unlisted = {
|
|
|
17
17
|
>
|
|
18
18
|
}[keyof Engine.Engine]
|
|
19
19
|
|
|
20
|
+
describe('install', () => {
|
|
21
|
+
test('accepts raw and promised slots and preserves their resolved shape', () => {
|
|
22
|
+
const keccak256 = (input: Uint8Array) => input
|
|
23
|
+
const toSeed = (_mnemonic: string) => new Uint8Array(64)
|
|
24
|
+
|
|
25
|
+
expectTypeOf(
|
|
26
|
+
Engine.install({
|
|
27
|
+
Hash: Promise.resolve({ keccak256 }),
|
|
28
|
+
Mnemonic: { toSeed },
|
|
29
|
+
}),
|
|
30
|
+
).toEqualTypeOf<
|
|
31
|
+
Promise<{
|
|
32
|
+
Hash: { keccak256: typeof keccak256 }
|
|
33
|
+
Mnemonic: { toSeed: typeof toSeed }
|
|
34
|
+
}>
|
|
35
|
+
>()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('rejects an unknown slot', () => {
|
|
39
|
+
// @ts-expect-error
|
|
40
|
+
void Engine.install({ Keccak: Promise.resolve({}) })
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('rejects an unknown slot alongside a valid slot', () => {
|
|
44
|
+
void Engine.install({
|
|
45
|
+
Hash: { keccak256: (input) => input },
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
Keccak: {},
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('rejects a misspelled function', () => {
|
|
52
|
+
void Engine.install({
|
|
53
|
+
// @ts-expect-error
|
|
54
|
+
Hash: Promise.resolve({ keccak_256: (input: Uint8Array) => input }),
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('rejects a misspelled function alongside a valid function', () => {
|
|
59
|
+
void Engine.install({
|
|
60
|
+
// @ts-expect-error
|
|
61
|
+
Hash: {
|
|
62
|
+
keccak256: (input: Uint8Array) => input,
|
|
63
|
+
keccak_256: (input: Uint8Array) => input,
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('rejects a mistyped promised function', () => {
|
|
69
|
+
void Engine.install({
|
|
70
|
+
// @ts-expect-error
|
|
71
|
+
Hash: Promise.resolve({ keccak256: (input: string) => input }),
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
20
76
|
describe('set', () => {
|
|
21
77
|
test('accepts a partial engine', () => {
|
|
22
78
|
expectTypeOf(Engine.set).parameter(0).toEqualTypeOf<Engine.Engine>()
|
|
@@ -38,6 +38,101 @@ function merkelize() {
|
|
|
38
38
|
return BinaryStateTree.merkelize(tree)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
describe('install', () => {
|
|
42
|
+
test('behavior: resolves slots in parallel and installs them atomically', async () => {
|
|
43
|
+
const keccak256 = () => new Uint8Array(32).fill(1)
|
|
44
|
+
const sign = () => new Uint8Array(65).fill(3)
|
|
45
|
+
const toSeed = () => new Uint8Array(64).fill(2)
|
|
46
|
+
let releaseHash: (() => void) | undefined
|
|
47
|
+
|
|
48
|
+
Engine.set({ Secp256k1: { sign } })
|
|
49
|
+
|
|
50
|
+
const hash = {
|
|
51
|
+
// oxlint-disable-next-line unicorn/no-thenable -- Distinguishes parallel resolution from sequential awaits.
|
|
52
|
+
then(
|
|
53
|
+
resolve: (value: Engine.Hash) => void,
|
|
54
|
+
reject: (reason: unknown) => void,
|
|
55
|
+
) {
|
|
56
|
+
const timeout = setTimeout(
|
|
57
|
+
() => reject(new Error('slots resolved serially')),
|
|
58
|
+
0,
|
|
59
|
+
)
|
|
60
|
+
releaseHash = () => {
|
|
61
|
+
clearTimeout(timeout)
|
|
62
|
+
resolve({ keccak256 })
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
} as unknown as PromiseLike<Engine.Hash>
|
|
66
|
+
const mnemonic = {
|
|
67
|
+
// oxlint-disable-next-line unicorn/no-thenable -- Distinguishes parallel resolution from sequential awaits.
|
|
68
|
+
then(resolve: (value: Engine.Mnemonic) => void) {
|
|
69
|
+
resolve({ toSeed })
|
|
70
|
+
releaseHash?.()
|
|
71
|
+
},
|
|
72
|
+
} as unknown as PromiseLike<Engine.Mnemonic>
|
|
73
|
+
|
|
74
|
+
const installed = await Engine.install({ Hash: hash, Mnemonic: mnemonic })
|
|
75
|
+
|
|
76
|
+
expect(installed).toEqual({
|
|
77
|
+
Hash: { keccak256 },
|
|
78
|
+
Mnemonic: { toSeed },
|
|
79
|
+
})
|
|
80
|
+
expect(Engine.get()).toEqual({
|
|
81
|
+
...installed,
|
|
82
|
+
Secp256k1: { sign },
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('behavior: a rejected slot leaves the previous engine installed', async () => {
|
|
87
|
+
const keccak256 = () => new Uint8Array(32).fill(1)
|
|
88
|
+
Engine.set({ Hash: { keccak256 } })
|
|
89
|
+
|
|
90
|
+
await expect(
|
|
91
|
+
Engine.install({
|
|
92
|
+
Hash: Promise.resolve({
|
|
93
|
+
sha256: () => new Uint8Array(32).fill(2),
|
|
94
|
+
}),
|
|
95
|
+
Mnemonic: Promise.reject(new Error('could not load engine')),
|
|
96
|
+
}),
|
|
97
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
98
|
+
`[Error: could not load engine]`,
|
|
99
|
+
)
|
|
100
|
+
expect(Engine.get()).toEqual({ Hash: { keccak256 } })
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('behavior: an invalid resolved engine leaves the previous engine installed', async () => {
|
|
104
|
+
const keccak256 = () => new Uint8Array(32).fill(1)
|
|
105
|
+
Engine.set({ Hash: { keccak256 } })
|
|
106
|
+
|
|
107
|
+
await expect(
|
|
108
|
+
Engine.install({
|
|
109
|
+
Hash: Promise.resolve({
|
|
110
|
+
sha256: () => new Uint8Array(32).fill(2),
|
|
111
|
+
}),
|
|
112
|
+
Mnemonic: Promise.resolve({
|
|
113
|
+
to_seed: () => new Uint8Array(64),
|
|
114
|
+
}),
|
|
115
|
+
} as never),
|
|
116
|
+
).rejects.toThrowError(Engine.UnknownPrimitiveError)
|
|
117
|
+
expect(Engine.get()).toEqual({ Hash: { keccak256 } })
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('behavior: a null resolved slot leaves the previous engine installed', async () => {
|
|
121
|
+
const keccak256 = () => new Uint8Array(32).fill(1)
|
|
122
|
+
Engine.set({ Hash: { keccak256 } })
|
|
123
|
+
|
|
124
|
+
await expect(
|
|
125
|
+
Engine.install({
|
|
126
|
+
Hash: Promise.resolve({
|
|
127
|
+
sha256: () => new Uint8Array(32).fill(2),
|
|
128
|
+
}),
|
|
129
|
+
Mnemonic: Promise.resolve(null),
|
|
130
|
+
} as never),
|
|
131
|
+
).rejects.toThrowError(Engine.InvalidSlotValueError)
|
|
132
|
+
expect(Engine.get()).toEqual({ Hash: { keccak256 } })
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
41
136
|
describe('set', () => {
|
|
42
137
|
test('behavior: empty engine is a no-op', () => {
|
|
43
138
|
const before = Hash.keccak256(payload)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Bytes, Hash, type Hex } from 'ox'
|
|
2
|
+
import { describe, expectTypeOf, test } from 'vp/test'
|
|
3
|
+
|
|
4
|
+
describe('blake3', () => {
|
|
5
|
+
test('default', () => {
|
|
6
|
+
expectTypeOf(Hash.blake3('0x')).toEqualTypeOf<Hex.Hex>()
|
|
7
|
+
expectTypeOf(Hash.blake3(new Uint8Array())).toEqualTypeOf<Bytes.Bytes>()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('as', () => {
|
|
11
|
+
expectTypeOf(
|
|
12
|
+
Hash.blake3('0x', { as: 'Bytes' }),
|
|
13
|
+
).toEqualTypeOf<Bytes.Bytes>()
|
|
14
|
+
expectTypeOf(
|
|
15
|
+
Hash.blake3(new Uint8Array(), { as: 'Hex' }),
|
|
16
|
+
).toEqualTypeOf<Hex.Hex>()
|
|
17
|
+
})
|
|
18
|
+
})
|
|
@@ -1,6 +1,104 @@
|
|
|
1
|
-
import { Hash } from 'ox'
|
|
1
|
+
import { Engine, Hash } from 'ox'
|
|
2
2
|
import { describe, expect, test } from 'vp/test'
|
|
3
3
|
|
|
4
|
+
describe('blake3', () => {
|
|
5
|
+
test('default', () => {
|
|
6
|
+
expect(Hash.blake3('0x')).toMatchInlineSnapshot(
|
|
7
|
+
`"0xaf1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"`,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
expect(Hash.blake3(new Uint8Array())).toMatchInlineSnapshot(`
|
|
11
|
+
Uint8Array [
|
|
12
|
+
175,
|
|
13
|
+
19,
|
|
14
|
+
73,
|
|
15
|
+
185,
|
|
16
|
+
245,
|
|
17
|
+
249,
|
|
18
|
+
161,
|
|
19
|
+
166,
|
|
20
|
+
160,
|
|
21
|
+
64,
|
|
22
|
+
77,
|
|
23
|
+
234,
|
|
24
|
+
54,
|
|
25
|
+
220,
|
|
26
|
+
201,
|
|
27
|
+
73,
|
|
28
|
+
155,
|
|
29
|
+
203,
|
|
30
|
+
37,
|
|
31
|
+
201,
|
|
32
|
+
173,
|
|
33
|
+
193,
|
|
34
|
+
18,
|
|
35
|
+
183,
|
|
36
|
+
204,
|
|
37
|
+
154,
|
|
38
|
+
147,
|
|
39
|
+
202,
|
|
40
|
+
228,
|
|
41
|
+
31,
|
|
42
|
+
50,
|
|
43
|
+
98,
|
|
44
|
+
]
|
|
45
|
+
`)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('as: Hex', () => {
|
|
49
|
+
expect(Hash.blake3(new Uint8Array(), { as: 'Hex' })).toMatchInlineSnapshot(
|
|
50
|
+
`"0xaf1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"`,
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('as: Bytes', () => {
|
|
55
|
+
expect(Hash.blake3('0x', { as: 'Bytes' })).toMatchInlineSnapshot(`
|
|
56
|
+
Uint8Array [
|
|
57
|
+
175,
|
|
58
|
+
19,
|
|
59
|
+
73,
|
|
60
|
+
185,
|
|
61
|
+
245,
|
|
62
|
+
249,
|
|
63
|
+
161,
|
|
64
|
+
166,
|
|
65
|
+
160,
|
|
66
|
+
64,
|
|
67
|
+
77,
|
|
68
|
+
234,
|
|
69
|
+
54,
|
|
70
|
+
220,
|
|
71
|
+
201,
|
|
72
|
+
73,
|
|
73
|
+
155,
|
|
74
|
+
203,
|
|
75
|
+
37,
|
|
76
|
+
201,
|
|
77
|
+
173,
|
|
78
|
+
193,
|
|
79
|
+
18,
|
|
80
|
+
183,
|
|
81
|
+
204,
|
|
82
|
+
154,
|
|
83
|
+
147,
|
|
84
|
+
202,
|
|
85
|
+
228,
|
|
86
|
+
31,
|
|
87
|
+
50,
|
|
88
|
+
98,
|
|
89
|
+
]
|
|
90
|
+
`)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('behavior: routes through the installed engine', () => {
|
|
94
|
+
Engine.set({ Hash: { blake3: () => new Uint8Array(32).fill(1) } })
|
|
95
|
+
|
|
96
|
+
expect(Hash.blake3('0x')).toMatchInlineSnapshot(
|
|
97
|
+
`"0x0101010101010101010101010101010101010101010101010101010101010101"`,
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
|
|
4
102
|
describe('hmac256', () => {
|
|
5
103
|
test('default', () => {
|
|
6
104
|
expect(
|
|
@@ -530,6 +628,7 @@ describe('validate', () => {
|
|
|
530
628
|
test('exports', () => {
|
|
531
629
|
expect(Object.keys(Hash)).toMatchInlineSnapshot(`
|
|
532
630
|
[
|
|
631
|
+
"blake3",
|
|
533
632
|
"keccak256",
|
|
534
633
|
"hmac256",
|
|
535
634
|
"ripemd160",
|
|
@@ -11,6 +11,13 @@ import * as vectors from '../../../test/vectors/hashes/index.js'
|
|
|
11
11
|
* See `test/vectors/hashes/README.md`.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
describe('blake3', () => {
|
|
15
|
+
test(`matches ${vectors.blake3.length} official BLAKE3 vectors`, () => {
|
|
16
|
+
for (const { digest, message } of vectors.blake3)
|
|
17
|
+
expect(Hash.blake3(message, { as: 'Bytes' })).toEqual(digest)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
14
21
|
describe('sha256', () => {
|
|
15
22
|
test(`matches ${vectors.sha256.length} NIST CAVP vectors`, () => {
|
|
16
23
|
for (const { digest, message } of vectors.sha256)
|
|
@@ -158,7 +158,11 @@ describe('fromRpc', () => {
|
|
|
158
158
|
})
|
|
159
159
|
.then(Transaction.fromRpc)
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
const { blockTimestamp: _, ...transaction_ } = {
|
|
162
|
+
blockTimestamp: undefined,
|
|
163
|
+
...transaction,
|
|
164
|
+
}
|
|
165
|
+
expect(transaction_).toMatchInlineSnapshot(`
|
|
162
166
|
{
|
|
163
167
|
"blockHash": "0x8299a290ae51a8958965987e2caf178a09b8ecde01b737b5f9a8badbacb407cb",
|
|
164
168
|
"blockNumber": 1110749n,
|
|
@@ -411,7 +415,12 @@ describe('fromRpc', () => {
|
|
|
411
415
|
],
|
|
412
416
|
})
|
|
413
417
|
.then(Transaction.fromRpc)
|
|
414
|
-
|
|
418
|
+
|
|
419
|
+
const { blockTimestamp: _, ...transaction_ } = {
|
|
420
|
+
blockTimestamp: undefined,
|
|
421
|
+
...transaction,
|
|
422
|
+
}
|
|
423
|
+
expect(transaction_).toMatchInlineSnapshot(`
|
|
415
424
|
{
|
|
416
425
|
"accessList": [],
|
|
417
426
|
"blockHash": "0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b",
|
|
@@ -263,21 +263,21 @@ export type Bls = {
|
|
|
263
263
|
* @internal
|
|
264
264
|
*/
|
|
265
265
|
export type Engine = {
|
|
266
|
-
/** Implementation for
|
|
266
|
+
/** Implementation for [`Bls`](/api/Bls). */
|
|
267
267
|
Bls?: Bls | undefined
|
|
268
|
-
/** Implementation for
|
|
268
|
+
/** Implementation for [`Ed25519`](/api/Ed25519). */
|
|
269
269
|
Ed25519?: Eddsa | undefined
|
|
270
|
-
/** Implementation for
|
|
270
|
+
/** Implementation for [`Hash`](/api/Hash). */
|
|
271
271
|
Hash?: Hash | undefined
|
|
272
|
-
/** Implementation for
|
|
272
|
+
/** Implementation for [`Keystore`](/api/Keystore). */
|
|
273
273
|
Keystore?: Keystore | undefined
|
|
274
|
-
/** Implementation for
|
|
274
|
+
/** Implementation for [`Mnemonic`](/api/Mnemonic). */
|
|
275
275
|
Mnemonic?: Mnemonic | undefined
|
|
276
|
-
/** Implementation for
|
|
276
|
+
/** Implementation for [`P256`](/api/P256). */
|
|
277
277
|
P256?: Ecdsa | undefined
|
|
278
|
-
/** Implementation for
|
|
278
|
+
/** Implementation for [`Secp256k1`](/api/Secp256k1). */
|
|
279
279
|
Secp256k1?: Ecdsa | undefined
|
|
280
|
-
/** Implementation for
|
|
280
|
+
/** Implementation for [`X25519`](/api/X25519). */
|
|
281
281
|
X25519?: Ecdh | undefined
|
|
282
282
|
}
|
|
283
283
|
|
package/src/index.ts
CHANGED
|
@@ -1536,9 +1536,12 @@ export * as Ed25519 from './core/Ed25519.js'
|
|
|
1536
1536
|
*
|
|
1537
1537
|
* ```ts twoslash
|
|
1538
1538
|
* // @noErrors
|
|
1539
|
-
* import { Engine } from 'ox
|
|
1539
|
+
* import { Engine } from 'ox'
|
|
1540
|
+
* import { Hash } from 'ox/wasm'
|
|
1540
1541
|
*
|
|
1541
|
-
* await Engine.
|
|
1542
|
+
* await Engine.install({
|
|
1543
|
+
* Hash: Hash.engine()
|
|
1544
|
+
* })
|
|
1542
1545
|
* ```
|
|
1543
1546
|
*
|
|
1544
1547
|
* @example
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto'
|
|
2
|
+
import type * as Engine from '../core/Engine.js'
|
|
3
|
+
import type * as Errors from '../core/Errors.js'
|
|
4
|
+
|
|
5
|
+
export * from '../core/Ed25519.js'
|
|
6
|
+
|
|
7
|
+
const privateKeyPrefix = Buffer.from('302e020100300506032b657004220420', 'hex')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Node.js implementation of the [`Ed25519`](/api/Ed25519) engine
|
|
11
|
+
* slot, without installing it.
|
|
12
|
+
*
|
|
13
|
+
* Node's verifier does not implement Ox's ZIP-215 verification semantics, so
|
|
14
|
+
* this engine deliberately omits `verify`. Public-key conversion and random
|
|
15
|
+
* key generation also remain on Ox's default implementation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts twoslash
|
|
19
|
+
* // @noErrors
|
|
20
|
+
* import { Engine } from 'ox'
|
|
21
|
+
* import { Ed25519 } from 'ox/node'
|
|
22
|
+
*
|
|
23
|
+
* await Engine.install({ Ed25519: Ed25519.engine() })
|
|
24
|
+
*
|
|
25
|
+
* Ed25519.getPublicKey({ privateKey: '0x...' })
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @returns The raw `Ed25519` engine slot.
|
|
29
|
+
*/
|
|
30
|
+
export function engine(): Promise<engine.ReturnType> {
|
|
31
|
+
return Promise.resolve({
|
|
32
|
+
getPublicKey: (privateKey) =>
|
|
33
|
+
rawPublicKey(crypto.createPublicKey(toPrivateKey(privateKey))),
|
|
34
|
+
sign: (payload, privateKey) =>
|
|
35
|
+
new Uint8Array(crypto.sign(null, payload, toPrivateKey(privateKey))),
|
|
36
|
+
toMontgomerySecret: (privateKey) => {
|
|
37
|
+
assertLength(privateKey)
|
|
38
|
+
const digest = crypto.hash('sha512', privateKey, 'buffer')
|
|
39
|
+
try {
|
|
40
|
+
const secretKey = Uint8Array.from(digest.subarray(0, 32))
|
|
41
|
+
secretKey[0]! &= 248
|
|
42
|
+
secretKey[31]! &= 127
|
|
43
|
+
secretKey[31]! |= 64
|
|
44
|
+
return secretKey
|
|
45
|
+
} finally {
|
|
46
|
+
digest.fill(0)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare namespace engine {
|
|
53
|
+
/** Every `Ed25519` primitive this module implements. */
|
|
54
|
+
type ReturnType = {
|
|
55
|
+
[key in 'getPublicKey' | 'sign' | 'toMontgomerySecret']-?: NonNullable<
|
|
56
|
+
Engine.Eddsa[key]
|
|
57
|
+
>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type ErrorType = Errors.GlobalErrorType
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function assertLength(key: Uint8Array): void {
|
|
64
|
+
if (key.length !== 32)
|
|
65
|
+
throw new RangeError(
|
|
66
|
+
`Ed25519 private key must be 32 bytes, got ${key.length}`,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function rawPublicKey(publicKey: crypto.KeyObject): Uint8Array {
|
|
71
|
+
const der = publicKey.export({ format: 'der', type: 'spki' })
|
|
72
|
+
return Uint8Array.from(der.subarray(-32))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function toPrivateKey(privateKey: Uint8Array): crypto.KeyObject {
|
|
76
|
+
assertLength(privateKey)
|
|
77
|
+
const der = Buffer.concat([privateKeyPrefix, privateKey])
|
|
78
|
+
try {
|
|
79
|
+
return crypto.createPrivateKey({
|
|
80
|
+
format: 'der',
|
|
81
|
+
key: der,
|
|
82
|
+
type: 'pkcs8',
|
|
83
|
+
})
|
|
84
|
+
} finally {
|
|
85
|
+
der.fill(0)
|
|
86
|
+
}
|
|
87
|
+
}
|