mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
The Stage-1 allocate gate was owner-gated in LOGIC (pinning.IsOwner over the block's threaded proposer) but UNENFORCEABLE by a verifying node: a Lux block carries no verifiable proposer, and resolving one (GetValidatorSet) can be a network call, so the gate could not run inside the pure, local block apply. The chain was therefore unsafe for >1 validator. Make ownership self-attested and cryptographically verifiable: - AllocateTx gains Signer/SignerScheme/SignerPubKey/Sig + Epoch/Nonce/Fingerprint. Sig is an ML-DSA signature (FIPS 204, the SAME scheme the validator NodeID derives from) over the SP 800-185-framed bytes Range|Count|Epoch|Nonce| Fingerprint. The owning proposer signs at BuildBlock with its staking key. - Verify (applyAllocate) is pure + local: recompute owner = pinning.Owner(R, V@epoch); require Signer == owner; re-derive the NodeID from the carried public key (ids.DeriveMLDSA — the NodeID is a SHAKE256-384 commitment to the key) and require it to equal Signer; ML-DSA-verify the signature. Any failure rejects the whole block (fail closed). - Validator-set locality: GetValidatorOutput carries no ML-DSA key, so Verify binds the key via the NodeID commitment instead of a set lookup, and uses the EpochFingerprint carried in the tx (recomputed from the local snapshot) as the DESIGN 6.4 guard — the network call (set resolution) happens in BuildBlock, never in Verify. A non-owner's forged allocate is unverifiable by construction: it cannot sign as the owner (no key), and claiming the owner's NodeID with a foreign key fails the re-derivation. This is the property that replaces raft's serialized writer. Tests (real ML-DSA keys, production NodeID derivation, no bypass): owner-signed accepted + contiguous/monotonic; non-owner-with-VALID-key rejected; forged sig rejected; foreign-key-for-owner-NodeID rejected; tampered tx rejected; epoch and fingerprint mismatch rejected; verifier accepts owner-signed block regardless of relay; state-root/manifest tests stay green. Full schain suite green under -race.