From dbd622cb647747333196c4d710b4deff3a0a094e Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 27 Sep 2026 18:34:53 +0700 Subject: [PATCH] refactor(drive): create once-per-identity claim trees in insert_contract v2 #4827 added the once-per-identity claims subtree to the token loop of insert_contract_operations_v1, which protocol versions 9-13 select. It is dead there (those versions refuse once-per-identity rules) and live at protocol version 14 only because insert_contract v2 composes v1, so new protocol version 14 behaviour sat inside a shipped generation. Move it to insert_contract_operations_v2, as #4834 already did for update_contract. The same trees are queued at protocol version 14; v1 is back to what shipped apart from the element-builder extraction v2 shares. Co-Authored-By: Claude Opus 5.5 --- .../contract/insert/insert_contract/v1/mod.rs | 15 -------- .../contract/insert/insert_contract/v2/mod.rs | 34 ++++++++++++++++++- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs index afbc243b51f..bc6062b4079 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs @@ -20,7 +20,6 @@ use crate::util::object_size_info::{DriveKeyInfo, PathKeyElementInfo}; use dpp::data_contract::accessors::v1::DataContractV1Getters; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::associated_token::token_distribution_rules::accessors::v0::TokenDistributionRulesV0Getters; -use dpp::data_contract::associated_token::token_distribution_rules::accessors::v1::TokenDistributionRulesV1Getters; use dpp::serialization::{PlatformSerializable, PlatformSerializableWithPlatformVersion}; use dpp::tokens::contract_info::TokenContractInfo; use dpp::tokens::status::TokenStatus; @@ -308,20 +307,6 @@ impl Drive { )?; } - if token_config - .distribution_rules() - .once_per_identity_distribution() - .is_some() - { - self.add_once_per_identity_distribution( - token_id.to_buffer(), - estimated_costs_only_with_layer_info, - &mut batch_operations, - transaction, - platform_version, - )?; - } - let path_holding_total_token_supply = total_tokens_root_supply_path_vec(); if token_config.base_supply() > 0 { diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v2/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v2/mod.rs index a1af8d5018e..255e85cfec8 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v2/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v2/mod.rs @@ -1,9 +1,13 @@ use crate::drive::Drive; +use crate::error::contract::DataContractError; use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use crate::util::storage_flags::StorageFlags; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::accessors::v1::DataContractV1Getters; +use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; +use dpp::data_contract::associated_token::token_distribution_rules::accessors::v1::TokenDistributionRulesV1Getters; use dpp::data_contract::config::v2::DataContractConfigGettersV2; use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}; use dpp::data_contract::DataContract; @@ -88,7 +92,9 @@ impl Drive { Ok(()) } - /// The generation 1 operations, then the moderation list trees the config declares. + /// The generation 1 operations, then the once-per-identity claims subtree of every token + /// that has a once-per-identity distribution, then the moderation list trees the config + /// declares. fn insert_contract_operations_v2( &self, contract_element: Element, @@ -113,6 +119,32 @@ impl Drive { platform_version, )?; + // The claims subtree of every token whose rules carry a once-per-identity + // distribution. Only protocol version 14 admits those rules, so generation 1, which + // protocol versions 9-13 select, does not create it. + for (token_pos, token_config) in contract.tokens() { + if token_config + .distribution_rules() + .once_per_identity_distribution() + .is_none() + { + continue; + } + let token_id = contract.token_id(*token_pos).ok_or(Error::DataContract( + DataContractError::CorruptedDataContract(format!( + "data contract has a token at position {}, but can not find it", + token_pos + )), + ))?; + self.add_once_per_identity_distribution( + token_id.to_buffer(), + estimated_costs_only_with_layer_info, + &mut batch_operations, + transaction, + platform_version, + )?; + } + if let Some(moderation) = contract.config().moderation() { self.insert_contract_moderation_trees_operations( contract.id().to_buffer(),