fix(platform)!: register the version 14 system contracts without storage flags - #4956
Conversation
…poll trees insert_contract gives every tree it creates with a contract the contract's storage flags (EpochOwned with the contract owner when the contract can be deleted or is not read only), including the contract, document type, storage and indexes trees under votes/contested_resource/active_polls. Genesis and the contract create/update transitions store contracts with no flags, so these trees only carry flags when a protocol upgrade registers a system contract with a contested index. The moderation charters contract, registered on the first block of protocol version 14, is the first, and its electedCharter trees failed the conformance check in the v13 to v14 strategy tests. The contracts side of the description already admits [EpochOwned, None] for trees created with a contract; the four poll trees now do too. A new structure fixture stores a contested contract through insert_contract and asserts the flags, and grovedb-structure.json is regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 54 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: dashpay/platform/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🌳 GroveDB structure This pull request changes the described GroveDB structure. Open it in the structure viewer: new nodes glow, removed ones stay as ghosts, and the tour walks through each change. Changed (9 nodes)
Compared |
|
🕓 Queued for automated review — 9th in line, estimated start in ~1.8 h (commit fb4981d)
|
A keeps-history contract stored through insert_contract carries the
contract's flags on its `latest` reference and revision items
(add_contract_to_storage writes them with the contract element's flags),
but the description admitted none there: the same miss as the contested
poll trees, latent because no system contract keeps history.
The contract, document and votes descriptions now share one
CONTRACT_FLAGS note, which says who writes the flags: a protocol upgrade
registering a system contract that can be deleted or is not read only.
Genesis and the contract create/update transitions write none. The token
trees insert_contract creates are written without flags and keep their
own descriptions.
The structure fixtures pin both origins: contracts_with_documents and
contested_documents store each contract a second time through
insert_contract and assert the history and poll nodes carry exactly
{None, EpochOwned}. The separate contested fixture and its fresh drive
are folded into contested_documents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…age flags Genesis stores system contracts without storage flags, but transition_to_version_14 registered app-connect and moderation charters through insert_contract, which gives a contract that is not read only (every system contract) and every tree created with it EpochOwned flags owned by the all-zero system owner. Nobody owns that storage and nothing deletes it, so no refund can ever be paid from those flags, and a chain upgraded to 14 stored the two contracts differently from a chain born at 14. The charter contract's contested index made it visible: its electedCharter trees under votes/contested_resource/active_polls failed the structure conformance check in the v13 to v14 strategy tests. Both contracts are now registered through apply_contract with no storage flags, as genesis does. A new test upgrades a chain born at 13 and checks both contracts, and the charter's trees under the active polls, carry no flags and are byte-identical to a chain born at 14. This takes back the description changes of the previous two commits: the poll trees and the history nodes admit no flags again. The contract and document areas keep one shared CONTRACT_FLAGS note, now naming the only contracts that carry flags (the ones upgrades 6, 9 and 13 registered). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Issue being fixed or feature implemented
Since #4898 (moderation charters system data contract, 58bfae8) merged, two drive-abci strategy tests fail the GroveDB structure conformance check on v4.2-dev:
Both panic in
packages/rs-drive/src/structure/conformance.rs:146:CI did not show this at first because nextest stopped at an earlier failure in
moderation-charters-contract.Cause: the upgrade to 14 gave two system contracts storage flags
Genesis stores system contracts without storage flags. The protocol upgrades that add a system contract use
insert_contractinstead. It gives the contract, and every tree created with it, the contract's storage flags (EpochOwned) whenever the contract is not read only. System contracts are loaded with the default config, which is not read only. None of them can be deleted, since no contract can.electedChartertrees undervotes / contested_resource / active_pollsgot flags, where the description expects none.System contracts should not carry flags. Their owner is the all-zero id, which no identity holds, and nothing deletes them, so no refund can ever be paid from those flags. The flags also meant a chain upgraded to 14 stored the two contracts differently from a chain born at 14.
What was done?
transition_to_version_14now registers app-connect and moderation charters throughapply_contractwithstorage_flags: None, the way genesis stores system contracts, instead ofinsert_contract. A comment says why.should_store_the_version_14_system_contracts_as_a_chain_born_at_14_does. It upgrades a chain born at 13 to 14, then compares it with a chain born at 14. The contract elements of both contracts, and of the charter contract under the active polls, carry no flags and are equal on the two chains. Every tree below them is byte-identical (collect_subtree_diffs).CONTRACT_FLAGSnote instead of three differently worded copies. The note names who carries the flags: only the four system contracts upgrades 6, 9 and 13 registered. Genesis, state transitions and later upgrades write none.grovedb-structure.jsonis regenerated; only that note changes.Earlier commits on this branch made the description accept the flags instead. The last commit takes that back and fixes the upgrade, so please squash.
Before / after
Before, on a chain upgraded from 13 to 14, the charter contract's poll trees carry EpochOwned flags, and the two strategy tests fail with the violations above. The new test fails on the old code:
Those bytes are SingleEpochOwned storage flags: the all-zero owner, epoch 1.
After, both contracts are stored without flags and match a chain born at 14 byte for byte. The strategy tests pass against the unchanged description.
In-place changes to shipped generations
perform_events_on_first_block_of_protocol_changev0 is a shipped generation, and the change is inside it. The edit is intransition_to_version_14, which runs only whenprevious_protocol_version < 14 && platform_version.protocol_version >= 14. No released binary runs protocol version 14, so no chain built from a release has executed that function. The edit cannot change consensus at any shipped protocol version.How Has This Been Tested?
cargo test -p drive-abci --lib -- version_14 app_connect_registration test_idempotent_transition: 35 passed. That covers the new test, the existing app-connect and moderation charters registration tests, the othertransition_to_version_14tests, the genesis v1 registration tests and the dispatcher rollback-and-retry test. Withinsert_contractput back, the new test fails as shown above.cargo test -p drive-abci --test strategy_tests -- upgrade_fork_tests: 4 passed (4#[ignore]upstream), includingrun_chain_v13_to_v14_registers_the_app_connect_contractandrun_chain_reopened_drive_at_epoch_boundary_locks_in_the_same_version_as_a_warm_node, against the unchanged description.cargo test -p drive --lib structure::tests: 11 passed, withgrovedb-structure.jsonregenerated.Breaking Changes
Consensus at protocol version 14, which is unreleased. The block that activates 14 now stores app-connect and moderation charters without flags. Its app hash therefore differs from what earlier v4.2-dev builds compute for the same upgrade. A devnet that already upgraded from 13 to 14 on such a build cannot be replayed with this one. Chains born at 14 are unaffected, since genesis already stored both contracts without flags.
Checklist:
structure.rs, regeneratedgrovedb-structure.json, and checked the structure viewer link posted on this pull requestFor repository code-owners and collaborators only
🤖 Generated with Claude Code
PR Hygiene ·
fb4981d/skip-botsproceeds without the ones not yet reported/self-reviewedonce the bots are doneWhen every box is checked the
PR Hygienecheck passes and this can merge.