ox 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/dist/core/Base64.d.ts +10 -21
- package/dist/core/Base64.d.ts.map +1 -1
- package/dist/core/Base64.js +8 -127
- package/dist/core/Base64.js.map +1 -1
- package/dist/core/BinaryStateTree.d.ts.map +1 -1
- package/dist/core/BinaryStateTree.js +2 -2
- package/dist/core/BinaryStateTree.js.map +1 -1
- package/dist/core/Bls.d.ts.map +1 -1
- package/dist/core/Bls.js +19 -44
- package/dist/core/Bls.js.map +1 -1
- package/dist/core/Ed25519.d.ts.map +1 -1
- package/dist/core/Ed25519.js +7 -6
- package/dist/core/Ed25519.js.map +1 -1
- package/dist/core/Engine.d.ts +124 -0
- package/dist/core/Engine.d.ts.map +1 -0
- package/dist/core/Engine.js +180 -0
- package/dist/core/Engine.js.map +1 -0
- package/dist/core/Hash.d.ts +4 -4
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +9 -12
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/Keystore.d.ts.map +1 -1
- package/dist/core/Keystore.js +15 -10
- package/dist/core/Keystore.js.map +1 -1
- package/dist/core/Mnemonic.d.ts.map +1 -1
- package/dist/core/Mnemonic.js +3 -2
- package/dist/core/Mnemonic.js.map +1 -1
- package/dist/core/P256.d.ts.map +1 -1
- package/dist/core/P256.js +8 -9
- package/dist/core/P256.js.map +1 -1
- package/dist/core/Secp256k1.d.ts.map +1 -1
- package/dist/core/Secp256k1.js +8 -9
- package/dist/core/Secp256k1.js.map +1 -1
- package/dist/core/WebCryptoP256.d.ts.map +1 -1
- package/dist/core/WebCryptoP256.js +2 -2
- package/dist/core/WebCryptoP256.js.map +1 -1
- package/dist/core/X25519.d.ts.map +1 -1
- package/dist/core/X25519.js +4 -3
- package/dist/core/X25519.js.map +1 -1
- package/dist/core/internal/bls.d.ts +12 -0
- package/dist/core/internal/bls.d.ts.map +1 -0
- package/dist/core/internal/bls.js +79 -0
- package/dist/core/internal/bls.js.map +1 -0
- package/dist/core/internal/codec/base64.d.ts +84 -0
- package/dist/core/internal/codec/base64.d.ts.map +1 -0
- package/dist/core/internal/codec/base64.js +177 -0
- package/dist/core/internal/codec/base64.js.map +1 -0
- package/dist/core/internal/codec/hex.d.ts +49 -4
- package/dist/core/internal/codec/hex.d.ts.map +1 -1
- package/dist/core/internal/codec/hex.js +109 -35
- package/dist/core/internal/codec/hex.js.map +1 -1
- package/dist/core/internal/curves.d.ts +17 -0
- package/dist/core/internal/curves.d.ts.map +1 -0
- package/dist/core/internal/curves.js +17 -0
- package/dist/core/internal/curves.js.map +1 -0
- package/dist/core/internal/ed25519.d.ts +14 -0
- package/dist/core/internal/ed25519.d.ts.map +1 -0
- package/dist/core/internal/ed25519.js +29 -0
- package/dist/core/internal/ed25519.js.map +1 -0
- package/dist/core/internal/engine.d.ts +278 -0
- package/dist/core/internal/engine.d.ts.map +1 -0
- package/dist/core/internal/engine.js +131 -0
- package/dist/core/internal/engine.js.map +1 -0
- package/dist/core/internal/hash.d.ts +12 -0
- package/dist/core/internal/hash.d.ts.map +1 -0
- package/dist/core/internal/hash.js +30 -0
- package/dist/core/internal/hash.js.map +1 -0
- package/dist/core/internal/keystore.d.ts +14 -0
- package/dist/core/internal/keystore.d.ts.map +1 -0
- package/dist/core/internal/keystore.js +32 -0
- package/dist/core/internal/keystore.js.map +1 -0
- package/dist/core/internal/mnemonic.d.ts +4 -0
- package/dist/core/internal/mnemonic.d.ts.map +1 -0
- package/dist/core/internal/mnemonic.js +14 -0
- package/dist/core/internal/mnemonic.js.map +1 -0
- package/dist/core/internal/p256.d.ts +14 -0
- package/dist/core/internal/p256.d.ts.map +1 -0
- package/dist/core/internal/p256.js +36 -0
- package/dist/core/internal/p256.js.map +1 -0
- package/dist/core/internal/secp256k1.d.ts +14 -0
- package/dist/core/internal/secp256k1.d.ts.map +1 -0
- package/dist/core/internal/secp256k1.js +36 -0
- package/dist/core/internal/secp256k1.js.map +1 -0
- package/dist/core/internal/x25519.d.ts +8 -0
- package/dist/core/internal/x25519.d.ts.map +1 -0
- package/dist/core/internal/x25519.js +20 -0
- package/dist/core/internal/x25519.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.docs.d.ts +2 -0
- package/dist/index.docs.d.ts.map +1 -1
- package/dist/index.docs.js +2 -0
- package/dist/index.docs.js.map +1 -1
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -1
- package/dist/node/Engine.d.ts +55 -0
- package/dist/node/Engine.d.ts.map +1 -0
- package/dist/node/Engine.js +51 -0
- package/dist/node/Engine.js.map +1 -0
- package/dist/node/Hash.d.ts +39 -0
- package/dist/node/Hash.d.ts.map +1 -0
- package/dist/node/Hash.js +37 -0
- package/dist/node/Hash.js.map +1 -0
- package/dist/node/index.d.ts +39 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +39 -0
- package/dist/node/index.js.map +1 -0
- package/dist/tempo/VirtualMaster.d.ts +2 -0
- package/dist/tempo/VirtualMaster.d.ts.map +1 -1
- package/dist/tempo/VirtualMaster.js +19 -5
- package/dist/tempo/VirtualMaster.js.map +1 -1
- package/dist/tempo/internal/mine.wasm.d.ts +2 -4
- package/dist/tempo/internal/mine.wasm.d.ts.map +1 -1
- package/dist/tempo/internal/mine.wasm.js +7 -12
- package/dist/tempo/internal/mine.wasm.js.map +1 -1
- package/dist/tempo/internal/virtualMasterPool.js +4 -1
- package/dist/tempo/internal/virtualMasterPool.js.map +1 -1
- package/dist/wasm/Engine.d.ts +62 -0
- package/dist/wasm/Engine.d.ts.map +1 -0
- package/dist/wasm/Engine.js +57 -0
- package/dist/wasm/Engine.js.map +1 -0
- package/dist/wasm/Hash.d.ts +49 -0
- package/dist/wasm/Hash.d.ts.map +1 -0
- package/dist/wasm/Hash.js +70 -0
- package/dist/wasm/Hash.js.map +1 -0
- package/dist/wasm/index.d.ts +46 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js +46 -0
- package/dist/wasm/index.js.map +1 -0
- package/dist/wasm/internal/hash.d.ts +9 -0
- package/dist/wasm/internal/hash.d.ts.map +1 -0
- package/dist/wasm/internal/hash.js +26 -0
- package/dist/wasm/internal/hash.js.map +1 -0
- package/dist/wasm/internal/hashes.wasm.d.ts +5 -0
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.wasm.js +12 -0
- package/dist/wasm/internal/hashes.wasm.js.map +1 -0
- package/dist/wasm/internal/instantiate.d.ts +56 -0
- package/dist/wasm/internal/instantiate.d.ts.map +1 -0
- package/dist/wasm/internal/instantiate.js +92 -0
- package/dist/wasm/internal/instantiate.js.map +1 -0
- package/dist/zod/TypedData.d.ts +12 -12
- package/package.json +36 -1
- package/src/core/Base64.ts +19 -166
- package/src/core/BinaryStateTree.ts +2 -3
- package/src/core/Bls.ts +27 -77
- package/src/core/Ed25519.ts +7 -7
- package/src/core/Engine.ts +235 -0
- package/src/core/Hash.ts +9 -12
- package/src/core/Keystore.ts +17 -17
- package/src/core/Mnemonic.ts +3 -6
- package/src/core/P256.ts +15 -24
- package/src/core/Rlp_tx.bench.ts +2 -4
- package/src/core/Secp256k1.ts +9 -14
- package/src/core/TxEnvelopeEip1559.bench.ts +0 -5
- package/src/core/WebCryptoP256.ts +2 -2
- package/src/core/X25519.ts +4 -3
- package/src/core/_test/AbiParameters.adversarial.fuzz.ts +1 -2
- package/src/core/_test/AbiParameters.fuzz.ts +1 -2
- package/src/core/_test/Base.fuzz.ts +1 -2
- package/src/core/_test/Cbor.fuzz.ts +1 -2
- package/src/core/_test/Engine.fuzz.ts +293 -0
- package/src/core/_test/Engine.test-d.ts +84 -0
- package/src/core/_test/Engine.test.ts +523 -0
- package/src/core/_test/Hash.vectors.test.ts +56 -0
- package/src/core/_test/Hex.fuzz.ts +1 -2
- package/src/core/_test/Rlp.fuzz.ts +1 -2
- package/src/core/_test/Signature.fuzz.ts +1 -2
- package/src/core/_test/curves.test.ts +7 -0
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/bls.ts +121 -0
- package/src/core/internal/codec/_test/base64.conformance.ts +156 -0
- package/src/core/internal/codec/_test/hex.conformance.ts +204 -0
- package/src/core/internal/codec/_test/hex.fuzz.ts +234 -0
- package/src/core/internal/codec/_test/hex.test.ts +124 -0
- package/src/core/internal/codec/base64.ts +222 -0
- package/src/core/internal/codec/hex.ts +115 -34
- package/src/core/internal/curves.ts +18 -0
- package/src/core/internal/ed25519.ts +64 -0
- package/src/core/internal/engine.ts +410 -0
- package/src/core/internal/hash.ts +48 -0
- package/src/core/internal/keystore.ts +107 -0
- package/src/core/internal/mnemonic.ts +18 -0
- package/src/core/internal/p256.ts +91 -0
- package/src/core/internal/secp256k1.ts +91 -0
- package/src/core/internal/x25519.ts +40 -0
- package/src/index.docs.ts +2 -0
- package/src/index.ts +36 -0
- package/src/node/Engine.ts +69 -0
- package/src/node/Hash.ts +56 -0
- package/src/node/_test/Engine.test.ts +62 -0
- package/src/node/_test/Hash.test-d.ts +26 -0
- package/src/node/_test/Hash.test.ts +102 -0
- package/src/node/index.ts +40 -0
- package/src/tempo/VirtualMaster.test.ts +75 -0
- package/src/tempo/VirtualMaster.ts +28 -6
- package/src/tempo/internal/mine.wasm.ts +7 -13
- package/src/tempo/internal/virtualMasterPool.ts +4 -1
- package/src/tsconfig.json +2 -1
- package/src/version.ts +1 -1
- package/src/wasm/Engine.ts +76 -0
- package/src/wasm/Hash.bench.ts +60 -0
- package/src/wasm/Hash.ts +109 -0
- package/src/wasm/_test/Engine.test.ts +62 -0
- package/src/wasm/_test/Hash.browser.test.ts +50 -0
- package/src/wasm/_test/Hash.fuzz.ts +188 -0
- package/src/wasm/_test/Hash.test-d.ts +28 -0
- package/src/wasm/_test/Hash.test.ts +211 -0
- package/src/wasm/_test/Hash.vectors.test.ts +117 -0
- package/src/wasm/_test/Runtime.test.ts +21 -0
- package/src/wasm/_test/runtime.wasm.ts +11 -0
- package/src/wasm/index.ts +47 -0
- package/src/wasm/internal/hash.ts +50 -0
- package/src/wasm/internal/hashes.wasm.ts +14 -0
- package/src/wasm/internal/instantiate.ts +135 -0
- package/src/tempo/internal/mine.c +0 -182
package/src/core/P256.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
normalizePublicKey,
|
|
9
9
|
normalizeSignature,
|
|
10
10
|
} from './internal/cryptoIo.js'
|
|
11
|
+
import * as engine from './internal/p256.js'
|
|
11
12
|
import * as Entropy from './internal/entropy.js'
|
|
12
13
|
import {
|
|
13
14
|
fromRecoveredBytes,
|
|
@@ -85,7 +86,7 @@ export function getPublicKey<as extends 'Hex' | 'Bytes' | 'Object' = 'Object'>(
|
|
|
85
86
|
options: getPublicKey.Options<as>,
|
|
86
87
|
): getPublicKey.ReturnType<as> {
|
|
87
88
|
const { as = 'Object', privateKey } = options
|
|
88
|
-
const bytes =
|
|
89
|
+
const bytes = engine.getPublicKey(Bytes.from(privateKey))
|
|
89
90
|
const publicKey = PublicKey.fromBytes(bytes)
|
|
90
91
|
return formatPublicKey(publicKey, as) as never
|
|
91
92
|
}
|
|
@@ -134,10 +135,9 @@ export function getSharedSecret<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
134
135
|
options: getSharedSecret.Options<as>,
|
|
135
136
|
): getSharedSecret.ReturnType<as> {
|
|
136
137
|
const { as = 'Hex', privateKey, publicKey } = options
|
|
137
|
-
const sharedSecret =
|
|
138
|
+
const sharedSecret = engine.getSharedSecret(
|
|
138
139
|
Bytes.from(privateKey),
|
|
139
140
|
PublicKey.toBytes(normalizePublicKey(publicKey)),
|
|
140
|
-
true, // compressed
|
|
141
141
|
)
|
|
142
142
|
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
|
|
143
143
|
return sharedSecret as never
|
|
@@ -190,7 +190,7 @@ export function randomPrivateKey<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
190
190
|
options: randomPrivateKey.Options<as> = {},
|
|
191
191
|
): randomPrivateKey.ReturnType<as> {
|
|
192
192
|
const { as = 'Hex' } = options
|
|
193
|
-
const bytes =
|
|
193
|
+
const bytes = engine.randomSecretKey()
|
|
194
194
|
if (as === 'Hex') return Hex.fromBytes(bytes) as never
|
|
195
195
|
return bytes as never
|
|
196
196
|
}
|
|
@@ -238,11 +238,8 @@ export function recoverPublicKey<
|
|
|
238
238
|
>(options: recoverPublicKey.Options<as>): recoverPublicKey.ReturnType<as> {
|
|
239
239
|
const { as = 'Object', payload, signature } = options
|
|
240
240
|
const sigBytes = toRecoveredBytes(normalizeSignature<true>(signature))
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
'recovered',
|
|
244
|
-
).recoverPublicKey(Bytes.from(payload))
|
|
245
|
-
const publicKey = PublicKey.fromBytes(point.toBytes(false))
|
|
241
|
+
const bytes = engine.recoverPublicKey(sigBytes, Bytes.from(payload))
|
|
242
|
+
const publicKey = PublicKey.fromBytes(bytes)
|
|
246
243
|
return formatPublicKey(publicKey, as) as never
|
|
247
244
|
}
|
|
248
245
|
|
|
@@ -302,19 +299,13 @@ export function sign<as extends 'Hex' | 'Bytes' | 'Object' = 'Object'>(
|
|
|
302
299
|
payload,
|
|
303
300
|
privateKey,
|
|
304
301
|
} = options
|
|
305
|
-
const sigBytes =
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
: Bytes.from(extraEntropy),
|
|
313
|
-
lowS: true,
|
|
314
|
-
prehash: hash === true,
|
|
315
|
-
format: 'recovered',
|
|
316
|
-
},
|
|
317
|
-
)
|
|
302
|
+
const sigBytes = engine.sign(Bytes.from(payload), Bytes.from(privateKey), {
|
|
303
|
+
extraEntropy:
|
|
304
|
+
typeof extraEntropy === 'boolean'
|
|
305
|
+
? extraEntropy
|
|
306
|
+
: Bytes.from(extraEntropy),
|
|
307
|
+
prehash: hash === true,
|
|
308
|
+
})
|
|
318
309
|
const signature = fromRecoveredBytes(sigBytes)
|
|
319
310
|
return formatSignature(signature, as) as never
|
|
320
311
|
}
|
|
@@ -381,11 +372,11 @@ export declare namespace sign {
|
|
|
381
372
|
*/
|
|
382
373
|
export function verify(options: verify.Options): boolean {
|
|
383
374
|
const { hash, payload, publicKey, signature } = options
|
|
384
|
-
return
|
|
375
|
+
return engine.verify(
|
|
385
376
|
toCompactBytes(normalizeSignature(signature)),
|
|
386
377
|
Bytes.from(payload),
|
|
387
378
|
PublicKey.toBytes(normalizePublicKey(publicKey)),
|
|
388
|
-
{
|
|
379
|
+
{ prehash: hash === true },
|
|
389
380
|
)
|
|
390
381
|
}
|
|
391
382
|
|
package/src/core/Rlp_tx.bench.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// codec-only bench naming under `src/core/Rlp.bench.ts`; this file scopes
|
|
4
|
-
// to transaction-shaped inputs to avoid collision.
|
|
1
|
+
// Scoped to transaction-shaped inputs, the RLP paths every TxEnvelope codec
|
|
2
|
+
// exercises. `src/core/Rlp.bench.ts` covers RLP on its own terms.
|
|
5
3
|
|
|
6
4
|
import { bench, describe } from 'vp/test'
|
|
7
5
|
import * as Hex from './Hex.js'
|
package/src/core/Secp256k1.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
normalizePublicKey,
|
|
10
10
|
normalizeSignature,
|
|
11
11
|
} from './internal/cryptoIo.js'
|
|
12
|
+
import * as engine from './internal/secp256k1.js'
|
|
12
13
|
import * as Entropy from './internal/entropy.js'
|
|
13
14
|
import {
|
|
14
15
|
fromRecoveredBytes,
|
|
@@ -89,7 +90,7 @@ export function getPublicKey<as extends 'Hex' | 'Bytes' | 'Object' = 'Object'>(
|
|
|
89
90
|
options: getPublicKey.Options<as>,
|
|
90
91
|
): getPublicKey.ReturnType<as> {
|
|
91
92
|
const { as = 'Object', privateKey } = options
|
|
92
|
-
const bytes =
|
|
93
|
+
const bytes = engine.getPublicKey(Bytes.from(privateKey))
|
|
93
94
|
const publicKey = PublicKey.fromBytes(bytes)
|
|
94
95
|
return formatPublicKey(publicKey, as) as never
|
|
95
96
|
}
|
|
@@ -142,10 +143,9 @@ export function getSharedSecret<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
142
143
|
options: getSharedSecret.Options<as>,
|
|
143
144
|
): getSharedSecret.ReturnType<as> {
|
|
144
145
|
const { as = 'Hex', privateKey, publicKey } = options
|
|
145
|
-
const sharedSecret =
|
|
146
|
+
const sharedSecret = engine.getSharedSecret(
|
|
146
147
|
Bytes.from(privateKey),
|
|
147
148
|
PublicKey.toBytes(normalizePublicKey(publicKey)),
|
|
148
|
-
true, // compressed
|
|
149
149
|
)
|
|
150
150
|
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
|
|
151
151
|
return sharedSecret as never
|
|
@@ -199,7 +199,7 @@ export function randomPrivateKey<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
199
199
|
options: randomPrivateKey.Options<as> = {},
|
|
200
200
|
): randomPrivateKey.ReturnType<as> {
|
|
201
201
|
const { as = 'Hex' } = options
|
|
202
|
-
const bytes =
|
|
202
|
+
const bytes = engine.randomSecretKey()
|
|
203
203
|
if (as === 'Hex') return Hex.fromBytes(bytes) as never
|
|
204
204
|
return bytes as never
|
|
205
205
|
}
|
|
@@ -296,11 +296,8 @@ export function recoverPublicKey<
|
|
|
296
296
|
>(options: recoverPublicKey.Options<as>): recoverPublicKey.ReturnType<as> {
|
|
297
297
|
const { as = 'Object', payload, signature } = options
|
|
298
298
|
const sigBytes = toRecoveredBytes(normalizeSignature<true>(signature))
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
'recovered',
|
|
302
|
-
).recoverPublicKey(Bytes.from(payload))
|
|
303
|
-
const publicKey = PublicKey.fromBytes(point.toBytes(false))
|
|
299
|
+
const bytes = engine.recoverPublicKey(sigBytes, Bytes.from(payload))
|
|
300
|
+
const publicKey = PublicKey.fromBytes(bytes)
|
|
304
301
|
return formatPublicKey(publicKey, as) as never
|
|
305
302
|
}
|
|
306
303
|
|
|
@@ -360,14 +357,12 @@ export function sign<as extends 'Hex' | 'Bytes' | 'Object' = 'Object'>(
|
|
|
360
357
|
payload,
|
|
361
358
|
privateKey,
|
|
362
359
|
} = options
|
|
363
|
-
const sigBytes =
|
|
360
|
+
const sigBytes = engine.sign(Bytes.from(payload), Bytes.from(privateKey), {
|
|
364
361
|
extraEntropy:
|
|
365
362
|
typeof extraEntropy === 'boolean'
|
|
366
363
|
? extraEntropy
|
|
367
364
|
: Bytes.from(extraEntropy),
|
|
368
|
-
lowS: true,
|
|
369
365
|
prehash: hash === true,
|
|
370
|
-
format: 'recovered',
|
|
371
366
|
})
|
|
372
367
|
const signature = fromRecoveredBytes(sigBytes)
|
|
373
368
|
return formatSignature(signature, as) as never
|
|
@@ -462,11 +457,11 @@ export function verify(options: verify.Options): boolean {
|
|
|
462
457
|
recoverAddress({ payload, signature: options.signature }),
|
|
463
458
|
)
|
|
464
459
|
const sig = normalizeSignature(options.signature)
|
|
465
|
-
return
|
|
460
|
+
return engine.verify(
|
|
466
461
|
toCompactBytes(sig),
|
|
467
462
|
Bytes.from(payload),
|
|
468
463
|
PublicKey.toBytes(normalizePublicKey(options.publicKey)),
|
|
469
|
-
{
|
|
464
|
+
{ prehash: hash === true },
|
|
470
465
|
)
|
|
471
466
|
}
|
|
472
467
|
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
// Track B / transactions: bench coverage for the EIP-1559 envelope
|
|
2
|
-
// serialize / deserialize / hash hot paths. Targets per
|
|
3
|
-
// `tasks/perf-api-audit-transactions.md` Phase 1: ≥ 2× faster envelope
|
|
4
|
-
// serialize and deserialize at the same input.
|
|
5
|
-
|
|
6
1
|
import { bench, describe } from 'vp/test'
|
|
7
2
|
import * as TxEnvelopeEip1559 from './TxEnvelopeEip1559.js'
|
|
8
3
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { p256 } from '@noble/curves/nist.js'
|
|
2
1
|
import * as Bytes from './Bytes.js'
|
|
3
2
|
import * as Errors from './Errors.js'
|
|
4
3
|
import * as Hex from './Hex.js'
|
|
@@ -7,12 +6,13 @@ import {
|
|
|
7
6
|
normalizePublicKey,
|
|
8
7
|
normalizeSignature,
|
|
9
8
|
} from './internal/cryptoIo.js'
|
|
9
|
+
import { p256N } from './internal/curves.js'
|
|
10
10
|
import type { Compute } from './internal/types.js'
|
|
11
11
|
import * as PublicKey from './PublicKey.js'
|
|
12
12
|
import type * as Signature from './Signature.js'
|
|
13
13
|
|
|
14
14
|
/** secp256r1 / P-256 curve order. */
|
|
15
|
-
const N =
|
|
15
|
+
const N = p256N
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Generates an ECDSA P256 key pair that includes:
|
package/src/core/X25519.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { x25519 } from '@noble/curves/ed25519.js'
|
|
|
2
2
|
import * as Bytes from './Bytes.js'
|
|
3
3
|
import type * as Errors from './Errors.js'
|
|
4
4
|
import * as Hex from './Hex.js'
|
|
5
|
+
import * as engine from './internal/x25519.js'
|
|
5
6
|
|
|
6
7
|
/** Re-export of noble/curves X25519 utilities. */
|
|
7
8
|
export const noble = x25519
|
|
@@ -77,7 +78,7 @@ export function getPublicKey<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
77
78
|
): getPublicKey.ReturnType<as> {
|
|
78
79
|
const { as = 'Hex', privateKey } = options
|
|
79
80
|
const privateKeyBytes = Bytes.from(privateKey)
|
|
80
|
-
const publicKeyBytes =
|
|
81
|
+
const publicKeyBytes = engine.getPublicKey(privateKeyBytes)
|
|
81
82
|
if (as === 'Hex') return Hex.fromBytes(publicKeyBytes) as never
|
|
82
83
|
return publicKeyBytes as never
|
|
83
84
|
}
|
|
@@ -130,7 +131,7 @@ export function getSharedSecret<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
130
131
|
const { as = 'Hex', privateKey, publicKey } = options
|
|
131
132
|
const privateKeyBytes = Bytes.from(privateKey)
|
|
132
133
|
const publicKeyBytes = Bytes.from(publicKey)
|
|
133
|
-
const sharedSecretBytes =
|
|
134
|
+
const sharedSecretBytes = engine.getSharedSecret(
|
|
134
135
|
privateKeyBytes,
|
|
135
136
|
publicKeyBytes,
|
|
136
137
|
)
|
|
@@ -182,7 +183,7 @@ export function randomPrivateKey<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
|
182
183
|
options: randomPrivateKey.Options<as> = {},
|
|
183
184
|
): randomPrivateKey.ReturnType<as> {
|
|
184
185
|
const { as = 'Hex' } = options
|
|
185
|
-
const bytes =
|
|
186
|
+
const bytes = engine.randomSecretKey()
|
|
186
187
|
if (as === 'Hex') return Hex.fromBytes(bytes) as never
|
|
187
188
|
return bytes as never
|
|
188
189
|
}
|
|
@@ -3,8 +3,7 @@ import { AbiParameters, Bytes, Hex } from 'ox'
|
|
|
3
3
|
import { describe, expect } from 'vp/test'
|
|
4
4
|
|
|
5
5
|
import { arbitraryAbiCase } from '../../../test/fuzz/arbitraries/abi.js'
|
|
6
|
-
|
|
7
|
-
const numRuns = Number(process.env.FC_NUM_RUNS) || 100
|
|
6
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Whitelist of error names ox is allowed to throw on adversarial-but-
|
|
@@ -3,8 +3,7 @@ import { AbiParameters } from 'ox'
|
|
|
3
3
|
import { describe, expect } from 'vp/test'
|
|
4
4
|
|
|
5
5
|
import { arbitraryAbiCase } from '../../../test/fuzz/arbitraries/abi.js'
|
|
6
|
-
|
|
7
|
-
const numRuns = Number(process.env.FC_NUM_RUNS) || 100
|
|
6
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
8
7
|
|
|
9
8
|
describe('AbiParameters round-trip', () => {
|
|
10
9
|
test.prop(
|
|
@@ -3,8 +3,7 @@ import { Base32, Base58, Base64 } from 'ox'
|
|
|
3
3
|
import { describe, expect } from 'vp/test'
|
|
4
4
|
|
|
5
5
|
import { arbitraryBytes } from '../../../test/fuzz/arbitraries/bytes.js'
|
|
6
|
-
|
|
7
|
-
const numRuns = Number(process.env.FC_NUM_RUNS) || 100
|
|
6
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
8
7
|
|
|
9
8
|
describe('Base32 round-trip', () => {
|
|
10
9
|
test.prop({ bytes: arbitraryBytes() }, { numRuns })(
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { fc, test } from '@fast-check/vitest'
|
|
2
2
|
import { Cbor } from 'ox'
|
|
3
3
|
import { describe, expect } from 'vp/test'
|
|
4
|
-
|
|
5
|
-
const numRuns = Number(process.env.FC_NUM_RUNS) || 100
|
|
4
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Recursive CBOR-encodable value. ox's Cbor module supports:
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { fc, test } from '@fast-check/vitest'
|
|
2
|
+
import {
|
|
3
|
+
Bls,
|
|
4
|
+
Ed25519,
|
|
5
|
+
Engine,
|
|
6
|
+
Hash,
|
|
7
|
+
Keystore,
|
|
8
|
+
Mnemonic,
|
|
9
|
+
P256,
|
|
10
|
+
Secp256k1,
|
|
11
|
+
X25519,
|
|
12
|
+
} from 'ox'
|
|
13
|
+
import { afterEach, describe, expect } from 'vp/test'
|
|
14
|
+
import { identity, sentinel } from '../../../test/engines.js'
|
|
15
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
16
|
+
|
|
17
|
+
const arbitraryBytes = fc.uint8Array({ maxLength: 256, minLength: 0 })
|
|
18
|
+
/**
|
|
19
|
+
* A 32-byte scalar that is a valid private key on every curve ox uses.
|
|
20
|
+
*
|
|
21
|
+
* Built compositionally rather than by filtering, so no candidate is ever
|
|
22
|
+
* rejected: a leading byte in `[0x01, 0x72]` is clear of zero and below every
|
|
23
|
+
* order in play. BLS12-381 sets the ceiling, not the 256-bit curves -- its
|
|
24
|
+
* scalar field is `0x73eda753…`, so anything above `0x72` reduces rather than
|
|
25
|
+
* being used as given, which would quietly narrow what the fuzz explores.
|
|
26
|
+
*/
|
|
27
|
+
const arbitraryPrivateKey = fc
|
|
28
|
+
.tuple(
|
|
29
|
+
fc.integer({ max: 0x72, min: 0x01 }),
|
|
30
|
+
fc.uint8Array({ maxLength: 31, minLength: 31 }),
|
|
31
|
+
)
|
|
32
|
+
.map(([first, rest]) => Uint8Array.of(first, ...rest))
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
Engine.reset()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Each entry runs one routed call site. `run` must be deterministic given its
|
|
40
|
+
* inputs, so that the same call before and after installing an engine can be
|
|
41
|
+
* compared directly.
|
|
42
|
+
*/
|
|
43
|
+
const callSites = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Hash.keccak256',
|
|
46
|
+
run: (bytes: Uint8Array) => Hash.keccak256(bytes),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Hash.sha256',
|
|
50
|
+
run: (bytes: Uint8Array) => Hash.sha256(bytes),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Hash.ripemd160',
|
|
54
|
+
run: (bytes: Uint8Array) => Hash.ripemd160(bytes),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Hash.hmac256',
|
|
58
|
+
run: (bytes: Uint8Array) => Hash.hmac256(new Uint8Array(32).fill(7), bytes),
|
|
59
|
+
},
|
|
60
|
+
] as const
|
|
61
|
+
|
|
62
|
+
describe('identity engine', () => {
|
|
63
|
+
test.prop({ bytes: arbitraryBytes }, { numRuns })(
|
|
64
|
+
'leaves every hash call site unchanged',
|
|
65
|
+
({ bytes }) => {
|
|
66
|
+
const before = callSites.map((site) => site.run(bytes))
|
|
67
|
+
Engine.set(identity)
|
|
68
|
+
expect(callSites.map((site) => site.run(bytes))).toEqual(before)
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
test.prop(
|
|
73
|
+
{ payload: arbitraryBytes, privateKey: arbitraryPrivateKey },
|
|
74
|
+
{
|
|
75
|
+
numRuns,
|
|
76
|
+
},
|
|
77
|
+
)('leaves secp256k1 unchanged', ({ payload, privateKey }) => {
|
|
78
|
+
const before = {
|
|
79
|
+
publicKey: Secp256k1.getPublicKey({ privateKey }),
|
|
80
|
+
signature: Secp256k1.sign({ payload, privateKey }),
|
|
81
|
+
}
|
|
82
|
+
const recovered = Secp256k1.recoverPublicKey({
|
|
83
|
+
payload,
|
|
84
|
+
signature: before.signature,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
Engine.set(identity)
|
|
88
|
+
|
|
89
|
+
expect(Secp256k1.getPublicKey({ privateKey })).toEqual(before.publicKey)
|
|
90
|
+
expect(Secp256k1.sign({ payload, privateKey })).toEqual(before.signature)
|
|
91
|
+
expect(
|
|
92
|
+
Secp256k1.recoverPublicKey({ payload, signature: before.signature }),
|
|
93
|
+
).toEqual(recovered)
|
|
94
|
+
expect(
|
|
95
|
+
Secp256k1.verify({
|
|
96
|
+
payload,
|
|
97
|
+
publicKey: before.publicKey,
|
|
98
|
+
signature: before.signature,
|
|
99
|
+
}),
|
|
100
|
+
).toBe(true)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test.prop(
|
|
104
|
+
{ payload: arbitraryBytes, privateKey: arbitraryPrivateKey },
|
|
105
|
+
{
|
|
106
|
+
numRuns,
|
|
107
|
+
},
|
|
108
|
+
)('leaves P256 unchanged', ({ payload, privateKey }) => {
|
|
109
|
+
const publicKey = P256.getPublicKey({ privateKey })
|
|
110
|
+
const signature = P256.sign({ payload, privateKey })
|
|
111
|
+
|
|
112
|
+
Engine.set(identity)
|
|
113
|
+
|
|
114
|
+
expect(P256.getPublicKey({ privateKey })).toEqual(publicKey)
|
|
115
|
+
expect(P256.sign({ payload, privateKey })).toEqual(signature)
|
|
116
|
+
expect(P256.verify({ payload, publicKey, signature })).toBe(true)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
test.prop(
|
|
120
|
+
{ payload: arbitraryBytes, privateKey: arbitraryPrivateKey },
|
|
121
|
+
{ numRuns },
|
|
122
|
+
)('leaves Ed25519 and X25519 unchanged', ({ payload, privateKey }) => {
|
|
123
|
+
const before = {
|
|
124
|
+
ed25519PublicKey: Ed25519.getPublicKey({ privateKey }),
|
|
125
|
+
signature: Ed25519.sign({ payload, privateKey }),
|
|
126
|
+
x25519PublicKey: X25519.getPublicKey({ privateKey }),
|
|
127
|
+
}
|
|
128
|
+
const sharedSecret = X25519.getSharedSecret({
|
|
129
|
+
privateKey,
|
|
130
|
+
publicKey: before.x25519PublicKey,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
Engine.set(identity)
|
|
134
|
+
|
|
135
|
+
expect(Ed25519.getPublicKey({ privateKey })).toEqual(
|
|
136
|
+
before.ed25519PublicKey,
|
|
137
|
+
)
|
|
138
|
+
expect(Ed25519.sign({ payload, privateKey })).toEqual(before.signature)
|
|
139
|
+
expect(X25519.getPublicKey({ privateKey })).toEqual(before.x25519PublicKey)
|
|
140
|
+
expect(
|
|
141
|
+
X25519.getSharedSecret({
|
|
142
|
+
privateKey,
|
|
143
|
+
publicKey: before.x25519PublicKey,
|
|
144
|
+
}),
|
|
145
|
+
).toEqual(sharedSecret)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test.prop({ password: fc.string({ maxLength: 64 }) }, { numRuns: 10 })(
|
|
149
|
+
'leaves Keystore key derivation unchanged',
|
|
150
|
+
({ password }) => {
|
|
151
|
+
// The smallest parameters ox accepts -- these run per { numRuns } case, and
|
|
152
|
+
// scrypt's real defaults take seconds. `iv` is pinned because it defaults
|
|
153
|
+
// to random, and the returned key is a thunk, so compare derived material
|
|
154
|
+
// rather than the returned tuple.
|
|
155
|
+
const options = {
|
|
156
|
+
iv: '0x6087dab2f9fdbbfaddc31a909735c1e6',
|
|
157
|
+
password,
|
|
158
|
+
salt: '0xae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd',
|
|
159
|
+
} as const
|
|
160
|
+
const before = {
|
|
161
|
+
pbkdf2: Keystore.pbkdf2({ ...options, iterations: 1000 })[0](),
|
|
162
|
+
scrypt: Keystore.scrypt({ ...options, n: 1024, p: 1, r: 1 })[0](),
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
Engine.set(identity)
|
|
166
|
+
|
|
167
|
+
expect(Keystore.pbkdf2({ ...options, iterations: 1000 })[0]()).toEqual(
|
|
168
|
+
before.pbkdf2,
|
|
169
|
+
)
|
|
170
|
+
expect(Keystore.scrypt({ ...options, n: 1024, p: 1, r: 1 })[0]()).toEqual(
|
|
171
|
+
before.scrypt,
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
test.prop(
|
|
177
|
+
{ payload: arbitraryBytes, privateKey: arbitraryPrivateKey },
|
|
178
|
+
{ numRuns: Math.min(numRuns, 10) },
|
|
179
|
+
)('leaves Bls unchanged', ({ payload, privateKey }) => {
|
|
180
|
+
const before = {
|
|
181
|
+
publicKey: Bls.getPublicKey({ privateKey }),
|
|
182
|
+
signature: Bls.sign({ payload, privateKey }),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
Engine.set(identity)
|
|
186
|
+
|
|
187
|
+
expect(Bls.getPublicKey({ privateKey })).toEqual(before.publicKey)
|
|
188
|
+
expect(Bls.sign({ payload, privateKey })).toEqual(before.signature)
|
|
189
|
+
expect(
|
|
190
|
+
Bls.verify({
|
|
191
|
+
payload,
|
|
192
|
+
publicKey: before.publicKey,
|
|
193
|
+
signature: before.signature,
|
|
194
|
+
}),
|
|
195
|
+
).toBe(true)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test.prop({ passphrase: fc.string({ maxLength: 32 }) }, { numRuns })(
|
|
199
|
+
'leaves Mnemonic.toSeed unchanged',
|
|
200
|
+
({ passphrase }) => {
|
|
201
|
+
const mnemonic =
|
|
202
|
+
'test test test test test test test test test test test junk'
|
|
203
|
+
const before = Mnemonic.toSeed(mnemonic, { passphrase })
|
|
204
|
+
Engine.set(identity)
|
|
205
|
+
expect(Mnemonic.toSeed(mnemonic, { passphrase })).toEqual(before)
|
|
206
|
+
},
|
|
207
|
+
)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
describe('sentinel engine', () => {
|
|
211
|
+
test.prop({ bytes: arbitraryBytes }, { numRuns })(
|
|
212
|
+
'is consulted by every hash call site',
|
|
213
|
+
({ bytes }) => {
|
|
214
|
+
// The inverse of the identity property: if a result survives a wrong
|
|
215
|
+
// implementation, the call site never reached the engine at all.
|
|
216
|
+
const before = callSites.map((site) => site.run(bytes))
|
|
217
|
+
Engine.set(sentinel)
|
|
218
|
+
const after = callSites.map((site) => site.run(bytes))
|
|
219
|
+
for (const [index, site] of callSites.entries())
|
|
220
|
+
expect(after[index], site.name).not.toEqual(before[index])
|
|
221
|
+
},
|
|
222
|
+
)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
describe('with', () => {
|
|
226
|
+
test.prop(
|
|
227
|
+
{ bytes: arbitraryBytes, depth: fc.integer({ max: 6, min: 1 }) },
|
|
228
|
+
{ numRuns },
|
|
229
|
+
)('restores the engine at every nesting depth', ({ bytes, depth }) => {
|
|
230
|
+
const expected = Hash.keccak256(bytes)
|
|
231
|
+
|
|
232
|
+
function nest(level: number): void {
|
|
233
|
+
if (level === 0) return
|
|
234
|
+
Engine.with(
|
|
235
|
+
{ Hash: { keccak256: () => new Uint8Array(32).fill(level) } },
|
|
236
|
+
() => {
|
|
237
|
+
expect(Hash.keccak256(bytes, { as: 'Bytes' })[0]).toBe(level)
|
|
238
|
+
nest(level - 1)
|
|
239
|
+
// Unwinding must restore *this* level, not the default.
|
|
240
|
+
expect(Hash.keccak256(bytes, { as: 'Bytes' })[0]).toBe(level)
|
|
241
|
+
},
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
nest(depth)
|
|
246
|
+
expect(Engine.get()).toEqual({})
|
|
247
|
+
expect(Hash.keccak256(bytes)).toEqual(expected)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
test.prop({ bytes: arbitraryBytes }, { numRuns })(
|
|
251
|
+
'restores the engine when the callback throws',
|
|
252
|
+
({ bytes }) => {
|
|
253
|
+
const expected = Hash.keccak256(bytes)
|
|
254
|
+
expect(() =>
|
|
255
|
+
Engine.with({ Hash: { keccak256: () => new Uint8Array(32) } }, () => {
|
|
256
|
+
throw new Error('boom')
|
|
257
|
+
}),
|
|
258
|
+
).toThrow('boom')
|
|
259
|
+
expect(Hash.keccak256(bytes)).toEqual(expected)
|
|
260
|
+
},
|
|
261
|
+
)
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
describe('merge', () => {
|
|
265
|
+
const slotNames = ['Hash', 'Secp256k1', 'P256', 'Ed25519', 'X25519'] as const
|
|
266
|
+
|
|
267
|
+
test.prop(
|
|
268
|
+
{
|
|
269
|
+
slots: fc.array(fc.constantFrom(...slotNames), {
|
|
270
|
+
maxLength: 8,
|
|
271
|
+
minLength: 1,
|
|
272
|
+
}),
|
|
273
|
+
},
|
|
274
|
+
{ numRuns },
|
|
275
|
+
)('accumulates slots across calls in any order', ({ slots }) => {
|
|
276
|
+
for (const slot of slots) Engine.set({ [slot]: {} })
|
|
277
|
+
expect(Object.keys(Engine.get()).sort()).toEqual([...new Set(slots)].sort())
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
test.prop(
|
|
281
|
+
{
|
|
282
|
+
slots: fc.array(fc.constantFrom(...slotNames), {
|
|
283
|
+
maxLength: 8,
|
|
284
|
+
minLength: 1,
|
|
285
|
+
}),
|
|
286
|
+
},
|
|
287
|
+
{ numRuns },
|
|
288
|
+
)('reset clears whatever was accumulated', ({ slots }) => {
|
|
289
|
+
for (const slot of slots) Engine.set({ [slot]: {} })
|
|
290
|
+
Engine.reset()
|
|
291
|
+
expect(Engine.get()).toEqual({})
|
|
292
|
+
})
|
|
293
|
+
})
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Engine } from 'ox'
|
|
2
|
+
import { describe, expectTypeOf, test } from 'vp/test'
|
|
3
|
+
import type { primitives } from '../internal/engine.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Primitives on a slot contract that the runtime name table omits.
|
|
7
|
+
*
|
|
8
|
+
* `set` rejects any name absent from that table, so anything showing up here
|
|
9
|
+
* would be a valid override refused at runtime.
|
|
10
|
+
*/
|
|
11
|
+
type Unlisted = {
|
|
12
|
+
// `-?` because the slots are optional, which would otherwise leave
|
|
13
|
+
// `undefined` in the union and mask a genuinely missing name.
|
|
14
|
+
[key in keyof Engine.Engine]-?: Exclude<
|
|
15
|
+
keyof NonNullable<Engine.Engine[key]>,
|
|
16
|
+
(typeof primitives)[key][number]
|
|
17
|
+
>
|
|
18
|
+
}[keyof Engine.Engine]
|
|
19
|
+
|
|
20
|
+
describe('set', () => {
|
|
21
|
+
test('accepts a partial engine', () => {
|
|
22
|
+
expectTypeOf(Engine.set).parameter(0).toEqualTypeOf<Engine.Engine>()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('rejects an unknown slot', () => {
|
|
26
|
+
// @ts-expect-error
|
|
27
|
+
Engine.set({ Keccak: {} })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('rejects a misspelled function', () => {
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
Engine.set({ Hash: { keccak_256: (input: Uint8Array) => input } })
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('rejects a mistyped function', () => {
|
|
36
|
+
// @ts-expect-error
|
|
37
|
+
Engine.set({ Hash: { keccak256: (input: string) => input } })
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('the runtime name table lists every primitive it must accept', () => {
|
|
41
|
+
expectTypeOf<Unlisted>().toEqualTypeOf<never>()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('get', () => {
|
|
46
|
+
test('default', () => {
|
|
47
|
+
expectTypeOf(Engine.get()).toEqualTypeOf<Engine.Engine>()
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
describe('reset', () => {
|
|
52
|
+
test('accepts a slot name', () => {
|
|
53
|
+
expectTypeOf(Engine.reset)
|
|
54
|
+
.parameter(0)
|
|
55
|
+
.toEqualTypeOf<keyof Engine.Engine | undefined>()
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
describe('with', () => {
|
|
60
|
+
test('preserves the return type', () => {
|
|
61
|
+
expectTypeOf(Engine.with({}, () => 1 as const)).toEqualTypeOf<1>()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe('Engine', () => {
|
|
66
|
+
test('the Secp256k1 and P256 slots share the Ecdsa contract', () => {
|
|
67
|
+
expectTypeOf<Engine.Engine['Secp256k1']>().toEqualTypeOf<
|
|
68
|
+
Engine.Ecdsa | undefined
|
|
69
|
+
>()
|
|
70
|
+
expectTypeOf<Engine.Engine['P256']>().toEqualTypeOf<
|
|
71
|
+
Engine.Ecdsa | undefined
|
|
72
|
+
>()
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('every slot is optional', () => {
|
|
76
|
+
expectTypeOf<Engine.Engine>().toEqualTypeOf<Partial<Engine.Engine>>()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('contracts speak raw bytes, not branded ox types', () => {
|
|
80
|
+
expectTypeOf<NonNullable<Engine.Hash['keccak256']>>().toEqualTypeOf<
|
|
81
|
+
(input: Uint8Array) => Uint8Array
|
|
82
|
+
>()
|
|
83
|
+
})
|
|
84
|
+
})
|