serviceability: add ip_verifier_authority_pk to GlobalState and rotate it via SetAuthority - #4207
Open
elitegreg wants to merge 1 commit into
Open
serviceability: add ip_verifier_authority_pk to GlobalState and rotate it via SetAuthority#4207elitegreg wants to merge 1 commit into
elitegreg wants to merge 1 commit into
Conversation
…e it via SetAuthority The RFC-27 verifier public key is the trust root for IP ownership proof validation. Storing it in onchain global state lets it rotate without a program upgrade. The field is appended to GlobalState, so accounts written before it existed deserialize with Pubkey::default() through the same unwrap_or_default() path feed_authority_pk uses. Pubkey::default() means no verifier is configured, which enforcement must treat as a hard reject rather than as a bypass. SetAuthority gains an optional ip_verifier_authority_pk; BorshDeserializeIncremental keeps transactions built against the old argument layout decoding, with the new field defaulting to None. Authorization is unchanged: GLOBALSTATE_ADMIN or the legacy foundation path. The CLI surfaces the key through global-config authority set/get, and the Rust SDK SetAuthority command builder forwards it. SDK deserializer work for Go, TypeScript, and Python is tracked separately; the regenerated global_state fixture already carries the field for that work to land against.
elitegreg
marked this pull request as ready for review
August 18, 2026 00:56
elitegreg
enabled auto-merge (squash)
August 18, 2026 00:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4196. Part of RFC-27 (rfcs/rfc27-ip-verification.md); tracker #4194.
Summary
GlobalStatecarriesip_verifier_authority_pk, the trust root for RFC-27 IP ownership proof validation, so the verifier key rotates without a program upgrade.SetAuthoritygains an optionalip_verifier_authority_pk; authorization is unchanged (GLOBALSTATE_ADMIN permission or the legacy foundation path).doublezero global-config authority set --ip-verifier-authority <pubkey|me>rotates the key, andauthority getreports it in both the table and JSON views.SetAuthorityCommandforwards the new field.Pubkey::default()means "no verifier configured". Enforcement, which lands with the onchain validation issue, must treat that as a hard reject rather than as "any signature passes".Details
The field is append-only, so accounts written before it existed deserialize with
Pubkey::default()through the sameunwrap_or_default()pathfeed_authority_pkuses. On the instruction side,BorshDeserializeIncrementalkeeps transactions built against the old argument layout decoding, with the new field defaulting toNone.SDK deserializer work for Go, TypeScript, and Python is tracked separately. The
global_statefixture is regenerated here because CI'smake check-fixturesdiffs the goldens against the Rust producer; all three readers ignore trailing bytes and skip meta fields they do not map, so they stay green until that work lands. Running the generator also refreshed itsCargo.lockfrom0.31.0to0.36.0.smartcontract/cli/src/init.rsneeded no change: it sendsInitGlobalStateand carries no authority arguments, and the program's initializer seeds the new field toPubkey::default().Testing Verification
tests/setauthority_test.rs: rotating the verifier key leaves the other authorities, the foundation allowlist, and the feature flags untouched; a second rotation replaces the previous key; and a laterSetAuthoritypassingNonedoes not clear it. It also asserts a freshly initializedGlobalStatereadsPubkey::default(), the state enforcement must reject.Pubkey::default(), and re-serialized with the field set it round-trips with every other field identical. Note that this stored vector is old enough that its bytes end atuser_airdrop_lamports, so appending 32 bytes to it would not have exercised the new field.SetAuthorityArgsunit tests: a pre-field four-option encoding still decodes withip_verifier_authority_pk: None, and the new field round-trips.