Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions scripts/genesis/ValidatorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
enforceOperatorsNotProxyAdmin,
schemaAddress,
schemaBigInt,
schemaHex,
schemaBytes32,
slotForAddressMap,
slotForBytes32Map,
slotIndex,
Expand Down Expand Up @@ -54,7 +54,11 @@ export const schemaValidatorManager = z
*/
validators: z.array(
z.object({
publicKey: schemaHex,
/**
* Ed25519 public key, exactly 32 bytes. ValidatorRegistry.registerValidator
* rejects any other length with InvalidPublicKeyFormat, so the schema does too.
*/
publicKey: schemaBytes32,
votingPower: schemaBigInt.max(UINT64_MAX),
/**
* Controllers authorized to manage this validator. Each controller is
Expand Down Expand Up @@ -217,12 +221,8 @@ export const buildValidatorManagerGenesisAllocs = async (ctx: BuilderContext, co
const idSetArraySlot = fromHex(keccak256(slotIndex(REGISTRY_STORAGE_LOCATION + 1n)), 'bigint') + BigInt(index)
const idSetMapSlotHex = slotForBytes32Map(REGISTRY_STORAGE_LOCATION + 2n, registrationId)
const validatorSlot = fromHex(slotForBytes32Map(REGISTRY_STORAGE_LOCATION + 0n, registrationId), 'bigint')
const publicKeyLength = BigInt(fromHex(validator.publicKey, 'bytes').length)

if (publicKeyLength !== 32n) {
// Only support 32 bytes public key now.
throw new Error(`Public key must be 32 bytes`)
}
// schemaBytes32 already guarantees the key is exactly 32 bytes.
const publicKeyLength = 32n

return [
// _validatorsByRegistrationId, mapping(uint256 => Validator = (enum, bytes, uint64))
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/validator-manager-genesis-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,34 @@ describe('ValidatorManager genesis validator-set validation', () => {
expect(result.success).to.be.true
})
})

describe('ValidatorManager genesis public-key validation', () => {
// ValidatorRegistry.registerValidator requires exactly 32 bytes; the schema
// has to say so too, or a bad key only fails later inside the alloc builder.
const PUBLIC_KEY_31 = `0x${'11'.repeat(31)}`
const PUBLIC_KEY_33 = `0x${'11'.repeat(33)}`

it('rejects a 31-byte public key at the schema', () => {
const result = schemaValidatorManager.safeParse(configWithValidators([validator(PUBLIC_KEY_31, CONTROLLER_A, 20n)]))

expect(result.success).to.be.false
if (!result.success) {
expect(result.error.issues.some((issue) => issue.path.join('.') === 'validators.0.publicKey')).to.be.true
}
})

it('rejects a 33-byte public key at the schema', () => {
const result = schemaValidatorManager.safeParse(configWithValidators([validator(PUBLIC_KEY_33, CONTROLLER_A, 20n)]))

expect(result.success).to.be.false
if (!result.success) {
expect(result.error.issues.some((issue) => issue.path.join('.') === 'validators.0.publicKey')).to.be.true
}
})

it('accepts a 32-byte public key', () => {
const result = schemaValidatorManager.safeParse(configWithValidators([validator(PUBLIC_KEY_A, CONTROLLER_A, 20n)]))

expect(result.success).to.be.true
})
})
Loading