Skip to content

fix(genesis): require a 32-byte validator public key in the schema - #401

Open
JspIIV wants to merge 1 commit into
circlefin:mainfrom
JspIIV:fix/genesis-public-key-length
Open

JspIIV wants to merge 1 commit into
circlefin:mainfrom
JspIIV:fix/genesis-public-key-length

Conversation

@JspIIV

@JspIIV JspIIV commented Sep 13, 2026

Copy link
Copy Markdown

Closes: #413

Summary

Same shape as #359, one field over: the genesis schema for ValidatorManager accepts a validator publicKey of any even hex length, while the chain only accepts 32 bytes.

publicKey: schemaHex,   // any 0x + even number of hex digits

ValidatorRegistry.registerValidator enforces the real rule:

require(publicKey.length == ED25519_PUBLIC_KEY_LENGTH, InvalidPublicKeyFormat());

and the alloc builder knows it too — but only as a throw new Error('Public key must be 32 bytes') inside buildValidatorManagerGenesisAllocs, after schemaGenesisConfig.parse has already accepted the config (genesis.ts:161 parses, :188 builds). So a 31-byte key passes validation, passes the uniqueness check, and then fails later with a message that carries no path to the offending entry.

Change

  • publicKey: schemaBytes32 — the schema already exists in types.ts and is exactly {32} bytes.
  • Drop the now-unreachable runtime throw; the builder re-parses the schema on entry, so nothing gets past it.

The error moves to where the other genesis invariants live, with a path (validators.0.publicKey) instead of a bare string.

Tests

tests/unit/validator-manager-genesis-validation.test.ts: a 31-byte and a 33-byte key are rejected at the schema with the path set, a 32-byte key is accepted. Both rejections fail on main (the schema accepts them; only the builder would object). Run with mocha -r ts-node/register directly, since forge is not available here and the hardhat-foundry plugin refuses to start without it; make genesis was not run for the same reason. Every key in assets/*/genesis.config.ts is already 64 hex characters, so no shipped config changes behaviour.

Does not overlap #374, which normalizes hex casing and leaves the field type alone.

Related: #346, #359

The chain only accepts 32-byte keys -- ValidatorRegistry.registerValidator
reverts with InvalidPublicKeyFormat on anything else -- but the genesis
schema typed publicKey as schemaHex, which is any even-length hex. The
32-byte rule lived only as a throw inside buildValidatorManagerGenesisAllocs,
so a 31-byte key passed schemaGenesisConfig.parse and the uniqueness check,
and failed later with an Error that names no path.

Use schemaBytes32, which already exists and is exactly 32 bytes, and drop
the runtime throw it makes unreachable: the builder re-parses the schema on
entry, so nothing gets past it. The rejection now carries a path,
validators.<i>.publicKey, like the other genesis invariants.

Tests: a 31-byte and a 33-byte key are rejected at the schema with the path
set, a 32-byte key is accepted. Both rejections fail on main.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

genesis: ValidatorManager schema accepts a validator public key of any length; the chain requires 32 bytes

1 participant