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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bytes, Ed25519, Hex, X25519 } from 'ox'
|
|
1
|
+
import { Bytes, Ed25519, Engine, Hex, X25519 } from 'ox'
|
|
2
2
|
import { describe, expect, test } from 'vp/test'
|
|
3
3
|
|
|
4
4
|
describe('createKeyPair', () => {
|
|
@@ -44,6 +44,108 @@ describe('createKeyPair', () => {
|
|
|
44
44
|
})
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
+
describe('fromPrf', () => {
|
|
48
|
+
test.each([
|
|
49
|
+
{
|
|
50
|
+
privateKey:
|
|
51
|
+
'0x2c513679b40b7572cbfaf5aee41680258ab23de9ec68d6eaf243470c28e7cea3',
|
|
52
|
+
prf: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
privateKey:
|
|
56
|
+
'0x7ad5cfcdff4bd56cf35bd854b794c9e18f9bcc3e6e12f9ecc0ef44bb23c6d920',
|
|
57
|
+
prf: '0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
|
58
|
+
},
|
|
59
|
+
] as const)('vector: $prf', ({ privateKey, prf }) => {
|
|
60
|
+
expect(Ed25519.fromPrf(prf)).toBe(privateKey)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('value: Bytes', () => {
|
|
64
|
+
const prf = Bytes.fromHex(
|
|
65
|
+
'0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
|
66
|
+
)
|
|
67
|
+
expect(Ed25519.fromPrf(prf)).toMatchInlineSnapshot(
|
|
68
|
+
`"0x7ad5cfcdff4bd56cf35bd854b794c9e18f9bcc3e6e12f9ecc0ef44bb23c6d920"`,
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('options: as', () => {
|
|
73
|
+
const privateKey = Ed25519.fromPrf(
|
|
74
|
+
'0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
|
75
|
+
{ as: 'Bytes' },
|
|
76
|
+
)
|
|
77
|
+
expect(privateKey).toEqual(
|
|
78
|
+
Bytes.fromHex(
|
|
79
|
+
'0x7ad5cfcdff4bd56cf35bd854b794c9e18f9bcc3e6e12f9ecc0ef44bb23c6d920',
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('behavior: output signs and verifies', () => {
|
|
85
|
+
const privateKey = Ed25519.fromPrf(Bytes.random(32))
|
|
86
|
+
const publicKey = Ed25519.getPublicKey({ privateKey })
|
|
87
|
+
const payload = '0xdeadbeef'
|
|
88
|
+
const signature = Ed25519.sign({ payload, privateKey })
|
|
89
|
+
|
|
90
|
+
expect(Ed25519.verify({ payload, publicKey, signature })).toBe(true)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('behavior: uses versioned label and zero counter', () => {
|
|
94
|
+
const messages: Hex.Hex[] = []
|
|
95
|
+
Engine.with(
|
|
96
|
+
{
|
|
97
|
+
Hash: {
|
|
98
|
+
hmacSha256: (_key, message) => {
|
|
99
|
+
messages.push(Hex.fromBytes(message))
|
|
100
|
+
return new Uint8Array(32)
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
() =>
|
|
105
|
+
Ed25519.fromPrf(
|
|
106
|
+
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
expect(messages).toMatchInlineSnapshot(`
|
|
111
|
+
[
|
|
112
|
+
"0x6f782e656432353531392e66726f6d5072662e763100000000",
|
|
113
|
+
]
|
|
114
|
+
`)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test('behavior: zeroes intermediate key for Hex output', () => {
|
|
118
|
+
const candidate = new Uint8Array(32).fill(1)
|
|
119
|
+
Engine.with(
|
|
120
|
+
{
|
|
121
|
+
Hash: {
|
|
122
|
+
hmacSha256: () => candidate,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
() =>
|
|
126
|
+
Ed25519.fromPrf(
|
|
127
|
+
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
expect(candidate).toEqual(new Uint8Array(32))
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('error: PRF output is too short', () => {
|
|
135
|
+
expect(() => Ed25519.fromPrf(new Uint8Array(31)))
|
|
136
|
+
.toThrowErrorMatchingInlineSnapshot(`
|
|
137
|
+
[Ed25519.InvalidPrfSizeError: PRF output must be exactly 32 bytes. Received 31 bytes.]
|
|
138
|
+
`)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('error: PRF output is too long', () => {
|
|
142
|
+
expect(() => Ed25519.fromPrf(new Uint8Array(33)))
|
|
143
|
+
.toThrowErrorMatchingInlineSnapshot(`
|
|
144
|
+
[Ed25519.InvalidPrfSizeError: PRF output must be exactly 32 bytes. Received 33 bytes.]
|
|
145
|
+
`)
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
47
149
|
describe('getPublicKey', () => {
|
|
48
150
|
const privateKey =
|
|
49
151
|
'0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'
|
|
@@ -436,3 +538,20 @@ describe('noble export', () => {
|
|
|
436
538
|
expect(Ed25519.noble.getPublicKey).toBeDefined()
|
|
437
539
|
})
|
|
438
540
|
})
|
|
541
|
+
|
|
542
|
+
test('exports', () => {
|
|
543
|
+
expect(Object.keys(Ed25519)).toMatchInlineSnapshot(`
|
|
544
|
+
[
|
|
545
|
+
"noble",
|
|
546
|
+
"createKeyPair",
|
|
547
|
+
"fromPrf",
|
|
548
|
+
"getPublicKey",
|
|
549
|
+
"randomPrivateKey",
|
|
550
|
+
"sign",
|
|
551
|
+
"verify",
|
|
552
|
+
"toX25519PublicKey",
|
|
553
|
+
"toX25519PrivateKey",
|
|
554
|
+
"InvalidPrfSizeError",
|
|
555
|
+
]
|
|
556
|
+
`)
|
|
557
|
+
})
|
|
@@ -136,5 +136,14 @@ describe('Engine', () => {
|
|
|
136
136
|
expectTypeOf<NonNullable<Engine.Hash['keccak256']>>().toEqualTypeOf<
|
|
137
137
|
(input: Uint8Array) => Uint8Array
|
|
138
138
|
>()
|
|
139
|
+
expectTypeOf<NonNullable<Engine.Hash['createKeccak256']>>().toEqualTypeOf<
|
|
140
|
+
() => Engine.HashState
|
|
141
|
+
>()
|
|
142
|
+
expectTypeOf<Engine.HashState>().toEqualTypeOf<{
|
|
143
|
+
clone(): Engine.HashState
|
|
144
|
+
destroy(): void
|
|
145
|
+
digestInto(output: Uint8Array): void
|
|
146
|
+
update(input: Uint8Array): void
|
|
147
|
+
}>()
|
|
139
148
|
})
|
|
140
149
|
})
|
|
@@ -266,7 +266,7 @@ describe('set', () => {
|
|
|
266
266
|
).toThrowErrorMatchingInlineSnapshot(`
|
|
267
267
|
[Engine.UnknownPrimitiveError: \`keccak_256\` is not a valid primitive for the \`Hash\` slot.
|
|
268
268
|
|
|
269
|
-
Valid primitives: blake3, hmacSha256, keccak256, ripemd160, sha256]
|
|
269
|
+
Valid primitives: blake3, createBlake3, createHmacSha256, createKeccak256, createRipemd160, createSha256, hmacSha256, keccak256, ripemd160, sha256]
|
|
270
270
|
`)
|
|
271
271
|
})
|
|
272
272
|
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
})
|
|
19
|
+
|
|
20
|
+
describe('incremental', () => {
|
|
21
|
+
test('factories', () => {
|
|
22
|
+
expectTypeOf(Hash.createBlake3()).toEqualTypeOf<Hash.Hasher>()
|
|
23
|
+
expectTypeOf(Hash.createHmac256('0x')).toEqualTypeOf<Hash.Hasher>()
|
|
24
|
+
expectTypeOf(Hash.createKeccak256()).toEqualTypeOf<Hash.Hasher>()
|
|
25
|
+
expectTypeOf(Hash.createRipemd160()).toEqualTypeOf<Hash.Hasher>()
|
|
26
|
+
expectTypeOf(Hash.createSha256()).toEqualTypeOf<Hash.Hasher>()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('Hasher', () => {
|
|
30
|
+
const hash = Hash.createSha256()
|
|
31
|
+
|
|
32
|
+
expectTypeOf(hash.update('0x')).toEqualTypeOf<Hash.Hasher>()
|
|
33
|
+
expectTypeOf(hash.update(new Uint8Array())).toEqualTypeOf<Hash.Hasher>()
|
|
34
|
+
expectTypeOf(hash.clone()).toEqualTypeOf<Hash.Hasher>()
|
|
35
|
+
expectTypeOf(hash.digest()).toEqualTypeOf<Hex.Hex>()
|
|
36
|
+
expectTypeOf(hash.digest({ as: 'Hex' })).toEqualTypeOf<Hex.Hex>()
|
|
37
|
+
expectTypeOf(hash.digest({ as: 'Bytes' })).toEqualTypeOf<Bytes.Bytes>()
|
|
38
|
+
expectTypeOf(hash.digestInto(new Uint8Array())).toEqualTypeOf<void>()
|
|
39
|
+
expectTypeOf(hash.destroy()).toEqualTypeOf<void>()
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -1,6 +1,249 @@
|
|
|
1
|
-
import { Hash } from 'ox'
|
|
1
|
+
import { type Bytes, Engine, Hash, type Hex } from 'ox'
|
|
2
2
|
import { describe, expect, test } from 'vp/test'
|
|
3
3
|
|
|
4
|
+
type Factory = {
|
|
5
|
+
create(): Hash.Hasher
|
|
6
|
+
digest(value: Hex.Hex | Bytes.Bytes): Bytes.Bytes
|
|
7
|
+
digestSize: number
|
|
8
|
+
name: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const factories = [
|
|
12
|
+
{
|
|
13
|
+
create: () => Hash.createBlake3(),
|
|
14
|
+
digest: (value) => Hash.blake3(value, { as: 'Bytes' }),
|
|
15
|
+
digestSize: 32,
|
|
16
|
+
name: 'createBlake3',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
create: () => Hash.createHmac256('0x6b6579'),
|
|
20
|
+
digest: (value) => Hash.hmac256('0x6b6579', value, { as: 'Bytes' }),
|
|
21
|
+
digestSize: 32,
|
|
22
|
+
name: 'createHmac256',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
create: () => Hash.createKeccak256(),
|
|
26
|
+
digest: (value) => Hash.keccak256(value, { as: 'Bytes' }),
|
|
27
|
+
digestSize: 32,
|
|
28
|
+
name: 'createKeccak256',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
create: () => Hash.createRipemd160(),
|
|
32
|
+
digest: (value) => Hash.ripemd160(value, { as: 'Bytes' }),
|
|
33
|
+
digestSize: 20,
|
|
34
|
+
name: 'createRipemd160',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
create: () => Hash.createSha256(),
|
|
38
|
+
digest: (value) => Hash.sha256(value, { as: 'Bytes' }),
|
|
39
|
+
digestSize: 32,
|
|
40
|
+
name: 'createSha256',
|
|
41
|
+
},
|
|
42
|
+
] as const satisfies readonly Factory[]
|
|
43
|
+
|
|
44
|
+
describe('incremental', () => {
|
|
45
|
+
test.each(factories)(
|
|
46
|
+
'$name: chunked input matches the one-shot function',
|
|
47
|
+
({ create, digest }) => {
|
|
48
|
+
const hash = create()
|
|
49
|
+
hash.update('0xdead').update(Uint8Array.of(0xbe, 0xef))
|
|
50
|
+
expect(hash.digest({ as: 'Bytes' })).toEqual(digest('0xdeadbeef'))
|
|
51
|
+
},
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
test.each(factories)(
|
|
55
|
+
'$name: empty input matches the one-shot function',
|
|
56
|
+
({ create, digest }) => {
|
|
57
|
+
expect(create().digest({ as: 'Bytes' })).toEqual(digest('0x'))
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
test.each(factories)(
|
|
62
|
+
'$name: clone branches from the same prefix',
|
|
63
|
+
({ create, digest }) => {
|
|
64
|
+
const first = create().update('0xdead')
|
|
65
|
+
const second = first.clone()
|
|
66
|
+
|
|
67
|
+
first.update('0xbeef')
|
|
68
|
+
second.update('0xcafe')
|
|
69
|
+
|
|
70
|
+
expect(first.digest({ as: 'Bytes' })).toEqual(digest('0xdeadbeef'))
|
|
71
|
+
expect(second.digest({ as: 'Bytes' })).toEqual(digest('0xdeadcafe'))
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
test.each(factories)(
|
|
76
|
+
'$name: digestInto validates bounds without consuming the state',
|
|
77
|
+
({ create, digest, digestSize }) => {
|
|
78
|
+
const hash = create().update('0xdeadbeef')
|
|
79
|
+
|
|
80
|
+
expect(() =>
|
|
81
|
+
hash.digestInto(new Uint8Array(digestSize - 1)),
|
|
82
|
+
).toThrowError(Hash.InvalidDigestSizeError)
|
|
83
|
+
|
|
84
|
+
const output = new Uint8Array(digestSize + 2).fill(0xff)
|
|
85
|
+
hash.digestInto(output)
|
|
86
|
+
|
|
87
|
+
expect(output.slice(0, digestSize)).toEqual(digest('0xdeadbeef'))
|
|
88
|
+
expect(output.slice(digestSize)).toEqual(Uint8Array.of(0xff, 0xff))
|
|
89
|
+
expect(() => hash.update('0x')).toThrowError(Hash.HasherDestroyedError)
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
test.each(factories)(
|
|
94
|
+
'$name: digest consumes the state and destroy is idempotent',
|
|
95
|
+
({ create }) => {
|
|
96
|
+
const hash = create()
|
|
97
|
+
hash.digest()
|
|
98
|
+
|
|
99
|
+
expect(() => hash.clone()).toThrowError(Hash.HasherDestroyedError)
|
|
100
|
+
expect(() => hash.digest()).toThrowError(Hash.HasherDestroyedError)
|
|
101
|
+
expect(() => hash.digestInto(new Uint8Array(32))).toThrowError(
|
|
102
|
+
Hash.HasherDestroyedError,
|
|
103
|
+
)
|
|
104
|
+
expect(() => hash.update('0x')).toThrowError(Hash.HasherDestroyedError)
|
|
105
|
+
expect(() => {
|
|
106
|
+
hash.destroy()
|
|
107
|
+
hash.destroy()
|
|
108
|
+
}).not.toThrow()
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
test.each(factories)(
|
|
113
|
+
'$name: destroy consumes the state and is idempotent',
|
|
114
|
+
({ create }) => {
|
|
115
|
+
const hash = create()
|
|
116
|
+
hash.destroy()
|
|
117
|
+
hash.destroy()
|
|
118
|
+
|
|
119
|
+
expect(() => hash.clone()).toThrowError(Hash.HasherDestroyedError)
|
|
120
|
+
expect(() => hash.digest()).toThrowError(Hash.HasherDestroyedError)
|
|
121
|
+
expect(() => hash.update('0x')).toThrowError(Hash.HasherDestroyedError)
|
|
122
|
+
},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
test('behavior: independent states can be interleaved', () => {
|
|
126
|
+
const first = Hash.createSha256().update('0xaa')
|
|
127
|
+
const second = Hash.createSha256().update('0xbb')
|
|
128
|
+
|
|
129
|
+
first.update('0xcc')
|
|
130
|
+
second.update('0xdd')
|
|
131
|
+
|
|
132
|
+
expect(first.digest()).toEqual(Hash.sha256('0xaacc'))
|
|
133
|
+
expect(second.digest()).toEqual(Hash.sha256('0xbbdd'))
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('behavior: a state keeps the provider captured at creation', () => {
|
|
137
|
+
Engine.set({ Hash: { createSha256: () => sentinelState(1) } })
|
|
138
|
+
const first = Hash.createSha256()
|
|
139
|
+
|
|
140
|
+
Engine.set({ Hash: { createSha256: () => sentinelState(2) } })
|
|
141
|
+
|
|
142
|
+
expect(first.digest({ as: 'Bytes' })[0]).toMatchInlineSnapshot('1')
|
|
143
|
+
expect(
|
|
144
|
+
Hash.createSha256().digest({ as: 'Bytes' })[0],
|
|
145
|
+
).toMatchInlineSnapshot('2')
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
describe('blake3', () => {
|
|
150
|
+
test('default', () => {
|
|
151
|
+
expect(Hash.blake3('0x')).toMatchInlineSnapshot(
|
|
152
|
+
`"0xaf1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"`,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
expect(Hash.blake3(new Uint8Array())).toMatchInlineSnapshot(`
|
|
156
|
+
Uint8Array [
|
|
157
|
+
175,
|
|
158
|
+
19,
|
|
159
|
+
73,
|
|
160
|
+
185,
|
|
161
|
+
245,
|
|
162
|
+
249,
|
|
163
|
+
161,
|
|
164
|
+
166,
|
|
165
|
+
160,
|
|
166
|
+
64,
|
|
167
|
+
77,
|
|
168
|
+
234,
|
|
169
|
+
54,
|
|
170
|
+
220,
|
|
171
|
+
201,
|
|
172
|
+
73,
|
|
173
|
+
155,
|
|
174
|
+
203,
|
|
175
|
+
37,
|
|
176
|
+
201,
|
|
177
|
+
173,
|
|
178
|
+
193,
|
|
179
|
+
18,
|
|
180
|
+
183,
|
|
181
|
+
204,
|
|
182
|
+
154,
|
|
183
|
+
147,
|
|
184
|
+
202,
|
|
185
|
+
228,
|
|
186
|
+
31,
|
|
187
|
+
50,
|
|
188
|
+
98,
|
|
189
|
+
]
|
|
190
|
+
`)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
test('as: Hex', () => {
|
|
194
|
+
expect(Hash.blake3(new Uint8Array(), { as: 'Hex' })).toMatchInlineSnapshot(
|
|
195
|
+
`"0xaf1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"`,
|
|
196
|
+
)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test('as: Bytes', () => {
|
|
200
|
+
expect(Hash.blake3('0x', { as: 'Bytes' })).toMatchInlineSnapshot(`
|
|
201
|
+
Uint8Array [
|
|
202
|
+
175,
|
|
203
|
+
19,
|
|
204
|
+
73,
|
|
205
|
+
185,
|
|
206
|
+
245,
|
|
207
|
+
249,
|
|
208
|
+
161,
|
|
209
|
+
166,
|
|
210
|
+
160,
|
|
211
|
+
64,
|
|
212
|
+
77,
|
|
213
|
+
234,
|
|
214
|
+
54,
|
|
215
|
+
220,
|
|
216
|
+
201,
|
|
217
|
+
73,
|
|
218
|
+
155,
|
|
219
|
+
203,
|
|
220
|
+
37,
|
|
221
|
+
201,
|
|
222
|
+
173,
|
|
223
|
+
193,
|
|
224
|
+
18,
|
|
225
|
+
183,
|
|
226
|
+
204,
|
|
227
|
+
154,
|
|
228
|
+
147,
|
|
229
|
+
202,
|
|
230
|
+
228,
|
|
231
|
+
31,
|
|
232
|
+
50,
|
|
233
|
+
98,
|
|
234
|
+
]
|
|
235
|
+
`)
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
test('behavior: routes through the installed engine', () => {
|
|
239
|
+
Engine.set({ Hash: { blake3: () => new Uint8Array(32).fill(1) } })
|
|
240
|
+
|
|
241
|
+
expect(Hash.blake3('0x')).toMatchInlineSnapshot(
|
|
242
|
+
`"0x0101010101010101010101010101010101010101010101010101010101010101"`,
|
|
243
|
+
)
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
|
|
4
247
|
describe('hmac256', () => {
|
|
5
248
|
test('default', () => {
|
|
6
249
|
expect(
|
|
@@ -527,14 +770,48 @@ describe('validate', () => {
|
|
|
527
770
|
})
|
|
528
771
|
})
|
|
529
772
|
|
|
773
|
+
function sentinelState(byte: number): Engine.HashState {
|
|
774
|
+
let active = true
|
|
775
|
+
|
|
776
|
+
const assertActive = () => {
|
|
777
|
+
if (!active) throw new Error('destroyed')
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
return {
|
|
781
|
+
clone: () => {
|
|
782
|
+
assertActive()
|
|
783
|
+
return sentinelState(byte)
|
|
784
|
+
},
|
|
785
|
+
destroy: () => {
|
|
786
|
+
active = false
|
|
787
|
+
},
|
|
788
|
+
digestInto: (output) => {
|
|
789
|
+
assertActive()
|
|
790
|
+
active = false
|
|
791
|
+
output.fill(byte, 0, 32)
|
|
792
|
+
},
|
|
793
|
+
update: () => {
|
|
794
|
+
assertActive()
|
|
795
|
+
},
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
530
799
|
test('exports', () => {
|
|
531
800
|
expect(Object.keys(Hash)).toMatchInlineSnapshot(`
|
|
532
801
|
[
|
|
802
|
+
"createBlake3",
|
|
803
|
+
"createHmac256",
|
|
804
|
+
"createKeccak256",
|
|
805
|
+
"createRipemd160",
|
|
806
|
+
"createSha256",
|
|
807
|
+
"blake3",
|
|
533
808
|
"keccak256",
|
|
534
809
|
"hmac256",
|
|
535
810
|
"ripemd160",
|
|
536
811
|
"sha256",
|
|
537
812
|
"validate",
|
|
813
|
+
"HasherDestroyedError",
|
|
814
|
+
"InvalidDigestSizeError",
|
|
538
815
|
]
|
|
539
816
|
`)
|
|
540
817
|
})
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Hash } from 'ox'
|
|
2
2
|
import { describe, expect, test } from 'vp/test'
|
|
3
3
|
import * as vectors from '../../../test/vectors/hashes/index.js'
|
|
4
|
-
import * as hash from '../internal/hash.js'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Published vectors against ox's default (`@noble/hashes`) implementations.
|
|
@@ -15,7 +14,7 @@ import * as hash from '../internal/hash.js'
|
|
|
15
14
|
describe('blake3', () => {
|
|
16
15
|
test(`matches ${vectors.blake3.length} official BLAKE3 vectors`, () => {
|
|
17
16
|
for (const { digest, message } of vectors.blake3)
|
|
18
|
-
expect(
|
|
17
|
+
expect(Hash.blake3(message, { as: 'Bytes' })).toEqual(digest)
|
|
19
18
|
})
|
|
20
19
|
})
|
|
21
20
|
|
|
@@ -30,6 +30,8 @@ describe('assert', () => {
|
|
|
30
30
|
|
|
31
31
|
describe('concat', () => {
|
|
32
32
|
test('default', () => {
|
|
33
|
+
expect(Hex.concat()).toMatchInlineSnapshot(`"0x"`)
|
|
34
|
+
expect(Hex.concat('0x1234')).toMatchInlineSnapshot(`"0x1234"`)
|
|
33
35
|
expect(Hex.concat('0x0', '0x1')).toBe('0x01')
|
|
34
36
|
expect(Hex.concat('0x1', '0x69', '0x420')).toBe('0x169420')
|
|
35
37
|
expect(Hex.concat('0x00000001', '0x00000069', '0x00000420')).toBe(
|
|
@@ -2,6 +2,24 @@ import { Bytes, type Hex, Rlp } from 'ox'
|
|
|
2
2
|
import { describe, expectTypeOf, test } from 'vp/test'
|
|
3
3
|
import type { RecursiveArray } from '../internal/types.js'
|
|
4
4
|
|
|
5
|
+
describe('Rlp.encodeTo', () => {
|
|
6
|
+
test('write', () => {
|
|
7
|
+
expectTypeOf(
|
|
8
|
+
Rlp.encodeTo('0x', (value) => {
|
|
9
|
+
expectTypeOf(value).toEqualTypeOf<Bytes.Bytes>()
|
|
10
|
+
}),
|
|
11
|
+
).toEqualTypeOf<void>()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('rejects asynchronous callbacks', () => {
|
|
15
|
+
Rlp.encodeTo(
|
|
16
|
+
'0x',
|
|
17
|
+
// @ts-expect-error RLP write callbacks are synchronous.
|
|
18
|
+
async () => {},
|
|
19
|
+
)
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
5
23
|
describe('Rlp.to', () => {
|
|
6
24
|
test('default', () => {
|
|
7
25
|
expectTypeOf(Rlp.toHex('0x')).toEqualTypeOf<RecursiveArray<Hex.Hex>>()
|
|
@@ -10,6 +10,7 @@ test('exports', () => {
|
|
|
10
10
|
"decodeRlpCursor",
|
|
11
11
|
"readLength",
|
|
12
12
|
"readList",
|
|
13
|
+
"encodeTo",
|
|
13
14
|
"from",
|
|
14
15
|
"fromBytes",
|
|
15
16
|
"fromHex",
|
|
@@ -32,6 +33,114 @@ const generateList = (length: number) => {
|
|
|
32
33
|
return bytes
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
function encodeToBytes(value: Parameters<typeof Rlp.encodeTo>[0]) {
|
|
37
|
+
const chunks: Uint8Array[] = []
|
|
38
|
+
Rlp.encodeTo(value, (chunk) => {
|
|
39
|
+
chunks.push(chunk)
|
|
40
|
+
})
|
|
41
|
+
return Bytes.concat(...chunks)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('Rlp.encodeTo', () => {
|
|
45
|
+
test('matches `from` for nested Hex values', () => {
|
|
46
|
+
const values = [
|
|
47
|
+
'0x',
|
|
48
|
+
'0x00',
|
|
49
|
+
'0x7f',
|
|
50
|
+
'0x80',
|
|
51
|
+
'0x1',
|
|
52
|
+
'0xabc',
|
|
53
|
+
['0x', '0x80', ['0x1', `0x${'ab'.repeat(56)}`], `0x${'cd'.repeat(256)}`],
|
|
54
|
+
] as const
|
|
55
|
+
|
|
56
|
+
for (const value of values)
|
|
57
|
+
expect(encodeToBytes(value)).toEqual(Rlp.from(value, { as: 'Bytes' }))
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('matches `from` for nested byte values', () => {
|
|
61
|
+
const values = [
|
|
62
|
+
new Uint8Array(),
|
|
63
|
+
Uint8Array.of(0),
|
|
64
|
+
Uint8Array.of(0x7f),
|
|
65
|
+
Uint8Array.of(0x80),
|
|
66
|
+
[
|
|
67
|
+
new Uint8Array(),
|
|
68
|
+
Uint8Array.of(0x80),
|
|
69
|
+
[generateBytes(56), generateBytes(256)],
|
|
70
|
+
],
|
|
71
|
+
] as const
|
|
72
|
+
|
|
73
|
+
for (const value of values)
|
|
74
|
+
expect(encodeToBytes(value)).toEqual(Rlp.from(value, { as: 'Bytes' }))
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('does not mutate emitted chunks', () => {
|
|
78
|
+
const chunks: Uint8Array[] = []
|
|
79
|
+
const values: Hex.Hex[] = []
|
|
80
|
+
|
|
81
|
+
Rlp.encodeTo(['0x01', `0x${'ab'.repeat(16_386)}`, '0x80'], (chunk) => {
|
|
82
|
+
chunks.push(chunk)
|
|
83
|
+
values.push(Hex.fromBytes(chunk))
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(chunks.map((chunk) => Hex.fromBytes(chunk))).toEqual(values)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('passes byte leaves without copying', () => {
|
|
90
|
+
const leaf = generateBytes(64)
|
|
91
|
+
let found = false
|
|
92
|
+
|
|
93
|
+
Rlp.encodeTo(leaf, (chunk) => {
|
|
94
|
+
if (chunk === leaf) found = true
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
expect(found).toMatchInlineSnapshot(`true`)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('validates every Hex leaf before writing', () => {
|
|
101
|
+
let writes = 0
|
|
102
|
+
|
|
103
|
+
expect(() =>
|
|
104
|
+
Rlp.encodeTo(['0x01', ['0x02', '0xzz' as Hex.Hex]], () => {
|
|
105
|
+
writes++
|
|
106
|
+
}),
|
|
107
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
108
|
+
`[BaseError: Invalid hex string \`0xzz\`.]`,
|
|
109
|
+
)
|
|
110
|
+
expect(writes).toMatchInlineSnapshot(`0`)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('propagates callback errors after partial output', () => {
|
|
114
|
+
const chunks: Uint8Array[] = []
|
|
115
|
+
|
|
116
|
+
expect(() =>
|
|
117
|
+
Rlp.encodeTo([Uint8Array.of(1), Uint8Array.of(2)], (chunk) => {
|
|
118
|
+
chunks.push(chunk)
|
|
119
|
+
if (chunks.length === 2) throw new Error('write failed')
|
|
120
|
+
}),
|
|
121
|
+
).toThrowErrorMatchingInlineSnapshot(`[Error: write failed]`)
|
|
122
|
+
expect(chunks.map((chunk) => Hex.fromBytes(chunk))).toMatchInlineSnapshot(`
|
|
123
|
+
[
|
|
124
|
+
"0xc2",
|
|
125
|
+
"0x01",
|
|
126
|
+
]
|
|
127
|
+
`)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('snapshots list structure before writing', () => {
|
|
131
|
+
const value: Hex.Hex[] = ['0x01']
|
|
132
|
+
const expected = Rlp.from(value, { as: 'Bytes' })
|
|
133
|
+
const chunks: Uint8Array[] = []
|
|
134
|
+
|
|
135
|
+
Rlp.encodeTo(value, (chunk) => {
|
|
136
|
+
chunks.push(chunk)
|
|
137
|
+
if (chunks.length === 1) value.push('0x02')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
expect(Bytes.concat(...chunks)).toEqual(expected)
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
|
|
35
144
|
describe('Rlp.to', () => {
|
|
36
145
|
test('no bytes', () => {
|
|
37
146
|
const rlpHex = '0x'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Bytes, type Hex, Secp256k1 } from 'ox'
|
|
2
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
3
|
+
|
|
4
|
+
test('fromPrf', () => {
|
|
5
|
+
const prf =
|
|
6
|
+
'0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'
|
|
7
|
+
|
|
8
|
+
expectTypeOf(Secp256k1.fromPrf(prf)).toEqualTypeOf<Hex.Hex>()
|
|
9
|
+
expectTypeOf(Secp256k1.fromPrf(new Uint8Array(32))).toEqualTypeOf<Hex.Hex>()
|
|
10
|
+
expectTypeOf(Secp256k1.fromPrf(prf, { as: 'Hex' })).toEqualTypeOf<Hex.Hex>()
|
|
11
|
+
expectTypeOf(
|
|
12
|
+
Secp256k1.fromPrf(prf, { as: 'Bytes' }),
|
|
13
|
+
).toEqualTypeOf<Bytes.Bytes>()
|
|
14
|
+
})
|