force deploys to latest Clarity; reserved-name defines for legacy trait implementations - #7404
Draft
francesco-stacks wants to merge 4 commits into
Draft
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR proposes a consensus-rule change for Epoch 4.0 that forces new smart-contract deploys to use the epoch-default (latest) Clarity version, while adding Clarity 6 VM support for defining certain previously-reserved native names only when required to implement legacy trait methods (keeping older traits interoperable under “force-latest”).
Changes:
- Enforce (in
process_transaction_precheck) that from Epoch 4.0, version-pinned contract deploys cannot pin a Clarity version older than the epoch default. - Add Clarity 6 initialization-time validation that allows public/read-only function defines under “shadowable reserved” names only when they match methods from legacy (pre-reservation) implemented traits; and prevent new traits from declaring currently-reserved method names.
- Add/adjust extensive unit tests across chainstate + VM analysis/runtime suites, plus changelog fragments for both behaviors.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| stackslib/src/chainstate/tests/runtime_analysis_tests.rs | Updates runtime error variant coverage mapping to include the new Clarity 6 reserved-name behavior test. |
| stackslib/src/chainstate/tests/consensus.rs | Updates Epoch 4.0 deployable Clarity version list to only include the latest version. |
| stackslib/src/chainstate/tests/consensus_unit_tests.rs | Adds consensus-level tests for Epoch 4.0 deploy version enforcement and Clarity 6 legacy-trait reserved-name interop. |
| stackslib/src/chainstate/stacks/db/transactions.rs | Factors deploy Clarity version validation into a helper and enforces “force-latest” from Epoch 4.0; adds precheck tests. |
| clarity/src/vm/tests/variables.rs | Makes initialization/runtime expectation checking stricter and clarifies test contract naming. |
| clarity/src/vm/tests/contracts.rs | Adds an extensive Clarity 6 test suite covering shadowable reserved names, trait matching, determinism, and edge cases. |
| clarity/src/vm/mod.rs | Introduces is_shadowable_reserved and initialization-time validate_shadowable_reserved_definitions with deterministic trait-loading and costing. |
| clarity/src/vm/functions/define.rs | Allows Clarity 6 public/read-only defines for shadowable reserved names (deferred validation), and rejects reserved method names in define-trait from Clarity 6. |
| clarity/src/vm/contexts.rs | Adds is_name_defined_by_contract and refactors is_name_used to support the reserved-name shadowing rule cleanly. |
| clarity/src/vm/analysis/tests/mod.rs | Adds analysis tests ensuring bare references keep resolving to natives even when shadowed functions exist. |
| changelog.d/epoch-4-force-latest-clarity.changed | Changelog entry for Epoch 4.0 deploy version enforcement. |
| changelog.d/clarity6-reserved-name-trait-impls.added | Changelog entry for Clarity 6 reserved-name defines for legacy trait implementations + new trait restrictions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
hstove-stacks
left a comment
Contributor
There was a problem hiding this comment.
Overall LGTM, but you'll have to update snapshots
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.
Description
NOTE: Not intended to be shipped with Clarity 6 / Epoch 4.0 itself. (but it would have been nice :P ) Changing which Clarity versions are deployable is a consensus-rules change that will likely require its own SIP. The PR is for early feedback and review.
From Epoch 4.0, new contract deploys are forced to the latest Clarity version. Two changes make thi safe and enforce it:
1. Deploy version enforcement (consensus rule)
process_transaction_prechecknow rejects a versioned smart-contract deploy that pins a Clarity version older than the epoch default, from Epoch 4.0 on (pinning a newer version was already rejected). Unversioned deploys resolve to the epoch default as before, which at Epoch 4.0 is Clarity 6. Already-deployed contracts keep running at their pinned version. The check runs in the shared precheck path, so it applies identically to mempool admission and block validation: a block containing such a deploy is invalid.2. Clarity 6: reserved-name defines for legacy trait implementations
Each Clarity version reserves names that used to be free (
slice?since Clarity 2,stacks-block-heightsince Clarity 3,current-contractsince Clarity 4, …). Traits deployed before those reservations may declare methods under such names - without this change, those traits would be unimplementable at the latest version, and force-latest would break interoperability with older contracts that define such methods.From Clarity 6, a
publicorread-onlyfunction may be defined under such a name, but only to implement a matching method of an implemented (impl-trait) trait deployed while the name was still free. Everything else is unchanged:contract-call?, static or dynamic, and trait dispatch).define-traitnow rejects currently-reserved method names, so no new trait can ever make a reserved name implementable - only traits that predate the reservation can.Validation mechanics (consensus-sensitive details)
The check runs after contract initialization (
validate_shadowable_reserved_definitions), sodefine/impl-traitordering doesn't matter, and it is a no-op unless the contract actually defines a reserved name. When it runs, implemented traits are consulted in sorted order (deterministic across nodes), each trait-defining contract load is priced like any contract load (LoadContractcost + memory, mirroringinner_execute_contract), and loading stops as soon as every name is matched. Analysis is intentionally unchanged: like reserved names generally, this is enforced at initialization only, and trait compliance (signature match) is still enforced by the existing analysis pass.Applicable issues
Additional info (benefits, drawbacks, caveats)
Checklist
docs/property-testing.md)changelog.d/README.md)rpc/openapi.yamlfor RPC endpoints,event-dispatcher.mdfor new events)clarity-benchmarkingrepo