You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(val): re-align VAL-2 checked insertion with merged leanSpec#1185
Upstream leanEthereum/leanSpec#1185 (closes #1184) now rejects a
manifest whose attestation and proposal public keys coincide, at load
time and without touching secret bytes. The model's addChecked
previously compared PRF seeds as a placeholder for the invited fix;
re-align it with the merged shape:
- addChecked now compares public keys, with the Arklib-side derivation
entering as the publicKeyOf parameter (the repo's crypto-as-parameter
pattern).
- addChecked_wellFormed holds for every derivation: distinct public
keys imply distinct secret keys by congruence alone.
- addChecked_seed_distinct keeps the OTS-reuse core of #1184: for
seed-fingerprinting derivations an accepted entry's keys have
distinct master seeds.
- Registry.lean and catalog docstrings drop the stale 'upstream does
not enforce' caveat: WellFormed is established by construction since
#1185.
@@ -388,17 +388,18 @@ The propositions here guarantee **duty correctness and slashing prevention**: pr
388
388
389
389
- [x] **VAL-2: Proposal key and attestation key are distinct**
390
390
- Source: `proposalKey` / `attestationKey` (ValidatorService; realized as the `attestation_secret_key` / `proposal_secret_key` fields of `ValidatorEntry`, `src/lean_spec/node/validator/registry.py`)
391
-
- Note: Each validator manages two separate signing keys, one for block proposal and one for attestations — documented upstream as "without OTS conflict", but **not enforced**: `ValidatorRegistry.add` assigns without validation and `from_yaml` compares nothing, so a same-key manifest loads silently and one slot's proposal + attestation signatures would consume overlapping XMSS one-time-signature state. Found by attempting this proposition; reported upstream as leanEthereum/leanSpec#1184 (the "invariant maintained only by convention" class of #1176). The theorem is therefore proved relative to `ValidatorRegistry.WellFormed`.
392
-
- Proved at: `LeanSpec/Validator/Registry.lean` (`ValidatorRegistry.dual_key_distinct`, relative to `WellFormed`; `WellFormed.add` shows the suggested fix — validate at insertion — preserves the invariant)
391
+
- Note: Each validator manages two separate signing keys, one for block proposal and one for attestations — documented upstream as "without OTS conflict". Originally **not enforced** (`ValidatorRegistry.add` assigned without validation, `from_yaml` compared nothing, so a same-key manifest loaded silently and one slot's proposal + attestation signatures would consume overlapping XMSS one-time-signature state); found by attempting this proposition and reported upstream as leanEthereum/leanSpec#1184 (the "invariant maintained only by convention" class of #1176). **Enforced since leanEthereum/leanSpec#1185**: the loader rejects a manifest whose two public keys coincide, before touching secret bytes, so every loaded registry satisfies `WellFormed` by construction.
392
+
- Proved at: `LeanSpec/Validator/Registry.lean` (`ValidatorRegistry.dual_key_distinct`, relative to `WellFormed`; `WellFormed.add` shows unchecked insertion preserves the invariant; `addChecked` mirrors the merged #1185 public-key check with the derivation as a parameter — `addChecked_wellFormed` for every derivation, `addChecked_seed_distinct` for seed-fingerprinting ones)
0 commit comments