Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions packages/rs-dpp/src/data_contract/conversion/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ impl Serialize for DataContract {
where
S: Serializer,
{
let current_version =
PlatformVersion::get_current().map_err(|e| serde::ser::Error::custom(e.to_string()))?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::ser::Error::custom(e.to_string()))?;
Comment on lines +14 to +15
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Serialize, mapping the platform-version resolution error to e.to_string() drops useful context about what failed (platform version resolution vs contract conversion). Consider wrapping the error with a brief prefix so debugging serde failures is easier.

Suggested change
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::ser::Error::custom(e.to_string()))?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None).map_err(
|e| {
serde::ser::Error::custom(format!(
"failed to resolve platform version for data contract serialization: {}",
e
))
},
)?;

Copilot uses AI. Check for mistakes.
let data_contract_in_serialization_format: DataContractInSerializationFormat = self
.try_into_platform_versioned(current_version)
.map_err(|e: ProtocolError| serde::ser::Error::custom(format!("expected to be able to serialize data contract into its serialized version: {}", e)))?;
Expand All @@ -26,12 +26,8 @@ impl<'de> Deserialize<'de> for DataContract {
D: Deserializer<'de>,
{
let serialization_format = DataContractInSerializationFormat::deserialize(deserializer)?;
let current_version = PlatformVersion::get_current().map_err(|e| {
serde::de::Error::custom(format!(
"expected to be able to get current platform version: {}",
e
))
})?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
Comment on lines +29 to +30
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Deserialize, the new serde::de::Error::custom(e.to_string()) loses the prior contextual message about failing to resolve the platform version. Please add a short context prefix (e.g., "failed to resolve platform version for DataContract deserialization") to make serde errors more diagnosable.

Suggested change
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None).map_err(
|e| {
serde::de::Error::custom(format!(
"failed to resolve platform version for DataContract deserialization: {}",
e
))
},
)?;

Copilot uses AI. Check for mistakes.
// when deserializing from json/platform_value/cbor we always want to validate (as this is not coming from the state)
DataContract::try_from_platform_versioned(
serialization_format,
Expand Down
33 changes: 27 additions & 6 deletions packages/rs-dpp/src/data_contract/v0/serialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@ impl<'de> Deserialize<'de> for DataContractV0 {
D: Deserializer<'de>,
{
let serialization_format = DataContractInSerializationFormatV0::deserialize(deserializer)?;
let current_version = PlatformVersion::get_current().map_err(|e| {
serde::de::Error::custom(format!(
"expected to be able to get current platform version: {}",
e
))
})?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
Comment thread
lklimek marked this conversation as resolved.
// when deserializing from json/platform_value/cbor we always want to validate (as this is not coming from the state)
DataContractV0::try_from_platform_versioned_v0(
serialization_format,
Expand Down Expand Up @@ -192,4 +188,29 @@ mod tests {
.expect("expected to deserialize state transition");
assert_eq!(contract, recovered_contract);
}

#[test]
#[cfg(feature = "random-identities")]
fn data_contract_v0_serde_json_roundtrip() {
use crate::data_contract::accessors::v0::DataContractV0Getters;
use crate::data_contract::v0::DataContractV0;

let platform_version = PlatformVersion::first();
let identity = Identity::random_identity(5, Some(5), platform_version)
.expect("expected a random identity");
let contract =
get_data_contract_fixture(Some(identity.id()), 0, platform_version.protocol_version)
.data_contract_owned();
let v0 = contract.into_v0().expect("expected V0 contract");

let json = serde_json::to_string(&v0).expect("expected to serialize to JSON");
let recovered: DataContractV0 =
serde_json::from_str(&json).expect("expected to deserialize from JSON");

// Schema normalization during deserialization means full equality may differ;
// verify stable identity fields to confirm a successful roundtrip.
assert_eq!(v0.id(), recovered.id());
assert_eq!(v0.owner_id(), recovered.owner_id());
assert_eq!(v0.version(), recovered.version());
}
}
34 changes: 28 additions & 6 deletions packages/rs-dpp/src/data_contract/v1/serialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,8 @@ impl<'de> Deserialize<'de> for DataContractV1 {
D: Deserializer<'de>,
{
let serialization_format = DataContractInSerializationFormatV1::deserialize(deserializer)?;
let current_version = PlatformVersion::get_current().map_err(|e| {
serde::de::Error::custom(format!(
"expected to be able to get current platform version: {}",
e
))
})?;
let current_version = PlatformVersion::get_version_or_current_or_latest(None)
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
Comment thread
lklimek marked this conversation as resolved.
// when deserializing from json/platform_value/cbor we always want to validate (as this is not coming from the state)
DataContractV1::try_from_platform_versioned_v1(
serialization_format,
Expand Down Expand Up @@ -222,4 +218,30 @@ mod tests {
.expect("expected to deserialize state transition");
assert_eq!(contract, recovered_contract);
}

#[test]
#[cfg(feature = "random-identities")]
fn data_contract_v1_serde_json_roundtrip() {
use crate::data_contract::accessors::v0::DataContractV0Getters;
use crate::data_contract::DataContractV1;

// V1 contracts are first produced at platform version 9
let platform_version = PlatformVersion::get(9).expect("expected protocol version 9");
let identity = Identity::random_identity(5, Some(5), platform_version)
.expect("expected a random identity");
let contract =
get_data_contract_fixture(Some(identity.id()), 0, platform_version.protocol_version)
.data_contract_owned();
let v1 = contract.into_v1().expect("expected V1 contract");

let json = serde_json::to_string(&v1).expect("expected to serialize to JSON");
let recovered: DataContractV1 =
serde_json::from_str(&json).expect("expected to deserialize from JSON");

// Schema normalization during deserialization means full equality may differ;
// verify stable identity fields to confirm a successful roundtrip.
assert_eq!(v1.id(), recovered.id());
assert_eq!(v1.owner_id(), recovered.owner_id());
assert_eq!(v1.version(), recovered.version());
}
}
Loading
Loading