diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 10091afae51..4a22b6dd8cd 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -49,7 +49,7 @@ serde_repr = { version = "0.1.7" } sha2 = { version = "0.10" } thiserror = { version = "2.0.12" } data-contracts = { path = "../data-contracts", optional = true } -platform-value = { path = "../rs-platform-value" } +platform-value = { path = "../rs-platform-value", features = ["json"] } platform-version = { path = "../rs-platform-version" } platform-versioning = { path = "../rs-platform-versioning" } platform-serialization = { path = "../rs-platform-serialization" } diff --git a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs index c9144dfa7c7..bc6fd6e5ca7 100644 --- a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs @@ -4,6 +4,7 @@ use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; use crate::block::epoch::EpochIndex; use crate::data_contract::associated_token::token_configuration::TokenConfiguration; +use crate::data_contract::group::v0::GroupV0; use crate::data_contract::group::Group; use crate::data_contract::v0::DataContractV0; use crate::data_contract::v1::DataContractV1; @@ -15,6 +16,7 @@ use crate::prelude::BlockHeight; use bincode::{Decode, Encode}; use platform_value::{Identifier, Value}; use serde::{Deserialize, Serialize}; +use serde_json::Value as JsonValue; use std::collections::BTreeMap; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] @@ -69,21 +71,59 @@ pub struct DataContractInSerializationFormatV1 { pub description: Option, } +/// Deserialize `groups` map with stringified u16 keys and enum-wrapped `Group` values. +/// +/// Accepts: +/// ```json +/// { +/// "0": { +/// "V0": { +/// "members": { "...": 1 }, +/// "required_power": 3 +/// } +/// } +/// } +/// ``` fn deserialize_u16_group_map<'de, D>( deserializer: D, ) -> Result, D::Error> where D: serde::Deserializer<'de>, { - let map: BTreeMap = BTreeMap::deserialize(deserializer)?; - map.into_iter() - .map(|(k, v)| { - k.parse::() - .map_err(serde::de::Error::custom) - .map(|key| (key, v)) - }) - .collect() + let map: BTreeMap = BTreeMap::deserialize(deserializer)?; + + let mut out = BTreeMap::new(); + + for (key_str, group_value) in map { + let key = key_str.parse::().map_err(|e| { + serde::de::Error::custom(format!("invalid group key '{}': {}", key_str, e)) + })?; + + let group_obj = group_value.into_btree_string_map().map_err(|e| { + serde::de::Error::custom(format!("invalid group structure at '{}': {}", key_str, e)) + })?; + + let v0_value = group_obj.get("V0").ok_or_else(|| { + serde::de::Error::custom(format!("missing 'V0' variant under group '{}'", key_str)) + })?; + + let v0_json: JsonValue = v0_value.clone().try_into_validating_json().map_err(|e| { + serde::de::Error::custom(format!("failed to convert to json at '{}': {}", key_str, e)) + })?; + + let group_v0: GroupV0 = serde_json::from_value(v0_json).map_err(|e| { + serde::de::Error::custom(format!( + "failed to deserialize GroupV0 at '{}': {}", + key_str, e + )) + })?; + + out.insert(key, Group::V0(group_v0)); + } + + Ok(out) } + fn deserialize_u16_token_configuration_map<'de, D>( deserializer: D, ) -> Result, D::Error>