From ee4e61f41a87e3c2f9f635e11961baa18b6297cb Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 07:25:16 +0700 Subject: [PATCH 1/3] fix(drive): structure description admits contract flags on contested 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 --- packages/rs-drive/grovedb-structure.json | 20 +++++++ .../rs-drive/src/drive/votes/structure.rs | 8 +++ packages/rs-drive/src/structure/tests.rs | 52 ++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index 8a074d22cd9..37dc60fbf6a 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -4062,6 +4062,11 @@ "kinds": [ "Tree" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4081,6 +4086,11 @@ "kinds": [ "Tree" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4097,6 +4107,11 @@ "kinds": [ "Tree" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4142,6 +4157,11 @@ "kinds": [ "Tree" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", diff --git a/packages/rs-drive/src/drive/votes/structure.rs b/packages/rs-drive/src/drive/votes/structure.rs index 42ef6631b51..51ad86f3b12 100644 --- a/packages/rs-drive/src/drive/votes/structure.rs +++ b/packages/rs-drive/src/drive/votes/structure.rs @@ -13,6 +13,10 @@ const CONTENDER_FLAGS: &str = "The owner is the contender whose document created the level, who is \ refunded when the poll is cleaned up. Written without storage flags, it carries none."; const POLL_FLAGS: &str = "The owner is the identity whose contested document started the poll."; +const CONTRACT_FLAGS: &str = + "The contract's flags, written with it. The owner is the contract owner, and the \ + epoch the one a protocol upgrade registered the system contract in. System \ + contracts created at genesis, and contracts a state transition creates, carry none."; const OWNED: [FlagsKind; 2] = [FlagsKind::EpochOwned, FlagsKind::None]; const CONTESTED_DOCUMENT: &str = "votes.contested_resource.active_polls.contract.document_type.storage.document"; @@ -190,6 +194,7 @@ fn active_polls() -> StructureNode { .child( StructureNode::identifier("contract", "contract_id", "The data contract id") .kind(ElementKind::Tree) + .flags(&OWNED, CONTRACT_FLAGS) .describe( "Created with a contract that has a contested \ index.", @@ -203,6 +208,7 @@ fn active_polls() -> StructureNode { "The document type name", ) .kind(ElementKind::Tree) + .flags(&OWNED, CONTRACT_FLAGS) .describe("A document type with a contested index.") .children(vec![ StructureNode::fixed( @@ -212,6 +218,7 @@ fn active_polls() -> StructureNode { "CONTESTED_DOCUMENT_STORAGE_TREE_KEY", ) .kind(ElementKind::Tree) + .flags(&OWNED, CONTRACT_FLAGS) .describe( "The documents competing, held here until a poll \ awards one of them.", @@ -230,6 +237,7 @@ fn active_polls() -> StructureNode { "CONTESTED_DOCUMENT_INDEXES_TREE_KEY", ) .kind(ElementKind::Tree) + .flags(&OWNED, CONTRACT_FLAGS) .describe( "The contested index. Only the values make levels \ here; property names are left out on purpose.", diff --git a/packages/rs-drive/src/structure/tests.rs b/packages/rs-drive/src/structure/tests.rs index 8babc356afe..4feed5aac13 100644 --- a/packages/rs-drive/src/structure/tests.rs +++ b/packages/rs-drive/src/structure/tests.rs @@ -349,6 +349,7 @@ mod fixtures { use dpp::platform_value::BinaryData; use dpp::platform_value::Value; use dpp::tests::fixtures::get_dashpay_contract_fixture; + use dpp::tests::json_document::json_document_to_contract_with_ids; use dpp::tokens::status::TokenStatus; use dpp::tokens::token_event::TokenEvent; use dpp::tokens::token_pricing_schedule::TokenPricingSchedule; @@ -516,8 +517,13 @@ mod fixtures { } /// Checks the state against the description, and records the shape of - /// every layer below a template that is fuller here than seen so far - fn conformance_of(drive: &Drive, fixture: &str, run: &mut FixtureRun) { + /// every layer below a template that is fuller here than seen so far. + /// Returns the kinds of flags found on the elements of each node. + fn conformance_of( + drive: &Drive, + fixture: &str, + run: &mut FixtureRun, + ) -> BTreeMap> { let platform_version = PlatformVersion::latest(); let structure = drive_structure(); let report = check_conformance(drive, &structure, None, platform_version) @@ -555,6 +561,7 @@ mod fixtures { ); } run.visited.extend(report.visited); + report.flags } fn identities(run: &mut FixtureRun) { @@ -1194,6 +1201,46 @@ mod fixtures { conformance_of(&drive, "contested_documents", run); } + /// A contract with a contested index stored with the contract's flags, the way + /// `insert_contract` stores the system contracts a protocol upgrade registers (the + /// moderation charters contract at 14). The trees created with it below the active + /// polls carry those flags; genesis and state transitions write none. + fn contested_index_contract_with_flags(run: &mut FixtureRun) { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", + None, + None, + false, + platform_version, + ) + .expect("expected the contract"); + drive + .insert_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert the contract"); + + let flags = conformance_of(&drive, "contested_index_contract_with_flags", run); + for node in [ + "votes.contested_resource.active_polls.contract", + "votes.contested_resource.active_polls.contract.document_type", + "votes.contested_resource.active_polls.contract.document_type.storage", + "votes.contested_resource.active_polls.contract.document_type.indexes", + ] { + assert_eq!( + flags.get(node), + Some(&BTreeSet::from([FlagsKind::EpochOwned])), + "expected `{node}` to carry the contract's flags", + ); + } + } + fn apply_operations(drive: &Drive, operations: Vec) { drive .apply_batch_low_level_drive_operations( @@ -1513,6 +1560,7 @@ mod fixtures { token_distributions(&mut run); contract_groups_and_bound_keys(&mut run); spent_nullifiers(&mut run); + contested_index_contract_with_flags(&mut run); run } From 4d5564a64a8e8e66e082f72d0f91c005e1409051 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 07:45:40 +0700 Subject: [PATCH 2/3] fix(drive): contract history nodes admit contract flags, one shared note 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 --- packages/rs-drive/grovedb-structure.json | 36 ++++++---- .../rs-drive/src/drive/contract/structure.rs | 11 ++- .../rs-drive/src/drive/document/structure.rs | 4 +- .../rs-drive/src/drive/votes/structure.rs | 5 +- packages/rs-drive/src/structure/tests.rs | 67 ++++++++++++------- 5 files changed, 75 insertions(+), 48 deletions(-) diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index 37dc60fbf6a..84b09dcb7b6 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -2537,7 +2537,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2560,7 +2560,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "value": "serialized DataContract", "since": 1, "presence": "always", @@ -2578,6 +2578,11 @@ "kinds": [ "Reference" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "reference": "contracts.contract.contract.revision", "since": 1, "presence": "always", @@ -2600,6 +2605,11 @@ "kinds": [ "Item" ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "value": "serialized DataContract", "since": 1, "presence": "always", @@ -2624,7 +2634,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2649,7 +2659,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/document/paths.rs", @@ -2678,7 +2688,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "lazy", "source": "packages/rs-drive/src/drive/document/primary_key_tree_type.rs", @@ -2947,7 +2957,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 14, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2969,7 +2979,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 14, "presence": "lazy", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2993,7 +3003,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 14, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -3062,7 +3072,7 @@ "EpochOwned", "None" ], - "flags_note": "The owner is the contract owner, and the epoch the one the contract was created in. System contracts created at genesis carry no flags.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "value": "u32 big endian", "since": 14, "presence": "always", @@ -4066,7 +4076,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4090,7 +4100,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4111,7 +4121,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4161,7 +4171,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags, written with it. The owner is the contract owner, and the epoch the one a protocol upgrade registered the system contract in. System contracts created at genesis, and contracts a state transition creates, carry none.", + "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", diff --git a/packages/rs-drive/src/drive/contract/structure.rs b/packages/rs-drive/src/drive/contract/structure.rs index c44b368aba9..b2457b791ed 100644 --- a/packages/rs-drive/src/drive/contract/structure.rs +++ b/packages/rs-drive/src/drive/contract/structure.rs @@ -8,9 +8,12 @@ use crate::drive::RootTree; use crate::structure::{ElementKind, FlagsKind, KeyEncoding, KeyMatcher, StructureNode}; const SOURCE: &str = "packages/rs-drive/src/drive/contract/paths.rs"; -const CONTRACT_FLAGS: &str = - "The owner is the contract owner, and the epoch the one the contract was \ - created in. System contracts created at genesis carry no flags."; +/// The flags of the elements written with a contract, shared by every area that describes one +pub(crate) const CONTRACT_FLAGS: &str = + "The contract's flags. A protocol upgrade registering a system contract that can be \ + deleted or is not read only writes them: the owner is the contract owner, and the \ + epoch the one the contract was registered in. Genesis, and the state transitions \ + that create and update contracts, write none."; const REMOVAL_FLAGS: &str = "The owner is the moderator who deleted the document. They pay for the record, \ which nothing deletes or replaces."; @@ -56,6 +59,7 @@ pub(crate) fn structure() -> StructureNode { .children(vec![ StructureNode::fixed("latest", &[0], "Latest", "") .kind(ElementKind::Reference) + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) .reference("contracts.contract.contract.revision") .describe("A sibling reference to the newest revision."), StructureNode::dynamic( @@ -67,6 +71,7 @@ pub(crate) fn structure() -> StructureNode { u64 big endian with the sign bit flipped", ) .kind(ElementKind::Item) + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) .value("serialized DataContract") .describe("The contract as it was at that time."), ]), diff --git a/packages/rs-drive/src/drive/document/structure.rs b/packages/rs-drive/src/drive/document/structure.rs index 4aa76a28a47..75dd4d23a8a 100644 --- a/packages/rs-drive/src/drive/document/structure.rs +++ b/packages/rs-drive/src/drive/document/structure.rs @@ -1,9 +1,7 @@ +use crate::drive::contract::structure::CONTRACT_FLAGS; use crate::structure::{ElementKind, FlagsKind, KeyEncoding, KeyMatcher, StructureNode}; const SOURCE: &str = "packages/rs-drive/src/drive/document/paths.rs"; -const CONTRACT_FLAGS: &str = - "The owner is the contract owner. System contracts created at genesis carry \ - no flags."; const DOCUMENT_FLAGS: &str = "The owner is the owner of the document, who is refunded when it is deleted. \ Documents the system writes carry no flags."; diff --git a/packages/rs-drive/src/drive/votes/structure.rs b/packages/rs-drive/src/drive/votes/structure.rs index 51ad86f3b12..75aaf413e1c 100644 --- a/packages/rs-drive/src/drive/votes/structure.rs +++ b/packages/rs-drive/src/drive/votes/structure.rs @@ -1,3 +1,4 @@ +use crate::drive::contract::structure::CONTRACT_FLAGS; use crate::drive::votes::paths::{ ACTIVE_POLLS_TREE_KEY, CONTESTED_DOCUMENT_INDEXES_TREE_KEY, CONTESTED_DOCUMENT_STORAGE_TREE_KEY, CONTESTED_RESOURCE_TREE_KEY, END_DATE_QUERIES_TREE_KEY, @@ -13,10 +14,6 @@ const CONTENDER_FLAGS: &str = "The owner is the contender whose document created the level, who is \ refunded when the poll is cleaned up. Written without storage flags, it carries none."; const POLL_FLAGS: &str = "The owner is the identity whose contested document started the poll."; -const CONTRACT_FLAGS: &str = - "The contract's flags, written with it. The owner is the contract owner, and the \ - epoch the one a protocol upgrade registered the system contract in. System \ - contracts created at genesis, and contracts a state transition creates, carry none."; const OWNED: [FlagsKind; 2] = [FlagsKind::EpochOwned, FlagsKind::None]; const CONTESTED_DOCUMENT: &str = "votes.contested_resource.active_polls.contract.document_type.storage.document"; diff --git a/packages/rs-drive/src/structure/tests.rs b/packages/rs-drive/src/structure/tests.rs index 4feed5aac13..a0cc8ccb824 100644 --- a/packages/rs-drive/src/structure/tests.rs +++ b/packages/rs-drive/src/structure/tests.rs @@ -349,7 +349,6 @@ mod fixtures { use dpp::platform_value::BinaryData; use dpp::platform_value::Value; use dpp::tests::fixtures::get_dashpay_contract_fixture; - use dpp::tests::json_document::json_document_to_contract_with_ids; use dpp::tokens::status::TokenStatus; use dpp::tokens::token_event::TokenEvent; use dpp::tokens::token_pricing_schedule::TokenPricingSchedule; @@ -385,6 +384,10 @@ mod fixtures { "votes.contested_resource.active_polls.contract.document_type.indexes.value.contender.votes.voter", ]; + /// A DPNS-shaped contract with a contested unique index + const CONTESTED_CONTRACT: &str = + "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json"; + /// Nodes nothing reaches, so their description has not been checked /// against a real GroveDB. Empty, and meant to stay empty: whoever /// describes a node can write a fixture that creates it. The coverage test @@ -657,6 +660,19 @@ mod fixtures { None, Some(platform_version), ); + // The same contract stored with its flags, as `insert_contract` stores the system + // contracts a protocol upgrade registers; `setup_contract` stores it with none + let mut with_flags = contract.clone(); + with_flags.set_id([index as u8 + 0x81; 32].into()); + drive + .insert_contract( + &with_flags, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert the contract"); for document_type in contract.document_types().values() { for seed in 1..4 { let document = document_type @@ -666,7 +682,18 @@ mod fixtures { } } } - conformance_of(&drive, "contracts_with_documents", run); + let flags = conformance_of(&drive, "contracts_with_documents", run); + for node in [ + "contracts.contract.contract.latest", + "contracts.contract.contract.revision", + ] { + assert_eq!( + flags.get(node), + Some(&BTreeSet::from([FlagsKind::None, FlagsKind::EpochOwned])), + "expected `{node}` without flags on the contract stored without, and with the \ + contract's flags on the one stored with them", + ); + } } /// A contract whose moderators only delete documents: no list, one document type they can @@ -1138,7 +1165,7 @@ mod fixtures { let drive = setup_drive_with_initial_state_structure(Some(platform_version)); let contract = setup_contract( &drive, - "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", + CONTESTED_CONTRACT, None, None, None::, @@ -1198,27 +1225,17 @@ mod fixtures { ) .expect("expected to add the contested document"); } - conformance_of(&drive, "contested_documents", run); - } - /// A contract with a contested index stored with the contract's flags, the way - /// `insert_contract` stores the system contracts a protocol upgrade registers (the - /// moderation charters contract at 14). The trees created with it below the active - /// polls carry those flags; genesis and state transitions write none. - fn contested_index_contract_with_flags(run: &mut FixtureRun) { - let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(Some(platform_version)); - let contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", - None, - None, - false, - platform_version, - ) - .expect("expected the contract"); + // The same contract stored with its flags, as `insert_contract` stores the system + // contracts a protocol upgrade registers (the moderation charters contract at 14). The + // trees created with it below the active polls carry them; `setup_contract` writes none, + // as genesis and state transitions do. Its id sorts after the first contract's, so the + // layers recorded for the structure stay the first contract's fuller ones. + let mut with_flags = contract.clone(); + with_flags.set_id([0xee; 32].into()); drive .insert_contract( - &contract, + &with_flags, BlockInfo::default(), true, None, @@ -1226,7 +1243,7 @@ mod fixtures { ) .expect("expected to insert the contract"); - let flags = conformance_of(&drive, "contested_index_contract_with_flags", run); + let flags = conformance_of(&drive, "contested_documents", run); for node in [ "votes.contested_resource.active_polls.contract", "votes.contested_resource.active_polls.contract.document_type", @@ -1235,8 +1252,9 @@ mod fixtures { ] { assert_eq!( flags.get(node), - Some(&BTreeSet::from([FlagsKind::EpochOwned])), - "expected `{node}` to carry the contract's flags", + Some(&BTreeSet::from([FlagsKind::None, FlagsKind::EpochOwned])), + "expected `{node}` without flags on the contract stored without, and with the \ + contract's flags on the one stored with them", ); } } @@ -1560,7 +1578,6 @@ mod fixtures { token_distributions(&mut run); contract_groups_and_bound_keys(&mut run); spent_nullifiers(&mut run); - contested_index_contract_with_flags(&mut run); run } From fb4981d40343b193e8d032c5d174c2cd57035eb1 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 08:42:04 +0700 Subject: [PATCH 3/3] fix(platform)!: register the version 14 system contracts without storage 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 --- .../v0/mod.rs | 92 ++++++++++++++++++- packages/rs-drive/grovedb-structure.json | 48 ++-------- .../rs-drive/src/drive/contract/structure.rs | 10 +- .../rs-drive/src/drive/votes/structure.rs | 5 - packages/rs-drive/src/structure/tests.rs | 75 +-------------- 5 files changed, 108 insertions(+), 122 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs index 494d97af704..1ee22fbcb2e 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs @@ -736,13 +736,19 @@ impl Platform { // App-connect contract: the wallet's encrypted login response gets one system // contract id on every network from this version. Fresh // chains register it at genesis (`create_genesis_state` v2). + // + // Both contracts registered here are stored without storage flags, as genesis stores + // system contracts: nobody owns their storage, and nothing ever refunds it. + // `insert_contract`, which the upgrades to 6, 9 and 13 used, would give them and every + // tree created with them the contract's flags, owned by the all-zero system owner. let app_connect_contract = load_system_data_contract(SystemDataContract::AppConnect, platform_version)?; - self.drive.insert_contract( + self.drive.apply_contract( &app_connect_contract, *block_info, true, + None, Some(transaction), platform_version, )?; @@ -754,10 +760,11 @@ impl Platform { let moderation_charters_contract = load_system_data_contract(SystemDataContract::ModerationCharters, platform_version)?; - self.drive.insert_contract( + self.drive.apply_contract( &moderation_charters_contract, *block_info, true, + None, Some(transaction), platform_version, )?; @@ -2123,6 +2130,87 @@ mod tests { ); } + /// The system contracts the upgrade to 14 registers are stored without storage flags, as a + /// chain born at 14 stores them at genesis. The contract elements, every tree created with + /// them and, for the moderation charters contract's contested index, its trees under the + /// active polls are byte-identical on the two chains. + #[test] + fn should_store_the_version_14_system_contracts_as_a_chain_born_at_14_does() { + use drive::drive::votes::paths::vote_contested_resource_active_polls_tree_path_vec; + use drive::util::grove_operations::DirectQueryType; + + let platform_version = PlatformVersion::latest(); + let born_at_14 = TestPlatformBuilder::new() + .with_initial_protocol_version(14) + .build_with_mock_rpc() + .set_genesis_state(); + let upgraded = TestPlatformBuilder::new() + .with_initial_protocol_version(13) + .build_with_mock_rpc() + .set_genesis_state(); + + let transaction = upgraded.drive.grove.start_transaction(); + let block_info = BlockInfo { + time_ms: 1_000_000, + height: 100, + core_height: 100, + epoch: Epoch::new(1).expect("expected epoch"), + }; + upgraded + .transition_to_version_14(&block_info, &transaction, platform_version) + .expect("expected version 14 transition to succeed"); + + let element = |platform: &crate::platform_types::platform::Platform, + transaction: Option<&Transaction>, + path: &[Vec], + key: &[u8]| { + platform + .drive + .grove_get_raw( + path.into(), + key, + DirectQueryType::StatefulDirectQuery, + transaction, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to read the element") + .expect("expected the element to exist") + }; + + let contracts = vec![vec![RootTree::DataContractDocuments as u8]]; + let active_polls = vote_contested_resource_active_polls_tree_path_vec(); + for (parent, contract) in [ + (&contracts, SystemDataContract::AppConnect), + (&contracts, SystemDataContract::ModerationCharters), + (&active_polls, SystemDataContract::ModerationCharters), + ] { + let id = contract.id().to_buffer(); + let upgraded_element = element(&upgraded, Some(&transaction), parent, &id); + assert_eq!( + upgraded_element.get_flags(), + &None, + "{contract:?} is stored without storage flags under {parent:?}" + ); + assert_eq!( + element(&born_at_14, None, parent, &id), + upgraded_element, + "{contract:?} under {parent:?} differs between a chain born at version 14 and \ + one upgraded to it" + ); + + let mut root_path = parent.clone(); + root_path.push(id.to_vec()); + let diffs = collect_subtree_diffs(&born_at_14, &upgraded, &transaction, root_path); + assert!( + diffs.is_empty(), + "the trees of {contract:?} under {parent:?} differ between a chain born at \ + version 14 and one upgraded to it:\n{}", + diffs.join("\n"), + ); + } + } + #[test] fn test_transition_to_version_14_creates_total_credits_history_tree() { let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index 84b09dcb7b6..a2845ab71a4 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -2537,7 +2537,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2560,7 +2560,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "value": "serialized DataContract", "since": 1, "presence": "always", @@ -2578,11 +2578,6 @@ "kinds": [ "Reference" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "reference": "contracts.contract.contract.revision", "since": 1, "presence": "always", @@ -2605,11 +2600,6 @@ "kinds": [ "Item" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "value": "serialized DataContract", "since": 1, "presence": "always", @@ -2634,7 +2624,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2659,7 +2649,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/document/paths.rs", @@ -2688,7 +2678,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 1, "presence": "lazy", "source": "packages/rs-drive/src/drive/document/primary_key_tree_type.rs", @@ -2957,7 +2947,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 14, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -2979,7 +2969,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 14, "presence": "lazy", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -3003,7 +2993,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "since": 14, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", @@ -3072,7 +3062,7 @@ "EpochOwned", "None" ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", "value": "u32 big endian", "since": 14, "presence": "always", @@ -4072,11 +4062,6 @@ "kinds": [ "Tree" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4096,11 +4081,6 @@ "kinds": [ "Tree" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4117,11 +4097,6 @@ "kinds": [ "Tree" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", @@ -4167,11 +4142,6 @@ "kinds": [ "Tree" ], - "flags": [ - "EpochOwned", - "None" - ], - "flags_note": "The contract's flags. A protocol upgrade registering a system contract that can be deleted or is not read only writes them: the owner is the contract owner, and the epoch the one the contract was registered in. Genesis, and the state transitions that create and update contracts, write none.", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/votes/paths.rs", diff --git a/packages/rs-drive/src/drive/contract/structure.rs b/packages/rs-drive/src/drive/contract/structure.rs index b2457b791ed..32626ba4da1 100644 --- a/packages/rs-drive/src/drive/contract/structure.rs +++ b/packages/rs-drive/src/drive/contract/structure.rs @@ -10,10 +10,10 @@ use crate::structure::{ElementKind, FlagsKind, KeyEncoding, KeyMatcher, Structur const SOURCE: &str = "packages/rs-drive/src/drive/contract/paths.rs"; /// The flags of the elements written with a contract, shared by every area that describes one pub(crate) const CONTRACT_FLAGS: &str = - "The contract's flags. A protocol upgrade registering a system contract that can be \ - deleted or is not read only writes them: the owner is the contract owner, and the \ - epoch the one the contract was registered in. Genesis, and the state transitions \ - that create and update contracts, write none."; + "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 \ + and 13 registered carry them (wallet utils, token history, keyword search and document \ + history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state \ + transitions and later upgrades write none."; const REMOVAL_FLAGS: &str = "The owner is the moderator who deleted the document. They pay for the record, \ which nothing deletes or replaces."; @@ -59,7 +59,6 @@ pub(crate) fn structure() -> StructureNode { .children(vec![ StructureNode::fixed("latest", &[0], "Latest", "") .kind(ElementKind::Reference) - .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) .reference("contracts.contract.contract.revision") .describe("A sibling reference to the newest revision."), StructureNode::dynamic( @@ -71,7 +70,6 @@ pub(crate) fn structure() -> StructureNode { u64 big endian with the sign bit flipped", ) .kind(ElementKind::Item) - .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) .value("serialized DataContract") .describe("The contract as it was at that time."), ]), diff --git a/packages/rs-drive/src/drive/votes/structure.rs b/packages/rs-drive/src/drive/votes/structure.rs index 75aaf413e1c..42ef6631b51 100644 --- a/packages/rs-drive/src/drive/votes/structure.rs +++ b/packages/rs-drive/src/drive/votes/structure.rs @@ -1,4 +1,3 @@ -use crate::drive::contract::structure::CONTRACT_FLAGS; use crate::drive::votes::paths::{ ACTIVE_POLLS_TREE_KEY, CONTESTED_DOCUMENT_INDEXES_TREE_KEY, CONTESTED_DOCUMENT_STORAGE_TREE_KEY, CONTESTED_RESOURCE_TREE_KEY, END_DATE_QUERIES_TREE_KEY, @@ -191,7 +190,6 @@ fn active_polls() -> StructureNode { .child( StructureNode::identifier("contract", "contract_id", "The data contract id") .kind(ElementKind::Tree) - .flags(&OWNED, CONTRACT_FLAGS) .describe( "Created with a contract that has a contested \ index.", @@ -205,7 +203,6 @@ fn active_polls() -> StructureNode { "The document type name", ) .kind(ElementKind::Tree) - .flags(&OWNED, CONTRACT_FLAGS) .describe("A document type with a contested index.") .children(vec![ StructureNode::fixed( @@ -215,7 +212,6 @@ fn active_polls() -> StructureNode { "CONTESTED_DOCUMENT_STORAGE_TREE_KEY", ) .kind(ElementKind::Tree) - .flags(&OWNED, CONTRACT_FLAGS) .describe( "The documents competing, held here until a poll \ awards one of them.", @@ -234,7 +230,6 @@ fn active_polls() -> StructureNode { "CONTESTED_DOCUMENT_INDEXES_TREE_KEY", ) .kind(ElementKind::Tree) - .flags(&OWNED, CONTRACT_FLAGS) .describe( "The contested index. Only the values make levels \ here; property names are left out on purpose.", diff --git a/packages/rs-drive/src/structure/tests.rs b/packages/rs-drive/src/structure/tests.rs index a0cc8ccb824..8babc356afe 100644 --- a/packages/rs-drive/src/structure/tests.rs +++ b/packages/rs-drive/src/structure/tests.rs @@ -384,10 +384,6 @@ mod fixtures { "votes.contested_resource.active_polls.contract.document_type.indexes.value.contender.votes.voter", ]; - /// A DPNS-shaped contract with a contested unique index - const CONTESTED_CONTRACT: &str = - "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json"; - /// Nodes nothing reaches, so their description has not been checked /// against a real GroveDB. Empty, and meant to stay empty: whoever /// describes a node can write a fixture that creates it. The coverage test @@ -520,13 +516,8 @@ mod fixtures { } /// Checks the state against the description, and records the shape of - /// every layer below a template that is fuller here than seen so far. - /// Returns the kinds of flags found on the elements of each node. - fn conformance_of( - drive: &Drive, - fixture: &str, - run: &mut FixtureRun, - ) -> BTreeMap> { + /// every layer below a template that is fuller here than seen so far + fn conformance_of(drive: &Drive, fixture: &str, run: &mut FixtureRun) { let platform_version = PlatformVersion::latest(); let structure = drive_structure(); let report = check_conformance(drive, &structure, None, platform_version) @@ -564,7 +555,6 @@ mod fixtures { ); } run.visited.extend(report.visited); - report.flags } fn identities(run: &mut FixtureRun) { @@ -660,19 +650,6 @@ mod fixtures { None, Some(platform_version), ); - // The same contract stored with its flags, as `insert_contract` stores the system - // contracts a protocol upgrade registers; `setup_contract` stores it with none - let mut with_flags = contract.clone(); - with_flags.set_id([index as u8 + 0x81; 32].into()); - drive - .insert_contract( - &with_flags, - BlockInfo::default(), - true, - None, - platform_version, - ) - .expect("expected to insert the contract"); for document_type in contract.document_types().values() { for seed in 1..4 { let document = document_type @@ -682,18 +659,7 @@ mod fixtures { } } } - let flags = conformance_of(&drive, "contracts_with_documents", run); - for node in [ - "contracts.contract.contract.latest", - "contracts.contract.contract.revision", - ] { - assert_eq!( - flags.get(node), - Some(&BTreeSet::from([FlagsKind::None, FlagsKind::EpochOwned])), - "expected `{node}` without flags on the contract stored without, and with the \ - contract's flags on the one stored with them", - ); - } + conformance_of(&drive, "contracts_with_documents", run); } /// A contract whose moderators only delete documents: no list, one document type they can @@ -1165,7 +1131,7 @@ mod fixtures { let drive = setup_drive_with_initial_state_structure(Some(platform_version)); let contract = setup_contract( &drive, - CONTESTED_CONTRACT, + "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", None, None, None::, @@ -1225,38 +1191,7 @@ mod fixtures { ) .expect("expected to add the contested document"); } - - // The same contract stored with its flags, as `insert_contract` stores the system - // contracts a protocol upgrade registers (the moderation charters contract at 14). The - // trees created with it below the active polls carry them; `setup_contract` writes none, - // as genesis and state transitions do. Its id sorts after the first contract's, so the - // layers recorded for the structure stay the first contract's fuller ones. - let mut with_flags = contract.clone(); - with_flags.set_id([0xee; 32].into()); - drive - .insert_contract( - &with_flags, - BlockInfo::default(), - true, - None, - platform_version, - ) - .expect("expected to insert the contract"); - - let flags = conformance_of(&drive, "contested_documents", run); - for node in [ - "votes.contested_resource.active_polls.contract", - "votes.contested_resource.active_polls.contract.document_type", - "votes.contested_resource.active_polls.contract.document_type.storage", - "votes.contested_resource.active_polls.contract.document_type.indexes", - ] { - assert_eq!( - flags.get(node), - Some(&BTreeSet::from([FlagsKind::None, FlagsKind::EpochOwned])), - "expected `{node}` without flags on the contract stored without, and with the \ - contract's flags on the one stored with them", - ); - } + conformance_of(&drive, "contested_documents", run); } fn apply_operations(drive: &Drive, operations: Vec) {