Skip to content

feat(replay): gate builtins and precompiles on the per-slot feature set - #9

Merged
Mctursh merged 2 commits into
masterfrom
feat/per-slot-feature-gating
Sep 8, 2026
Merged

Mctursh merged 2 commits into
masterfrom
feat/per-slot-feature-gating

Conversation

@Mctursh

@Mctursh Mctursh commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Two places assumed the epoch-808 feature state.

register_builtins registered every solana_builtins::BUILTINS entry regardless of feature state. Three of the nine sit behind enable_feature_id, so a replay could make a program invokable that the cluster didn't have. The feature set was already there: build_feature_set reads it off the on-chain feature accounts and backfill already handed it to the Replayer. register_builtins just never asked.

Not cosmetic at epoch 808. zk_token_proof and loader_v4 have never activated on mainnet and were both being registered. No state was written (all three program accounts already exist on chain, so add_builtin never stubbed) and nothing in the verified 50k range invokes them, so that run's byte-exact result stands.

The precompile callbacks hardcoded |_| true and all_enabled(). secp256r1 sits behind enable_secp256r1_precompile, active from slot 345,600,000, so a range below that would resolve a precompile the cluster didn't have. ReplayBank now carries the feature set, defaulting to all-enabled so fixtures are unchanged, and backfill sets it after seeding. The SVM reaches these callbacks through the bank rather than the Replayer, which is why the Replayer already holding one wasn't enough.

Two places assumed the epoch-808 feature state.

register_builtins registered every solana_builtins::BUILTINS entry
regardless of feature state. Three of the nine sit behind
enable_feature_id, so a replay could make a program invokable that the
cluster didn't have. The feature set was already there: build_feature_set
reads it off the on-chain feature accounts and backfill already handed it
to the Replayer. register_builtins just never asked.

Not cosmetic at epoch 808. zk_token_proof and loader_v4 have never
activated on mainnet and were both being registered. No state was written
(all three program accounts already exist on chain, so add_builtin never
stubbed) and nothing in the verified 50k range invokes them, so that run's
byte-exact result stands.

The precompile callbacks hardcoded |_| true and all_enabled(). secp256r1
sits behind enable_secp256r1_precompile, active from slot 345,600,000, so
a range below that would resolve a precompile the cluster didn't have.
ReplayBank now carries the feature set, defaulting to all-enabled so
fixtures are unchanged, and backfill sets it after seeding. The SVM
reaches these callbacks through the bank rather than the Replayer, which
is why the Replayer already holding one wasn't enough.
@Mctursh
Mctursh merged commit f41a551 into master Sep 8, 2026
2 checks passed
@Mctursh
Mctursh deleted the feat/per-slot-feature-gating branch September 8, 2026 14:39
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