Skip to content

Commit

Permalink
feat(platform)!: transient properties (#1990)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer authored Jul 23, 2024
1 parent 319c597 commit 2facc4d
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 15 deletions.
3 changes: 3 additions & 0 deletions packages/dpns-contract/schema/v1/dpns-contract-documents.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
"records",
"subdomainRules"
],
"transient": [
"preorderSalt"
],
"additionalProperties": false,
"$comment": "In order to register a domain you need to create a preorder. The preorder step is needed to prevent man-in-the-middle attacks. normalizedLabel + '.' + normalizedParentDomain must not be longer than 253 chars length as defined by RFC 1035. Domain documents are immutable: modification and deletion are restricted"
},
Expand Down
42 changes: 42 additions & 0 deletions packages/platform-test-suite/test/e2e/dpns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,28 @@ describe('DPNS', () => {
const rawDocument = documents[0].toObject();

delete rawDocument.$createdAt;
delete rawDocument.$createdAtCoreBlockHeight;
delete rawDocument.$createdAtBlockHeight;
delete rawDocument.$updatedAt;
delete rawDocument.$updatedAtCoreBlockHeight;
delete rawDocument.$updatedAtBlockHeight;
delete rawDocument.$transferredAt;
delete rawDocument.$transferredAtCoreBlockHeight;
delete rawDocument.$transferredAtBlockHeight;
delete rawDocument.preorderSalt;

const rawRegisteredDomain = registeredDomain.toObject();

delete rawRegisteredDomain.$createdAt;
delete rawRegisteredDomain.$createdAtCoreBlockHeight;
delete rawRegisteredDomain.$createdAtBlockHeight;
delete rawRegisteredDomain.$updatedAt;
delete rawRegisteredDomain.$updatedAtCoreBlockHeight;
delete rawRegisteredDomain.$updatedAtBlockHeight;
delete rawRegisteredDomain.$transferredAt;
delete rawRegisteredDomain.$transferredAtCoreBlockHeight;
delete rawRegisteredDomain.$transferredAtBlockHeight;
delete rawRegisteredDomain.preorderSalt;

expect(rawDocument).to.deep.equal(rawRegisteredDomain);
});
Expand All @@ -238,14 +252,28 @@ describe('DPNS', () => {
const rawDocument = document.toObject();

delete rawDocument.$createdAt;
delete rawDocument.$createdAtCoreBlockHeight;
delete rawDocument.$createdAtBlockHeight;
delete rawDocument.$updatedAt;
delete rawDocument.$updatedAtCoreBlockHeight;
delete rawDocument.$updatedAtBlockHeight;
delete rawDocument.$transferredAt;
delete rawDocument.$transferredAtCoreBlockHeight;
delete rawDocument.$transferredAtBlockHeight;
delete rawDocument.preorderSalt;

const rawRegisteredDomain = registeredDomain.toObject();

delete rawRegisteredDomain.$createdAt;
delete rawRegisteredDomain.$createdAtCoreBlockHeight;
delete rawRegisteredDomain.$createdAtBlockHeight;
delete rawRegisteredDomain.$updatedAt;
delete rawRegisteredDomain.$updatedAtCoreBlockHeight;
delete rawRegisteredDomain.$updatedAtBlockHeight;
delete rawRegisteredDomain.$transferredAt;
delete rawRegisteredDomain.$transferredAtCoreBlockHeight;
delete rawRegisteredDomain.$transferredAtBlockHeight;
delete rawRegisteredDomain.preorderSalt;

expect(rawDocument).to.deep.equal(rawRegisteredDomain);
});
Expand All @@ -259,14 +287,28 @@ describe('DPNS', () => {
const rawDocument = document.toObject();

delete rawDocument.$createdAt;
delete rawDocument.$createdAtCoreBlockHeight;
delete rawDocument.$createdAtBlockHeight;
delete rawDocument.$updatedAt;
delete rawDocument.$updatedAtCoreBlockHeight;
delete rawDocument.$updatedAtBlockHeight;
delete rawDocument.$transferredAt;
delete rawDocument.$transferredAtCoreBlockHeight;
delete rawDocument.$transferredAtBlockHeight;
delete rawDocument.preorderSalt;

const rawRegisteredDomain = registeredDomain.toObject();

delete rawRegisteredDomain.$createdAt;
delete rawRegisteredDomain.$createdAtCoreBlockHeight;
delete rawRegisteredDomain.$createdAtBlockHeight;
delete rawRegisteredDomain.$updatedAt;
delete rawRegisteredDomain.$updatedAtCoreBlockHeight;
delete rawRegisteredDomain.$updatedAtBlockHeight;
delete rawRegisteredDomain.$transferredAt;
delete rawRegisteredDomain.$transferredAtCoreBlockHeight;
delete rawRegisteredDomain.$transferredAtBlockHeight;
delete rawRegisteredDomain.preorderSalt;

expect(rawDocument).to.deep.equal(rawRegisteredDomain);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,12 @@
"minProperties": 1,
"maxProperties": 100
},
"transient": {
"type": "array",
"items": {
"type": "string"
}
},
"additionalProperties": {
"type": "boolean",
"const": false
Expand Down
18 changes: 18 additions & 0 deletions packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ impl DocumentTypeV0Getters for DocumentType {
}
}

fn transient_fields(&self) -> &BTreeSet<String> {
match self {
DocumentType::V0(v0) => v0.transient_fields(),
}
}

fn documents_keep_history(&self) -> bool {
match self {
DocumentType::V0(v0) => v0.documents_keep_history(),
Expand Down Expand Up @@ -205,6 +211,12 @@ impl<'a> DocumentTypeV0Getters for DocumentTypeRef<'a> {
}
}

fn transient_fields(&self) -> &BTreeSet<String> {
match self {
DocumentTypeRef::V0(v0) => v0.transient_fields(),
}
}

fn documents_keep_history(&self) -> bool {
match self {
DocumentTypeRef::V0(v0) => v0.documents_keep_history(),
Expand Down Expand Up @@ -333,6 +345,12 @@ impl<'a> DocumentTypeV0Getters for DocumentTypeMutRef<'a> {
}
}

fn transient_fields(&self) -> &BTreeSet<String> {
match self {
DocumentTypeMutRef::V0(v0) => v0.transient_fields(),
}
}

fn documents_keep_history(&self) -> bool {
match self {
DocumentTypeMutRef::V0(v0) => v0.documents_keep_history(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ pub trait DocumentTypeV0Getters {
/// Returns the required fields of the document type.
fn required_fields(&self) -> &BTreeSet<String>;

/// Returns the transient fields of the document type.
/// Transient fields are fields that should be stripped from the document before storage.
fn transient_fields(&self) -> &BTreeSet<String>;

/// Returns the documents keep history flag of the document type.
fn documents_keep_history(&self) -> bool;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,21 @@ impl DocumentTypeV0 {
property_names::REQUIRED,
);

let transient_fields = Value::inner_recursive_optional_array_of_strings(
schema_map,
"".to_string(),
property_names::PROPERTIES,
property_names::TRANSIENT,
);

// Based on the property name, determine the type
for (property_key, property_value) in property_values {
// TODO: It's very inefficient. It must be done in one iteration and flattened properties
// must keep a reference? We even could keep only one collection
insert_values(
&mut flattened_document_properties,
&required_fields,
&transient_fields,
None,
property_key.clone(),
property_value,
Expand All @@ -268,6 +276,7 @@ impl DocumentTypeV0 {
insert_values_nested(
&mut document_properties,
&required_fields,
&transient_fields,
property_key,
property_value,
&root_schema,
Expand Down Expand Up @@ -558,6 +567,7 @@ impl DocumentTypeV0 {
identifier_paths,
binary_paths,
required_fields,
transient_fields,
documents_keep_history,
documents_mutable,
documents_can_be_deleted,
Expand All @@ -577,6 +587,7 @@ impl DocumentTypeV0 {
fn insert_values(
document_properties: &mut IndexMap<String, DocumentProperty>,
known_required: &BTreeSet<String>,
known_transient: &BTreeSet<String>,
prefix: Option<String>,
property_key: String,
property_value: &Value,
Expand All @@ -602,6 +613,7 @@ fn insert_values(
let type_value = inner_properties.get_str(property_names::TYPE)?;

let is_required = known_required.contains(&prefixed_property_key);
let is_transient = known_transient.contains(&prefixed_property_key);
let field_type: DocumentPropertyType;

match type_value {
Expand Down Expand Up @@ -645,6 +657,7 @@ fn insert_values(
DocumentProperty {
property_type: field_type,
required: is_required,
transient: is_transient,
},
);
}
Expand Down Expand Up @@ -686,6 +699,7 @@ fn insert_values(
DocumentProperty {
property_type: field_type,
required: is_required,
transient: is_transient,
},
);
}
Expand All @@ -698,6 +712,7 @@ fn insert_values(
DocumentProperty {
property_type: field_type,
required: is_required,
transient: is_transient,
},
);
}
Expand All @@ -709,6 +724,7 @@ fn insert_values(
fn insert_values_nested(
document_properties: &mut IndexMap<String, DocumentProperty>,
known_required: &BTreeSet<String>,
known_transient: &BTreeSet<String>,
property_key: String,
property_value: &Value,
root_schema: &Value,
Expand All @@ -725,6 +741,8 @@ fn insert_values_nested(

let is_required = known_required.contains(&property_key);

let is_transient = known_transient.contains(&property_key);

let field_type = match type_value {
"integer" => DocumentPropertyType::I64,
"number" => DocumentPropertyType::F64,
Expand Down Expand Up @@ -800,6 +818,17 @@ fn insert_values_nested(
})
.collect();

let stripped_transient: BTreeSet<String> = known_transient
.iter()
.filter_map(|key| {
if key.starts_with(&property_key) && key.len() > property_key.len() {
Some(key[property_key.len() + 1..].to_string())
} else {
None
}
})
.collect();

for (object_property_key, object_property_value) in properties.iter() {
let object_property_string = object_property_key
.as_text()
Expand All @@ -811,6 +840,7 @@ fn insert_values_nested(
insert_values_nested(
&mut nested_properties,
&stripped_required,
&stripped_transient,
object_property_string,
object_property_value,
root_schema,
Expand All @@ -822,6 +852,7 @@ fn insert_values_nested(
DocumentProperty {
property_type: DocumentPropertyType::Object(nested_properties),
required: is_required,
transient: is_transient,
},
);
return Ok(());
Expand All @@ -834,6 +865,7 @@ fn insert_values_nested(
DocumentProperty {
property_type: field_type,
required: is_required,
transient: is_transient,
},
);

Expand Down
1 change: 1 addition & 0 deletions packages/rs-dpp/src/data_contract/document_type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ mod property_names {
pub const PROPERTIES: &str = "properties";
pub const POSITION: &str = "position";
pub const REQUIRED: &str = "required";
pub const TRANSIENT: &str = "transient";
pub const TYPE: &str = "type";
pub const REF: &str = "$ref";
pub const CREATED_AT: &str = "$createdAt";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod array;
pub struct DocumentProperty {
pub property_type: DocumentPropertyType,
pub required: bool,
pub transient: bool,
}

#[derive(Debug, PartialEq, Clone, Serialize)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ impl DocumentTypeV0Getters for DocumentTypeV0 {
fn required_fields(&self) -> &BTreeSet<String> {
&self.required_fields
}
fn transient_fields(&self) -> &BTreeSet<String> {
&self.transient_fields
}

fn documents_keep_history(&self) -> bool {
self.documents_keep_history
Expand Down
2 changes: 2 additions & 0 deletions packages/rs-dpp/src/data_contract/document_type/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub struct DocumentTypeV0 {
pub(in crate::data_contract) binary_paths: BTreeSet<String>,
/// The required fields on the document type
pub(in crate::data_contract) required_fields: BTreeSet<String>,
/// The transient fields on the document type
pub(in crate::data_contract) transient_fields: BTreeSet<String>,
/// Should documents keep history?
pub(in crate::data_contract) documents_keep_history: bool,
/// Are documents mutable?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ impl DocumentTypeV0 {
DocumentProperty {
property_type: document_type,
required,
transient: false,
}
};

Expand Down Expand Up @@ -432,6 +433,7 @@ impl DocumentTypeV0 {
identifier_paths,
binary_paths,
required_fields,
transient_fields: Default::default(),
documents_keep_history,
documents_mutable,
documents_can_be_deleted,
Expand Down Expand Up @@ -520,6 +522,7 @@ impl DocumentTypeV0 {
DocumentProperty {
property_type: document_type,
required,
transient: false,
}
};

Expand Down Expand Up @@ -605,6 +608,7 @@ impl DocumentTypeV0 {
identifier_paths,
binary_paths,
required_fields,
transient_fields: Default::default(),
documents_keep_history,
documents_mutable,
documents_can_be_deleted,
Expand Down
Loading

0 comments on commit 2facc4d

Please sign in to comment.