ox 1.1.2 → 1.3.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 +61 -0
- package/dist/core/AbiFunction.d.ts +1 -1
- package/dist/core/AbiFunction.d.ts.map +1 -1
- package/dist/core/AbiFunction.js +6 -2
- package/dist/core/AbiFunction.js.map +1 -1
- package/dist/core/AbiParameters.d.ts +1 -1
- package/dist/core/AbiParameters.d.ts.map +1 -1
- package/dist/core/AbiParameters.js +1 -13
- package/dist/core/AbiParameters.js.map +1 -1
- package/dist/core/AesGcm.d.ts +36 -1
- package/dist/core/AesGcm.d.ts.map +1 -1
- package/dist/core/AesGcm.js +44 -0
- package/dist/core/AesGcm.js.map +1 -1
- package/dist/core/Ed25519.d.ts +46 -1
- package/dist/core/Ed25519.d.ts.map +1 -1
- package/dist/core/Ed25519.js +43 -0
- package/dist/core/Ed25519.js.map +1 -1
- package/dist/core/Engine.d.ts +1 -1
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Hash.d.ts +200 -1
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +207 -0
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/Hex.d.ts.map +1 -1
- package/dist/core/Hex.js +1 -4
- package/dist/core/Hex.js.map +1 -1
- package/dist/core/Rlp.d.ts +32 -0
- package/dist/core/Rlp.d.ts.map +1 -1
- package/dist/core/Rlp.js +146 -0
- package/dist/core/Rlp.js.map +1 -1
- package/dist/core/Secp256k1.d.ts +46 -1
- package/dist/core/Secp256k1.d.ts.map +1 -1
- package/dist/core/Secp256k1.js +48 -0
- package/dist/core/Secp256k1.js.map +1 -1
- package/dist/core/WebAuthn.d.ts +224 -0
- package/dist/core/WebAuthn.d.ts.map +1 -0
- package/dist/core/WebAuthn.js +343 -0
- package/dist/core/WebAuthn.js.map +1 -0
- package/dist/core/WebAuthnP256.d.ts +46 -50
- package/dist/core/WebAuthnP256.d.ts.map +1 -1
- package/dist/core/WebAuthnP256.js +44 -50
- package/dist/core/WebAuthnP256.js.map +1 -1
- package/dist/core/internal/abiParameters.d.ts +7 -87
- package/dist/core/internal/abiParameters.d.ts.map +1 -1
- package/dist/core/internal/abiParameters.js +339 -194
- package/dist/core/internal/abiParameters.js.map +1 -1
- package/dist/core/internal/engine.d.ts +35 -2
- package/dist/core/internal/engine.d.ts.map +1 -1
- package/dist/core/internal/engine.js +12 -1
- package/dist/core/internal/engine.js.map +1 -1
- package/dist/core/internal/hash.d.ts +10 -0
- package/dist/core/internal/hash.d.ts.map +1 -1
- package/dist/core/internal/hash.js +26 -1
- package/dist/core/internal/hash.js.map +1 -1
- package/dist/index.d.ts +23 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/node/Engine.d.ts +1 -1
- package/dist/node/Engine.d.ts.map +1 -1
- package/dist/node/Engine.js.map +1 -1
- package/dist/node/Hash.d.ts +6 -4
- package/dist/node/Hash.d.ts.map +1 -1
- package/dist/node/Hash.js +35 -3
- package/dist/node/Hash.js.map +1 -1
- package/dist/tempo/AuthorizationTempo.d.ts +6 -6
- package/dist/tempo/AuthorizationTempo.js +6 -6
- package/dist/tempo/KeyAuthorization.d.ts +3 -8
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +3 -8
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/SignatureEnvelope.d.ts +8 -8
- package/dist/tempo/SignatureEnvelope.js +8 -8
- 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/Engine.d.ts +4 -3
- package/dist/wasm/Engine.d.ts.map +1 -1
- package/dist/wasm/Engine.js +5 -5
- package/dist/wasm/Engine.js.map +1 -1
- package/dist/wasm/Hash.d.ts +1 -1
- package/dist/wasm/Hash.d.ts.map +1 -1
- package/dist/wasm/Hash.js +5 -0
- package/dist/wasm/Hash.js.map +1 -1
- package/dist/wasm/Keystore.d.ts +23 -9
- package/dist/wasm/Keystore.d.ts.map +1 -1
- package/dist/wasm/Keystore.js +30 -13
- package/dist/wasm/Keystore.js.map +1 -1
- 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/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/index.d.ts +44 -1
- package/dist/wasm/index.d.ts.map +1 -1
- package/dist/wasm/index.js +44 -1
- package/dist/wasm/index.js.map +1 -1
- package/dist/wasm/internal/blake3.d.ts +10 -1
- package/dist/wasm/internal/blake3.d.ts.map +1 -1
- package/dist/wasm/internal/blake3.js +12 -1
- package/dist/wasm/internal/blake3.js.map +1 -1
- package/dist/wasm/internal/blake3.wasm.d.ts +3 -1
- package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/blake3.wasm.js +3 -1
- package/dist/wasm/internal/blake3.wasm.js.map +1 -1
- package/dist/wasm/internal/hash.d.ts +9 -0
- package/dist/wasm/internal/hash.d.ts.map +1 -1
- package/dist/wasm/internal/hash.js +13 -1
- package/dist/wasm/internal/hash.js.map +1 -1
- package/dist/wasm/internal/hashState.d.ts +25 -0
- package/dist/wasm/internal/hashState.d.ts.map +1 -0
- package/dist/wasm/internal/hashState.js +105 -0
- package/dist/wasm/internal/hashState.js.map +1 -0
- package/dist/wasm/internal/hashes.d.ts +12 -1
- package/dist/wasm/internal/hashes.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.js +18 -1
- package/dist/wasm/internal/hashes.js.map +1 -1
- package/dist/wasm/internal/hashes.wasm.d.ts +11 -3
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.wasm.js +11 -3
- 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/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/webauthn/Authentication.d.ts +2 -0
- package/dist/webauthn/Authentication.d.ts.map +1 -1
- package/dist/webauthn/Authentication.js +2 -1
- package/dist/webauthn/Authentication.js.map +1 -1
- package/dist/webauthn/Registration.d.ts.map +1 -1
- package/dist/webauthn/Registration.js +2 -1
- package/dist/webauthn/Registration.js.map +1 -1
- package/dist/webauthn/Types.d.ts +27 -6
- package/dist/webauthn/Types.d.ts.map +1 -1
- package/dist/webauthn/internal/utils.d.ts.map +1 -1
- package/dist/webauthn/internal/utils.js +35 -9
- package/dist/webauthn/internal/utils.js.map +1 -1
- package/dist/zod/TypedData.d.ts +2 -2
- package/package.json +27 -2
- package/src/benchmarks/Ox.bench.ts +6 -0
- package/src/benchmarks/OxNode.bench.ts +8 -0
- package/src/benchmarks/OxV0.bench.ts +4 -0
- package/src/benchmarks/OxWasm.bench.ts +22 -0
- package/src/core/AbiFunction.ts +5 -5
- package/src/core/AbiParameters.ts +8 -20
- package/src/core/AesGcm.ts +86 -1
- package/src/core/Ed25519.ts +87 -1
- package/src/core/Engine.ts +1 -0
- package/src/core/Hash.ts +321 -1
- package/src/core/Hex.ts +1 -4
- package/src/core/Rlp.ts +172 -5
- package/src/core/Secp256k1.ts +92 -1
- package/src/core/WebAuthn.ts +579 -0
- package/src/core/WebAuthnP256.ts +47 -50
- package/src/core/_test/AbiFunction.test.ts +9 -0
- package/src/core/_test/AbiParameters.differential.fuzz.ts +156 -0
- package/src/core/_test/AbiParameters.encode.test.ts +22 -0
- package/src/core/_test/AbiParameters.fuzz.ts +4 -0
- package/src/core/_test/AesGcm.test.ts +76 -0
- package/src/core/_test/Block.test.ts +9 -2
- package/src/core/_test/Ed25519.test-d.ts +13 -1
- package/src/core/_test/Ed25519.test.ts +120 -1
- package/src/core/_test/Engine.test-d.ts +9 -0
- package/src/core/_test/Engine.test.ts +1 -1
- package/src/core/_test/Hash.test-d.ts +41 -0
- package/src/core/_test/Hash.test.ts +278 -1
- package/src/core/_test/Hash.vectors.test.ts +1 -2
- package/src/core/_test/Hex.test.ts +2 -0
- package/src/core/_test/Rlp.test-d.ts +18 -0
- package/src/core/_test/Rlp.test.ts +109 -0
- package/src/core/_test/Secp256k1.test-d.ts +14 -0
- package/src/core/_test/Secp256k1.test.ts +91 -1
- package/src/core/_test/Transaction.test.ts +11 -2
- package/src/core/_test/WebAuthn.test-d.ts +142 -0
- package/src/core/_test/WebAuthn.test.ts +766 -0
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/abiParameters.ts +466 -326
- package/src/core/internal/engine.ts +47 -2
- package/src/core/internal/hash.ts +53 -1
- package/src/index.ts +24 -14
- package/src/node/Engine.ts +1 -0
- package/src/node/Hash.ts +43 -6
- package/src/node/_test/Engine.test-d.ts +1 -0
- package/src/node/_test/Engine.test.ts +2 -0
- package/src/node/_test/Hash.test-d.ts +11 -0
- package/src/node/_test/Hash.test.ts +46 -0
- package/src/tempo/AuthorizationTempo.ts +6 -6
- package/src/tempo/KeyAuthorization.ts +3 -8
- package/src/tempo/SignatureEnvelope.ts +8 -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/Engine.ts +9 -6
- package/src/wasm/Hash.ts +10 -0
- package/src/wasm/Keystore.bench.ts +26 -0
- package/src/wasm/Keystore.ts +32 -14
- package/src/wasm/Kzg.bench.ts +63 -0
- package/src/wasm/Kzg.ts +518 -0
- package/src/wasm/Secp256k1.bench.ts +79 -0
- package/src/wasm/Secp256k1.ts +248 -0
- package/src/wasm/_test/Engine.test-d.ts +2 -0
- package/src/wasm/_test/Engine.test.ts +5 -0
- package/src/wasm/_test/Hash.browser.test.ts +31 -0
- package/src/wasm/_test/Hash.test-d.ts +17 -0
- package/src/wasm/_test/Hash.test.ts +252 -3
- package/src/wasm/_test/Keystore.browser.test.ts +31 -0
- package/src/wasm/_test/Keystore.fuzz.ts +50 -0
- package/src/wasm/_test/Keystore.test-d.ts +10 -1
- package/src/wasm/_test/Keystore.test.ts +289 -4
- package/src/wasm/_test/Kzg.test-d.ts +19 -0
- package/src/wasm/_test/Kzg.test.ts +220 -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/index.ts +46 -1
- package/src/wasm/internal/blake3.ts +23 -2
- package/src/wasm/internal/blake3.wasm.ts +4 -1
- package/src/wasm/internal/hash.ts +27 -1
- package/src/wasm/internal/hashState.ts +154 -0
- package/src/wasm/internal/hashes.ts +56 -15
- package/src/wasm/internal/hashes.wasm.ts +15 -3
- 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/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/webauthn/Authentication.ts +4 -0
- package/src/webauthn/Registration.ts +2 -0
- package/src/webauthn/Types.ts +32 -2
- package/src/webauthn/_test/Authentication.test.ts +123 -1
- package/src/webauthn/_test/Registration.test.ts +26 -6
- package/src/webauthn/_test/WebAuthn.browser.test.ts +28 -0
- package/src/webauthn/internal/utils.ts +41 -8
- 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/wasm/Kzg.ts
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import * as Bytes from '../core/Bytes.js'
|
|
2
|
+
import * as Errors from '../core/Errors.js'
|
|
3
|
+
import * as Hex from '../core/Hex.js'
|
|
4
|
+
import type * as CoreKzg from '../core/Kzg.js'
|
|
5
|
+
import type * as kzg from './internal/kzg.js'
|
|
6
|
+
|
|
7
|
+
export * from '../core/Kzg.js'
|
|
8
|
+
|
|
9
|
+
const blobSize = 131_072
|
|
10
|
+
const cellSize = 2_048
|
|
11
|
+
const cellsPerBlob = 128
|
|
12
|
+
const commitmentSize = 48
|
|
13
|
+
const g1Points = 4_096
|
|
14
|
+
const g2Points = 65
|
|
15
|
+
const proofSize = 48
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Trusted setup points accepted by `create`.
|
|
19
|
+
*
|
|
20
|
+
* Point arrays use the established Ethereum trusted-setup field names. Each
|
|
21
|
+
* field may also be supplied as one packed byte array.
|
|
22
|
+
*/
|
|
23
|
+
export type TrustedSetup = {
|
|
24
|
+
/** 4,096 G1 points in Lagrange form. */
|
|
25
|
+
readonly g1_lagrange: Bytes.Bytes | readonly string[]
|
|
26
|
+
/** 4,096 G1 points in monomial form. */
|
|
27
|
+
readonly g1_monomial: Bytes.Bytes | readonly string[]
|
|
28
|
+
/** 65 G2 points in monomial form. */
|
|
29
|
+
readonly g2_monomial: Bytes.Bytes | readonly string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Creates an independently owned WASM implementation of [`Kzg.Kzg`](/api/Kzg).
|
|
34
|
+
*
|
|
35
|
+
* The factory compiles the c-kzg artifact once per JavaScript realm. Every call
|
|
36
|
+
* instantiates separate WASM memory and trusted-setup state. Call `dispose` when
|
|
37
|
+
* the instance is no longer needed.
|
|
38
|
+
*
|
|
39
|
+
* Operations on an instance are synchronous and run to completion. JavaScript
|
|
40
|
+
* workers do not share an instance, so create one in each worker that needs KZG.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts twoslash
|
|
44
|
+
* // @noErrors
|
|
45
|
+
* import { Setups } from 'ox/trusted-setups'
|
|
46
|
+
* import { Kzg } from 'ox/wasm'
|
|
47
|
+
*
|
|
48
|
+
* const kzg = await Kzg.create({
|
|
49
|
+
* trustedSetup: Setups.mainnet
|
|
50
|
+
* })
|
|
51
|
+
* // Pass `kzg` anywhere that accepts `Kzg.Kzg`.
|
|
52
|
+
*
|
|
53
|
+
* kzg.dispose()
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param options - Trusted setup and precomputation options.
|
|
57
|
+
* @returns An initialized KZG implementation with explicit disposal.
|
|
58
|
+
*/
|
|
59
|
+
export async function create(
|
|
60
|
+
options: create.Options,
|
|
61
|
+
): Promise<create.ReturnType> {
|
|
62
|
+
const { trustedSetup } = options
|
|
63
|
+
const precompute = options.precompute ?? 0
|
|
64
|
+
if (!Number.isInteger(precompute) || precompute < 0 || precompute > 8)
|
|
65
|
+
throw new InvalidPrecomputeError({ precompute })
|
|
66
|
+
|
|
67
|
+
const setup = {
|
|
68
|
+
g1Lagrange: normalizePoints(
|
|
69
|
+
trustedSetup.g1_lagrange,
|
|
70
|
+
g1Points,
|
|
71
|
+
commitmentSize,
|
|
72
|
+
'g1_lagrange',
|
|
73
|
+
),
|
|
74
|
+
g1Monomial: normalizePoints(
|
|
75
|
+
trustedSetup.g1_monomial,
|
|
76
|
+
g1Points,
|
|
77
|
+
commitmentSize,
|
|
78
|
+
'g1_monomial',
|
|
79
|
+
),
|
|
80
|
+
g2Monomial: normalizePoints(
|
|
81
|
+
trustedSetup.g2_monomial,
|
|
82
|
+
g2Points,
|
|
83
|
+
96,
|
|
84
|
+
'g2_monomial',
|
|
85
|
+
),
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const { instantiate } = await import('./internal/kzg.js')
|
|
89
|
+
let module: Awaited<ReturnType<typeof instantiate>> | undefined =
|
|
90
|
+
await instantiate()
|
|
91
|
+
|
|
92
|
+
const getModule = () => {
|
|
93
|
+
if (!module) throw new DisposedError()
|
|
94
|
+
return module
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const initialized = getModule()
|
|
99
|
+
withBuffers(
|
|
100
|
+
initialized,
|
|
101
|
+
[setup.g1Monomial, setup.g1Lagrange, setup.g2Monomial],
|
|
102
|
+
[],
|
|
103
|
+
([g1Monomial, g1Lagrange, g2Monomial]) => {
|
|
104
|
+
assertReturn(
|
|
105
|
+
initialized.exports.kzg_initialize(
|
|
106
|
+
g1Monomial!,
|
|
107
|
+
g1Lagrange!,
|
|
108
|
+
g2Monomial!,
|
|
109
|
+
precompute,
|
|
110
|
+
),
|
|
111
|
+
'initialize',
|
|
112
|
+
)
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
} catch (error) {
|
|
116
|
+
module?.exports.kzg_dispose()
|
|
117
|
+
module = undefined
|
|
118
|
+
throw error
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const instance: create.ReturnType = {
|
|
122
|
+
blobToKzgCommitment(blob) {
|
|
123
|
+
assertBytes(blob, blobSize, 'blob')
|
|
124
|
+
return withBuffers(
|
|
125
|
+
getModule(),
|
|
126
|
+
[blob],
|
|
127
|
+
[commitmentSize],
|
|
128
|
+
([blob], [out]) => {
|
|
129
|
+
const module = getModule()
|
|
130
|
+
assertReturn(
|
|
131
|
+
module.exports.kzg_blob_to_kzg_commitment(out!, blob!),
|
|
132
|
+
'blobToKzgCommitment',
|
|
133
|
+
)
|
|
134
|
+
},
|
|
135
|
+
)[0]!
|
|
136
|
+
},
|
|
137
|
+
computeCells(blob) {
|
|
138
|
+
assertBytes(blob, blobSize, 'blob')
|
|
139
|
+
const bytes = withBuffers(
|
|
140
|
+
getModule(),
|
|
141
|
+
[blob],
|
|
142
|
+
[cellsPerBlob * cellSize],
|
|
143
|
+
([blob], [cells]) => {
|
|
144
|
+
const module = getModule()
|
|
145
|
+
assertReturn(
|
|
146
|
+
module.exports.kzg_compute_cells(cells!, blob!),
|
|
147
|
+
'computeCells',
|
|
148
|
+
)
|
|
149
|
+
},
|
|
150
|
+
)[0]!
|
|
151
|
+
return split(bytes, cellSize)
|
|
152
|
+
},
|
|
153
|
+
computeCellsAndKzgProofs(blob) {
|
|
154
|
+
assertBytes(blob, blobSize, 'blob')
|
|
155
|
+
const [cells, proofs] = withBuffers(
|
|
156
|
+
getModule(),
|
|
157
|
+
[blob],
|
|
158
|
+
[cellsPerBlob * cellSize, cellsPerBlob * proofSize],
|
|
159
|
+
([blob], [cells, proofs]) => {
|
|
160
|
+
const module = getModule()
|
|
161
|
+
assertReturn(
|
|
162
|
+
module.exports.kzg_compute_cells_and_kzg_proofs(
|
|
163
|
+
cells!,
|
|
164
|
+
proofs!,
|
|
165
|
+
blob!,
|
|
166
|
+
),
|
|
167
|
+
'computeCellsAndKzgProofs',
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
)
|
|
171
|
+
return {
|
|
172
|
+
cells: split(cells!, cellSize),
|
|
173
|
+
proofs: split(proofs!, proofSize),
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
dispose() {
|
|
177
|
+
if (!module) return
|
|
178
|
+
const initialized = module
|
|
179
|
+
module = undefined
|
|
180
|
+
initialized.exports.kzg_dispose()
|
|
181
|
+
},
|
|
182
|
+
recoverCellsAndKzgProofs(cellIndices, cells) {
|
|
183
|
+
if (cellIndices.length !== cells.length)
|
|
184
|
+
throw new InvalidInputError({
|
|
185
|
+
message: '`cellIndices` and `cells` must have the same length.',
|
|
186
|
+
})
|
|
187
|
+
if (cells.length < 64 || cells.length > cellsPerBlob)
|
|
188
|
+
throw new InvalidInputError({
|
|
189
|
+
message: '`cells` must contain between 64 and 128 cells.',
|
|
190
|
+
})
|
|
191
|
+
assertCellIndices(cellIndices, true)
|
|
192
|
+
for (const cell of cells) assertBytes(cell, cellSize, 'cell')
|
|
193
|
+
|
|
194
|
+
const values = cellIndices
|
|
195
|
+
.map((index, i) => ({ cell: cells[i]!, index }))
|
|
196
|
+
.sort((a, b) => a.index - b.index)
|
|
197
|
+
const indices = values.map(({ index }) => index)
|
|
198
|
+
const sortedCells = values.map(({ cell }) => cell)
|
|
199
|
+
|
|
200
|
+
const [recoveredCells, proofs] = withBuffers(
|
|
201
|
+
getModule(),
|
|
202
|
+
[encodeIndices(indices), concat(sortedCells)],
|
|
203
|
+
[cellsPerBlob * cellSize, cellsPerBlob * proofSize],
|
|
204
|
+
([indices, cells], [recoveredCells, proofs]) => {
|
|
205
|
+
const module = getModule()
|
|
206
|
+
assertReturn(
|
|
207
|
+
module.exports.kzg_recover_cells_and_kzg_proofs(
|
|
208
|
+
recoveredCells!,
|
|
209
|
+
proofs!,
|
|
210
|
+
indices!,
|
|
211
|
+
cells!,
|
|
212
|
+
values.length,
|
|
213
|
+
),
|
|
214
|
+
'recoverCellsAndKzgProofs',
|
|
215
|
+
)
|
|
216
|
+
},
|
|
217
|
+
)
|
|
218
|
+
return {
|
|
219
|
+
cells: split(recoveredCells!, cellSize),
|
|
220
|
+
proofs: split(proofs!, proofSize),
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
verifyCellKzgProofBatch(commitments, cellIndices, cells, proofs) {
|
|
224
|
+
const count = commitments.length
|
|
225
|
+
if (
|
|
226
|
+
count === 0 ||
|
|
227
|
+
cellIndices.length !== count ||
|
|
228
|
+
cells.length !== count ||
|
|
229
|
+
proofs.length !== count
|
|
230
|
+
)
|
|
231
|
+
throw new InvalidInputError({
|
|
232
|
+
message:
|
|
233
|
+
'`commitments`, `cellIndices`, `cells`, and `proofs` must have the same non-zero length.',
|
|
234
|
+
})
|
|
235
|
+
assertCellIndices(cellIndices, false)
|
|
236
|
+
for (const commitment of commitments)
|
|
237
|
+
assertBytes(commitment, commitmentSize, 'commitment')
|
|
238
|
+
for (const cell of cells) assertBytes(cell, cellSize, 'cell')
|
|
239
|
+
for (const proof of proofs) assertBytes(proof, proofSize, 'proof')
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
withBuffers(
|
|
243
|
+
getModule(),
|
|
244
|
+
[
|
|
245
|
+
concat(commitments),
|
|
246
|
+
encodeIndices(cellIndices),
|
|
247
|
+
concat(cells),
|
|
248
|
+
concat(proofs),
|
|
249
|
+
],
|
|
250
|
+
[4],
|
|
251
|
+
([commitments, indices, cells, proofs], [verified]) => {
|
|
252
|
+
const module = getModule()
|
|
253
|
+
assertReturn(
|
|
254
|
+
module.exports.kzg_verify_cell_kzg_proof_batch(
|
|
255
|
+
verified!,
|
|
256
|
+
commitments!,
|
|
257
|
+
indices!,
|
|
258
|
+
cells!,
|
|
259
|
+
proofs!,
|
|
260
|
+
count,
|
|
261
|
+
),
|
|
262
|
+
'verifyCellKzgProofBatch',
|
|
263
|
+
)
|
|
264
|
+
},
|
|
265
|
+
)[0]![0] === 1
|
|
266
|
+
)
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
return instance
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export declare namespace create {
|
|
273
|
+
/** Options for `create`. */
|
|
274
|
+
type Options = {
|
|
275
|
+
/**
|
|
276
|
+
* Fixed-base MSM window from 0 through 8.
|
|
277
|
+
*
|
|
278
|
+
* `0` performs no fixed-base precomputation and uses the least memory.
|
|
279
|
+
* Larger values improve proof generation at an exponential memory cost.
|
|
280
|
+
*
|
|
281
|
+
* @default 0
|
|
282
|
+
*/
|
|
283
|
+
precompute?: number | undefined
|
|
284
|
+
/** Ethereum trusted-setup points. */
|
|
285
|
+
trustedSetup: TrustedSetup
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** An initialized KZG implementation with explicit lifecycle ownership. */
|
|
289
|
+
type ReturnType = CoreKzg.Kzg & {
|
|
290
|
+
/**
|
|
291
|
+
* Releases the trusted setup and makes every operation throw.
|
|
292
|
+
*
|
|
293
|
+
* Disposal is idempotent.
|
|
294
|
+
*/
|
|
295
|
+
dispose(): void
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
type ErrorType =
|
|
299
|
+
| DisposedError
|
|
300
|
+
| InvalidInputError
|
|
301
|
+
| InvalidPrecomputeError
|
|
302
|
+
| InvalidTrustedSetupError
|
|
303
|
+
| MemoryError
|
|
304
|
+
| WasmError
|
|
305
|
+
| Errors.GlobalErrorType
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function assertBytes(value: Bytes.Bytes, size: number, name: string) {
|
|
309
|
+
if (!(value instanceof Uint8Array) || value.length !== size)
|
|
310
|
+
throw new InvalidInputError({
|
|
311
|
+
message: `\`${name}\` must contain exactly ${size} bytes.`,
|
|
312
|
+
})
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function assertCellIndices(indices: readonly number[], unique: boolean) {
|
|
316
|
+
const seen = new Set<number>()
|
|
317
|
+
for (const index of indices) {
|
|
318
|
+
if (!Number.isInteger(index) || index < 0 || index >= cellsPerBlob)
|
|
319
|
+
throw new InvalidInputError({
|
|
320
|
+
message: '`cellIndices` must contain integers from 0 through 127.',
|
|
321
|
+
})
|
|
322
|
+
if (unique && seen.has(index))
|
|
323
|
+
throw new InvalidInputError({
|
|
324
|
+
message: '`cellIndices` must not contain duplicate indices.',
|
|
325
|
+
})
|
|
326
|
+
seen.add(index)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function assertReturn(value: number, operation: string) {
|
|
331
|
+
if (value === 0) return
|
|
332
|
+
if (value === 1)
|
|
333
|
+
throw operation === 'initialize'
|
|
334
|
+
? new InvalidTrustedSetupError()
|
|
335
|
+
: new InvalidInputError({ message: `c-kzg rejected \`${operation}\`.` })
|
|
336
|
+
if (value === 3) throw new MemoryError()
|
|
337
|
+
throw new WasmError({ operation })
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function concat(values: readonly Bytes.Bytes[]) {
|
|
341
|
+
const size = values.reduce((size, value) => size + value.length, 0)
|
|
342
|
+
const result = new Uint8Array(size)
|
|
343
|
+
let offset = 0
|
|
344
|
+
for (const value of values) {
|
|
345
|
+
result.set(value, offset)
|
|
346
|
+
offset += value.length
|
|
347
|
+
}
|
|
348
|
+
return result
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function encodeIndices(indices: readonly number[]) {
|
|
352
|
+
const bytes = new Uint8Array(indices.length * 8)
|
|
353
|
+
const view = new DataView(bytes.buffer)
|
|
354
|
+
for (let i = 0; i < indices.length; i++)
|
|
355
|
+
view.setBigUint64(i * 8, BigInt(indices[i]!), true)
|
|
356
|
+
return bytes
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function normalizePoints(
|
|
360
|
+
value: Bytes.Bytes | readonly string[],
|
|
361
|
+
count: number,
|
|
362
|
+
size: number,
|
|
363
|
+
name: keyof TrustedSetup,
|
|
364
|
+
) {
|
|
365
|
+
const expected = count * size
|
|
366
|
+
if (value instanceof Uint8Array) {
|
|
367
|
+
if (value.length !== expected)
|
|
368
|
+
throw new InvalidTrustedSetupError({
|
|
369
|
+
message: `\`${name}\` must contain exactly ${expected} bytes.`,
|
|
370
|
+
})
|
|
371
|
+
return Uint8Array.from(value)
|
|
372
|
+
}
|
|
373
|
+
if (!Array.isArray(value) || value.length !== count)
|
|
374
|
+
throw new InvalidTrustedSetupError({
|
|
375
|
+
message: `\`${name}\` must contain exactly ${count} points.`,
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
const result = new Uint8Array(expected)
|
|
379
|
+
for (let i = 0; i < value.length; i++) {
|
|
380
|
+
const point = value[i]!
|
|
381
|
+
try {
|
|
382
|
+
const bytes = Hex.toBytes(point as Hex.Hex)
|
|
383
|
+
if (bytes.length !== size) throw new Error()
|
|
384
|
+
result.set(bytes, i * size)
|
|
385
|
+
} catch {
|
|
386
|
+
throw new InvalidTrustedSetupError({
|
|
387
|
+
message: `\`${name}[${i}]\` must be a ${size}-byte hex value.`,
|
|
388
|
+
})
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return result
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function split(value: Bytes.Bytes, size: number) {
|
|
395
|
+
const result: Bytes.Bytes[] = []
|
|
396
|
+
for (let offset = 0; offset < value.length; offset += size)
|
|
397
|
+
result.push(value.slice(offset, offset + size))
|
|
398
|
+
return result
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function withBuffers(
|
|
402
|
+
module: Awaited<ReturnType<typeof kzg.instantiate>>,
|
|
403
|
+
inputs: readonly Bytes.Bytes[],
|
|
404
|
+
outputs: readonly number[],
|
|
405
|
+
call: (inputs: readonly number[], outputs: readonly number[]) => void,
|
|
406
|
+
) {
|
|
407
|
+
const inputPointers: number[] = []
|
|
408
|
+
const outputPointers: number[] = []
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
for (const input of inputs)
|
|
412
|
+
inputPointers.push(allocate(module, input.length))
|
|
413
|
+
for (const size of outputs) outputPointers.push(allocate(module, size))
|
|
414
|
+
|
|
415
|
+
const view = module.view()
|
|
416
|
+
for (let i = 0; i < inputs.length; i++)
|
|
417
|
+
view.set(inputs[i]!, inputPointers[i]!)
|
|
418
|
+
|
|
419
|
+
call(inputPointers, outputPointers)
|
|
420
|
+
|
|
421
|
+
return outputs.map((size, i) =>
|
|
422
|
+
module.view().slice(outputPointers[i]!, outputPointers[i]! + size),
|
|
423
|
+
)
|
|
424
|
+
} catch (cause) {
|
|
425
|
+
if (cause instanceof Errors.BaseError) throw cause
|
|
426
|
+
throw new WasmError({ cause: cause as Error })
|
|
427
|
+
} finally {
|
|
428
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
429
|
+
const pointer = inputPointers[i]
|
|
430
|
+
if (!pointer) continue
|
|
431
|
+
module.exports.zero(pointer, inputs[i]!.length)
|
|
432
|
+
module.exports.dealloc(pointer)
|
|
433
|
+
}
|
|
434
|
+
for (let i = 0; i < outputs.length; i++) {
|
|
435
|
+
const pointer = outputPointers[i]
|
|
436
|
+
if (!pointer) continue
|
|
437
|
+
module.exports.zero(pointer, outputs[i]!)
|
|
438
|
+
module.exports.dealloc(pointer)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function allocate(
|
|
444
|
+
module: Awaited<ReturnType<typeof kzg.instantiate>>,
|
|
445
|
+
size: number,
|
|
446
|
+
) {
|
|
447
|
+
const pointer = module.exports.alloc(size)
|
|
448
|
+
if (!pointer) throw new MemoryError()
|
|
449
|
+
return pointer
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/** Thrown when an operation is called after its KZG instance was disposed. */
|
|
453
|
+
export class DisposedError extends Errors.BaseError {
|
|
454
|
+
override readonly name = 'Kzg.DisposedError'
|
|
455
|
+
|
|
456
|
+
constructor() {
|
|
457
|
+
super('KZG instance has been disposed.')
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** Thrown when a KZG operation receives malformed input. */
|
|
462
|
+
export class InvalidInputError extends Errors.BaseError {
|
|
463
|
+
override readonly name = 'Kzg.InvalidInputError'
|
|
464
|
+
|
|
465
|
+
constructor({ message }: { message: string }) {
|
|
466
|
+
super(message)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** Thrown when `precompute` is outside the supported memory bound. */
|
|
471
|
+
export class InvalidPrecomputeError extends Errors.BaseError {
|
|
472
|
+
override readonly name = 'Kzg.InvalidPrecomputeError'
|
|
473
|
+
|
|
474
|
+
constructor({ precompute }: { precompute: number }) {
|
|
475
|
+
super(
|
|
476
|
+
`\`precompute\` must be an integer from 0 through 8. Got ${precompute}.`,
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** Thrown when c-kzg rejects the trusted setup. */
|
|
482
|
+
export class InvalidTrustedSetupError extends Errors.BaseError {
|
|
483
|
+
override readonly name = 'Kzg.InvalidTrustedSetupError'
|
|
484
|
+
|
|
485
|
+
constructor(options: { message?: string | undefined } = {}) {
|
|
486
|
+
super(options.message ?? 'c-kzg rejected the trusted setup.')
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** Thrown when the KZG artifact reaches its 128 MiB memory limit. */
|
|
491
|
+
export class MemoryError extends Errors.BaseError {
|
|
492
|
+
override readonly name = 'Kzg.MemoryError'
|
|
493
|
+
|
|
494
|
+
constructor() {
|
|
495
|
+
super('KZG WASM memory limit was exceeded.', {
|
|
496
|
+
metaMessages: [
|
|
497
|
+
'The artifact grows memory on demand up to 128 MiB.',
|
|
498
|
+
'Use a smaller `precompute` value or batch fewer proofs.',
|
|
499
|
+
],
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/** Thrown when the KZG artifact traps or reports an internal error. */
|
|
505
|
+
export class WasmError extends Errors.BaseError<Error | undefined> {
|
|
506
|
+
override readonly name = 'Kzg.WasmError'
|
|
507
|
+
|
|
508
|
+
constructor(
|
|
509
|
+
options: { cause?: Error | undefined; operation?: string | undefined } = {},
|
|
510
|
+
) {
|
|
511
|
+
super('KZG WASM operation failed.', {
|
|
512
|
+
cause: options.cause,
|
|
513
|
+
metaMessages: options.operation
|
|
514
|
+
? [`Operation: ${options.operation}`]
|
|
515
|
+
: undefined,
|
|
516
|
+
})
|
|
517
|
+
}
|
|
518
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js'
|
|
2
|
+
import { bench, describe } from 'vp/test'
|
|
3
|
+
import { engine as wasmEngine } from './Secp256k1.js'
|
|
4
|
+
|
|
5
|
+
const wasm = await wasmEngine()
|
|
6
|
+
const privateKey = new Uint8Array(32)
|
|
7
|
+
privateKey[31] = 1
|
|
8
|
+
const privateKeyB = new Uint8Array(32)
|
|
9
|
+
privateKeyB[31] = 2
|
|
10
|
+
const payload = Uint8Array.from({ length: 32 }, (_, index) => index)
|
|
11
|
+
const publicKey = secp256k1.getPublicKey(privateKey, false)
|
|
12
|
+
const publicKeyB = secp256k1.getPublicKey(privateKeyB, false)
|
|
13
|
+
const signature = secp256k1.sign(payload, privateKey, {
|
|
14
|
+
extraEntropy: false,
|
|
15
|
+
format: 'recovered',
|
|
16
|
+
lowS: true,
|
|
17
|
+
prehash: false,
|
|
18
|
+
})
|
|
19
|
+
const signOptions = { extraEntropy: false, prehash: false } as const
|
|
20
|
+
const verifyOptions = { prehash: false } as const
|
|
21
|
+
|
|
22
|
+
describe('getPublicKey', () => {
|
|
23
|
+
bench('ox', () => {
|
|
24
|
+
secp256k1.getPublicKey(privateKey, false)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
bench('ox/wasm', () => {
|
|
28
|
+
wasm.getPublicKey(privateKey)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('getSharedSecret', () => {
|
|
33
|
+
bench('ox', () => {
|
|
34
|
+
secp256k1.getSharedSecret(privateKey, publicKeyB, true)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
bench('ox/wasm', () => {
|
|
38
|
+
wasm.getSharedSecret(privateKey, publicKeyB)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('recoverPublicKey', () => {
|
|
43
|
+
bench('ox', () => {
|
|
44
|
+
secp256k1.Signature.fromBytes(signature, 'recovered')
|
|
45
|
+
.recoverPublicKey(payload)
|
|
46
|
+
.toBytes(false)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
bench('ox/wasm', () => {
|
|
50
|
+
wasm.recoverPublicKey(signature, payload)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('sign', () => {
|
|
55
|
+
bench('ox', () => {
|
|
56
|
+
secp256k1.sign(payload, privateKey, {
|
|
57
|
+
...signOptions,
|
|
58
|
+
format: 'recovered',
|
|
59
|
+
lowS: true,
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
bench('ox/wasm', () => {
|
|
64
|
+
wasm.sign(payload, privateKey, signOptions)
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('verify', () => {
|
|
69
|
+
bench('ox', () => {
|
|
70
|
+
secp256k1.verify(signature.slice(1), payload, publicKey, {
|
|
71
|
+
lowS: true,
|
|
72
|
+
...verifyOptions,
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
bench('ox/wasm', () => {
|
|
77
|
+
wasm.verify(signature.slice(1), payload, publicKey, verifyOptions)
|
|
78
|
+
})
|
|
79
|
+
})
|