Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(platform)!: transient properties #1990

Merged
merged 5 commits into from
Jul 23, 2024
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
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 struct DocumentProperty {
pub property_type: DocumentPropertyType,
pub required: bool,
pub transient: bool,
}

#[derive(Debug, PartialEq, Clone, Serialize)]
Expand Down Expand Up @@ -1199,7 +1200,7 @@
}
match self {
DocumentPropertyType::String(_) => {
if value == &vec![0] {

Check warning on line 1203 in packages/rs-dpp/src/data_contract/document_type/property/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

taken reference of right operand

warning: taken reference of right operand --> packages/rs-dpp/src/data_contract/document_type/property/mod.rs:1203:20 | 1203 | if value == &vec![0] { | ^^^^^^^^^-------- | | | help: use the right value directly: `...` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref = note: `#[warn(clippy::op_ref)]` on by default
// we don't want to collide with the definition of an empty string
Ok(Value::Text("".to_string()))
} else {
Expand Down Expand Up @@ -1290,9 +1291,9 @@
Ok(identifier.into())
}
DocumentPropertyType::Boolean => {
if value == &vec![0] {

Check warning on line 1294 in packages/rs-dpp/src/data_contract/document_type/property/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

taken reference of right operand

warning: taken reference of right operand --> packages/rs-dpp/src/data_contract/document_type/property/mod.rs:1294:20 | 1294 | if value == &vec![0] { | ^^^^^^^^^-------- | | | help: use the right value directly: `...` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
Ok(Value::Bool(false))
} else if value == &vec![1] {

Check warning on line 1296 in packages/rs-dpp/src/data_contract/document_type/property/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

taken reference of right operand

warning: taken reference of right operand --> packages/rs-dpp/src/data_contract/document_type/property/mod.rs:1296:27 | 1296 | } else if value == &vec![1] { | ^^^^^^^^^-------- | | | help: use the right value directly: `...` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
Ok(Value::Bool(true))
} else {
Err(ProtocolError::DecodingError(
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 @@
DocumentProperty {
property_type: document_type,
required,
transient: false,
}
};

Expand Down Expand Up @@ -392,24 +393,24 @@
}).collect::<serde_json::Map<String, serde_json::Value>>();

// Generate indices
let indices_json_schema = indices
.iter()
.map(|(_, index)| {
let properties_schema = index
.properties
.iter()
.map(|prop| {
// Only "asc" is allowed for now (v1.0-dev)
json!({ <std::string::String as Clone>::clone(&prop.name): "asc" })
})
.collect::<Vec<_>>();

json!({
"name": index.name,
"properties": properties_schema,
"unique": index.unique,
})
})

Check warning on line 413 in packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

iterating on a map's values

warning: iterating on a map's values --> packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs:396:35 | 396 | let indices_json_schema = indices | ___________________________________^ 397 | | .iter() 398 | | .map(|(_, index)| { 399 | | let properties_schema = index ... | 412 | | }) 413 | | }) | |______________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map = note: `#[warn(clippy::iter_kv_map)]` on by default help: try | 396 ~ let indices_json_schema = indices.values().map(|index| { 397 + let properties_schema = index 398 + .properties 399 + .iter() 400 + .map(|prop| { 401 + // Only "asc" is allowed for now (v1.0-dev) 402 + json!({ <std::string::String as Clone>::clone(&prop.name): "asc" }) 403 + }) 404 + .collect::<Vec<_>>(); 405 + 406 + json!({ 407 + "name": index.name, 408 + "properties": properties_schema, 409 + "unique": index.unique, 410 + }) 411 + }) |
.collect::<Vec<_>>();

// Combine everything into the final schema
Expand All @@ -432,6 +433,7 @@
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 @@
DocumentProperty {
property_type: document_type,
required,
transient: false,
}
};

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