Skip to content

Commit

Permalink
fix: sdk should ignore transient fields when verifying proofs (#2000)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer authored Jul 24, 2024
1 parent 799fd04 commit 5eb3e8c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::document::document_methods::DocumentGetRawForDocumentTypeV0;
use crate::document::DocumentV0Getters;
use platform_value::Value;
use std::collections::BTreeMap;

pub trait DocumentIsEqualIgnoringTimestampsV0:
DocumentV0Getters + DocumentGetRawForDocumentTypeV0
Expand All @@ -11,10 +13,31 @@ pub trait DocumentIsEqualIgnoringTimestampsV0:
/// created_at/updated_at
/// created_at_block_height/updated_at_block_height
/// created_at_core_block_height/updated_at_core_block_height
fn is_equal_ignoring_time_based_fields_v0(&self, rhs: &Self) -> bool {
fn is_equal_ignoring_time_based_fields_v0(
&self,
rhs: &Self,
also_ignore_fields: Option<Vec<&str>>,
) -> bool {
fn filtered_properties<'a>(
properties: &'a BTreeMap<String, Value>,
ignore_fields: &Vec<&str>,

Check warning on line 23 in packages/rs-dpp/src/document/document_methods/is_equal_ignoring_timestamps/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

writing `&Vec` instead of `&[_]` involves a new object where a slice will do

warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> packages/rs-dpp/src/document/document_methods/is_equal_ignoring_timestamps/v0/mod.rs:23:28 | 23 | ignore_fields: &Vec<&str>, | ^^^^^^^^^^ help: change this to: `&[&str]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg = note: `#[warn(clippy::ptr_arg)]` on by default
) -> BTreeMap<&'a String, &'a Value> {
properties
.iter()
.filter(|(key, _)| !ignore_fields.contains(&key.as_str()))
.collect()
}

let properties_equal = if let Some(fields) = &also_ignore_fields {
filtered_properties(self.properties(), fields)
== filtered_properties(rhs.properties(), fields)
} else {
self.properties() == rhs.properties()
};

self.id() == rhs.id()
&& self.owner_id() == rhs.owner_id()
&& self.properties() == rhs.properties()
&& properties_equal
&& self.revision() == rhs.revision()
}
}
1 change: 1 addition & 0 deletions packages/rs-dpp/src/document/document_methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub trait DocumentMethodsV0 {
fn is_equal_ignoring_time_based_fields(
&self,
rhs: &Self,
also_ignore_fields: Option<Vec<&str>>,
platform_version: &PlatformVersion,
) -> Result<bool, ProtocolError>;
}
4 changes: 3 additions & 1 deletion packages/rs-dpp/src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ impl DocumentMethodsV0 for Document {
fn is_equal_ignoring_time_based_fields(
&self,
rhs: &Self,
also_ignore_fields: Option<Vec<&str>>,
platform_version: &PlatformVersion,
) -> Result<bool, ProtocolError> {
match (self, rhs) {
Expand All @@ -193,7 +194,8 @@ impl DocumentMethodsV0 for Document {
.document_method_versions
.is_equal_ignoring_timestamps
{
0 => Ok(document_v0.is_equal_ignoring_time_based_fields_v0(rhs_v0)),
0 => Ok(document_v0
.is_equal_ignoring_time_based_fields_v0(rhs_v0, also_ignore_fields)),
version => Err(ProtocolError::UnknownVersionMismatch {
method: "DocumentMethodV0::is_equal_ignoring_time_based_fields".to_string(),
known_versions: vec![0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5833,10 +5833,20 @@ mod tests {
.expect("expected to get back documents")
.documents_owned();

let transient_fields = domain
.transient_fields()
.iter()
.map(|a| a.as_str())
.collect();

assert!(documents
.get(0)
.expect("expected a document")
.is_equal_ignoring_time_based_fields(&document_3, platform_version)
.is_equal_ignoring_time_based_fields(
&document_3,
Some(transient_fields),
platform_version
)
.expect("expected to run is equal"));

let drive_query = DriveDocumentQuery {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,15 @@ impl Drive {
platform_version,
)?;

let transient_fields = document_type
.transient_fields()
.iter()
.map(|a| a.as_str())
.collect();

if !document.is_equal_ignoring_time_based_fields(
&expected_document,
Some(transient_fields),
platform_version,
)? {
return Err(Error::Proof(ProofError::IncorrectProof(format!("proof of state transition execution did not contain expected document (time fields were not checked) after create with id {}", create_transition.base().id()))));
Expand All @@ -192,8 +199,15 @@ impl Drive {
platform_version,
)?;

let transient_fields = document_type
.transient_fields()
.iter()
.map(|a| a.as_str())
.collect();

if !document.is_equal_ignoring_time_based_fields(
&expected_document,
Some(transient_fields),
platform_version,
)? {
return Err(Error::Proof(ProofError::IncorrectProof(format!("proof of state transition execution did not contain expected document (time fields were not checked) after replace with id {}", replace_transition.base().id()))));
Expand Down

0 comments on commit 5eb3e8c

Please sign in to comment.