Skip to content

fix(test): make the shard-split authorization gate live in the fixture - #618

Open
blacks1ne wants to merge 1 commit into
QuilibriumNetwork:v2.1.0.25from
blacks1ne:blacks1ne/fix-shard-split-authorization-fixture
Open

fix(test): make the shard-split authorization gate live in the fixture#618
blacks1ne wants to merge 1 commit into
QuilibriumNetwork:v2.1.0.25from
blacks1ne:blacks1ne/fix-shard-split-authorization-fixture

Conversation

@blacks1ne

Copy link
Copy Markdown
Contributor

Base: 2b96656e

shard_split_by_global_prover_registers_enumerable_child_and_rejects_non_global fails — a non-global proposer is accepted.

proposer_is_active_global authorizes against committed hypergraph state and skips itself when that slot is empty:

let Some(hg) = self.hypergraph.as_ref() else { return true };

split_fixture never installs it — with_kick_verify_deps is the only setter, and the fixture calls only with_frame_header_deps — so the gate returns true unconditionally.

The skip is deliberate and consistent with validate (if let Some(hg)), so invoke and validate still agree on the same node. What no longer holds is the fixture's node shape: the previous implementation read prover_registry, which the fixture does install, and failed closed when it was absent.

Both halves of the test were inert, not only the failing one. The positive half was passing for the wrong reason, and could not have passed for the right one: seed_global_prover stores the allocation vertex at an arbitrary flat key, while verify_shard_op_signer_is_active_global reads the signer's PublicKey out of the prover tree and looks up allocation_address(pubkey, <empty filter>). The registry path tolerated the flat key because refresh_from_store keys by the tree's ProverAddress field rather than by the storage key.

Fix: install the crdt, and seed the allocation at the derived address — deriving it from the prover's own filter is what makes the non-global case miss the empty-filter lookup and be rejected. The assertion now pins the rejection reason; a bare is_err() passes just as well when the op is refused for an unrelated reason, which is how this dimension went silently inert.

cargo nextest run -p quil-engine --test materialize_harness → 9/9 pass. The four other split_fixture users pass with the gate now live, so it accepts the legitimate global prover rather than merely rejecting everything.

Out of scope: whether the gate should fail open when the hypergraph slot is empty. That is a product decision; this only makes the test exercise the behaviour as written.

`split_fixture` never installs the intrinsic's hypergraph slot —
`with_kick_verify_deps` is its only setter and the fixture calls only
`with_frame_header_deps`. `proposer_is_active_global` returns true
unconditionally when that slot is empty, so the authorization check is a
no-op and the non-global proposer is accepted.

Both halves of the test were inert, not just the failing one. The positive
half was passing for the wrong reason and could not have passed for the right
one: `seed_global_prover` stores the allocation vertex at an arbitrary flat
key, while `verify_shard_op_signer_is_active_global` reads the signer's
PublicKey out of the prover tree and looks up
`allocation_address(pubkey, <empty filter>)`. The registry path this replaced
tolerated the flat key because `refresh_from_store` parses the blob and keys
by the tree's ProverAddress field.

Install the crdt, and seed the allocation at the derived address — taking it
from the prover's own filter is what makes the non-global case miss the
empty-filter lookup and be rejected. Also pin the rejection reason: bare
`is_err()` passes just as well when the op is refused for an unrelated
reason, which is how this dimension went silently inert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant