ox
Version:
Ethereum Standard Library
577 lines (529 loc) • 18 kB
text/typescript
import { Bytes, PublicKey } from 'ox'
import { describe, expect, test } from 'vp/test'
test('exports', () => {
expect(Object.keys(PublicKey)).toMatchInlineSnapshot(`
[
"assert",
"compress",
"from",
"fromBytes",
"fromHex",
"toBytes",
"toHex",
"validate",
"InvalidError",
"InvalidPrefixError",
"InvalidCompressedPrefixError",
"InvalidUncompressedPrefixError",
"InvalidSerializedSizeError",
]
`)
})
describe('PublicKey.assert', () => {
test('compressed', () => {
PublicKey.assert({
prefix: 2,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
})
PublicKey.assert({
prefix: 3,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
})
expect(() =>
PublicKey.assert({
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(
`
[PublicKey.InvalidPrefixError: Prefix "undefined" is invalid.
Details: Prefix must be 2 or 3 for compressed public keys.]
`,
)
expect(() =>
PublicKey.assert({
prefix: 5,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 2 or 3 for compressed public keys.]
`)
})
test('uncompressed', () => {
PublicKey.assert({
prefix: 4,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
})
expect(() =>
PublicKey.assert({
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "undefined" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
`)
expect(() =>
PublicKey.assert({
prefix: 3,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "3" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
`)
expect(() =>
PublicKey.assert({
prefix: 5,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
`)
})
test('unknown', () => {
expect(() =>
PublicKey.assert({
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
}),
).toThrowErrorMatchingInlineSnapshot(
`
[PublicKey.InvalidError: Value \`{"y":"0x0000000000000000000000000000000000000000000000000000000000000001"}\` is not a valid public key.
Public key must contain:
- an \`x\` and \`prefix\` value (compressed)
- an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
`,
)
})
test('behavior: rejects missing x/y when compressed: false is set', () => {
expect(() => PublicKey.assert({ prefix: 4 }, { compressed: false }))
.toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidError: Value \`{"prefix":4}\` is not a valid public key.
Public key must contain:
- an \`x\` and \`prefix\` value (compressed)
- an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
`)
expect(() =>
PublicKey.assert(
{
prefix: 4,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
},
{ compressed: false },
),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidError: Value \`{"prefix":4,"x":"0x0000000000000000000000000000000000000000000000000000000000000001"}\` is not a valid public key.
Public key must contain:
- an \`x\` and \`prefix\` value (compressed)
- an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
`)
})
test('behavior: rejects missing x or extra y when compressed: true is set', () => {
expect(() => PublicKey.assert({ prefix: 2 }, { compressed: true }))
.toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidError: Value \`{"prefix":2}\` is not a valid public key.
Public key must contain:
- an \`x\` and \`prefix\` value (compressed)
- an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
`)
expect(() =>
PublicKey.assert(
{
prefix: 2,
x: '0x0000000000000000000000000000000000000000000000000000000000000001',
y: '0x0000000000000000000000000000000000000000000000000000000000000001',
},
{ compressed: true },
),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidError: Value \`{"prefix":2,"x":"0x0000000000000000000000000000000000000000000000000000000000000001","y":"0x0000000000000000000000000000000000000000000000000000000000000001"}\` is not a valid public key.
Public key must contain:
- an \`x\` and \`prefix\` value (compressed)
- an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
`)
})
})
describe('PublicKey.compress', () => {
test('default', () => {
{
const publicKey = PublicKey.compress({
prefix: 4,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 3,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
}
{
const publicKey = PublicKey.compress({
prefix: 4,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa6',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 2,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
}
})
})
describe('PublicKey.fromHex', () => {
test('default', () => {
const serialized =
'0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5'
const publicKey = PublicKey.fromHex(serialized)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('behavior: prefix', () => {
const serialized =
'0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5'
const publicKey = PublicKey.fromHex(serialized)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('behavior: compressed', () => {
const serialized =
'0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75'
const publicKey = PublicKey.fromHex(serialized)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 3,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
})
test('error: invalid size', () => {
expect(() =>
PublicKey.fromHex(
'0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2a',
),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidSerializedSizeError: Value \`0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2a\` is an invalid public key size.
Expected: 33 bytes (compressed + prefix), 64 bytes (uncompressed) or 65 bytes (uncompressed + prefix).
Received 63 bytes.]
`)
})
test('error: invalid uncompressed prefix', () => {
// 65-byte serialized with prefix 5 (invalid for uncompressed).
expect(() =>
PublicKey.fromHex(
'0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
`)
})
test('error: invalid compressed prefix', () => {
// 33-byte serialized with prefix 5 (invalid for compressed).
expect(() =>
PublicKey.fromHex(
'0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
),
).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 2 or 3 for compressed public keys.]
`)
})
})
describe('PublicKey.fromBytes', () => {
test('default', () => {
const serialized = Bytes.fromHex(
'0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
const publicKey = PublicKey.fromBytes(serialized)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('error: invalid prefix', () => {
const serialized = Bytes.fromHex(
'0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
expect(() => PublicKey.fromBytes(serialized))
.toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
`)
})
})
describe('PublicKey.from', () => {
test('uncompressed', () => {
const publicKey = PublicKey.from({
prefix: 4,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('uncompressed, serialized hex', () => {
const publicKey = PublicKey.from(
'0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('uncompressed, serialized bytes', () => {
const publicKey = PublicKey.from(
Bytes.fromHex(
'0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
),
)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('uncompressed, no prefix', () => {
const publicKey = PublicKey.from({
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('uncompressed, no prefix, serialized hex', () => {
const publicKey = PublicKey.from(
'0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 4,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
"y": "0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
}
`)
})
test('compressed', () => {
const publicKey = PublicKey.from({
prefix: 3,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 3,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
})
test('compressed', () => {
const publicKey = PublicKey.from({
prefix: 2,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
})
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 2,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
})
test('compressed, serialized hex', () => {
const publicKey = PublicKey.from(
'0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 3,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
})
test('compressed, serialized bytes', () => {
const publicKey = PublicKey.from(
Bytes.fromHex(
'0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
),
)
expect(publicKey).toMatchInlineSnapshot(`
{
"prefix": 3,
"x": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75",
}
`)
})
})
describe('PublicKey.toHex', () => {
test('default', () => {
const publicKey = PublicKey.from({
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
const serialized = PublicKey.toHex(publicKey)
expect(serialized).toMatchInlineSnapshot(
`"0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"`,
)
})
test('behavior: prefix', () => {
const publicKey = PublicKey.from({
prefix: 4,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
const serialized = PublicKey.toHex(publicKey)
expect(serialized).toMatchInlineSnapshot(
`"0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"`,
)
})
test('behavior: compressed', () => {
const publicKey = PublicKey.from({
prefix: 3,
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
})
const serialized = PublicKey.toHex(publicKey)
expect(serialized).toMatchInlineSnapshot(
`"0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75"`,
)
})
test('option: includePrefix', () => {
const publicKey = PublicKey.from({
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
const serialized = PublicKey.toHex(publicKey, { includePrefix: false })
expect(serialized).toMatchInlineSnapshot(
`"0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"`,
)
})
})
describe('PublicKey.toBytes', () => {
test('default', () => {
const publicKey = PublicKey.from({
x: '0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
y: '0x3547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
})
const serialized = PublicKey.toBytes(publicKey)
expect(serialized).toMatchInlineSnapshot(
`
Uint8Array [
4,
131,
24,
83,
91,
84,
16,
93,
74,
122,
174,
96,
192,
143,
196,
95,
150,
135,
24,
27,
79,
223,
198,
37,
189,
26,
117,
63,
167,
57,
127,
237,
117,
53,
71,
241,
28,
168,
105,
102,
70,
242,
243,
172,
176,
142,
49,
1,
106,
250,
194,
62,
99,
12,
93,
17,
245,
159,
97,
254,
245,
123,
13,
42,
165,
]
`,
)
})
})
describe('PublicKey.validate', () => {
test('default', () => {
expect(
PublicKey.validate({
prefix: 4,
x: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
y: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
}),
).toBe(true)
expect(
PublicKey.validate({
prefix: 4,
y: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
}),
).toBe(false)
})
})